Skip to content

Commit cdcc74b

Browse files
authored
Merge pull request #1270 from psgreco/master-trim-headers-v2
Restore full functionality to trim_headers (untrim)
2 parents a4d7ac7 + eed85dc commit cdcc74b

20 files changed

+501
-127
lines changed

src/bench/rpc_blockchain.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
namespace {
1616

1717
struct TestBlockAndIndex {
18-
const std::unique_ptr<const TestingSetup> testing_setup{MakeNoLogFileContext<const TestingSetup>(CBaseChainParams::MAIN)};
18+
std::unique_ptr<TestingSetup> testing_setup{MakeNoLogFileContext<TestingSetup>(CBaseChainParams::MAIN)};
1919
CBlock block{};
2020
uint256 blockHash{};
2121
CBlockIndex blockindex{};
@@ -28,6 +28,7 @@ struct TestBlockAndIndex {
2828

2929
stream >> block;
3030

31+
CBlockIndex::SetNodeContext(&(testing_setup->m_node));
3132
blockHash = block.GetHash();
3233
blockindex.phashBlock = &blockHash;
3334
blockindex.nBits = 403014710;

src/chain.cpp

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

66
#include <chain.h>
77
#include <util/time.h>
8+
#include <validation.h>
9+
#include <node/context.h>
10+
11+
12+
node::NodeContext *CBlockIndex::m_pcontext;
813

914
std::string CBlockFileInfo::ToString() const
1015
{
@@ -51,6 +56,27 @@ CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
5156
return CBlockLocator(vHave);
5257
}
5358

59+
void CBlockIndex::untrim() EXCLUSIVE_LOCKS_REQUIRED(::cs_main){
60+
AssertLockHeld(::cs_main);
61+
if (!trimmed())
62+
return;
63+
CBlockIndex tmp;
64+
const CBlockIndex *pindexfull = untrim_to(&tmp);
65+
assert(pindexfull!=this);
66+
m_trimmed = false;
67+
set_stored();
68+
proof = pindexfull->proof;
69+
m_dynafed_params = pindexfull->m_dynafed_params;
70+
m_signblock_witness = pindexfull->m_signblock_witness;
71+
m_pcontext->chainman->m_blockman.m_dirty_blockindex.insert(this);
72+
}
73+
74+
const CBlockIndex *CBlockIndex::untrim_to(CBlockIndex *pindexNew) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
75+
{
76+
AssertLockHeld(::cs_main);
77+
return m_pcontext->chainman->m_blockman.m_block_tree_db->RegenerateFullIndex(this, pindexNew);
78+
}
79+
5480
const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
5581
if (pindex == nullptr) {
5682
return nullptr;

src/chain.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
#include <vector>
1818

19+
namespace node {
20+
struct NodeContext;
21+
}
1922
/**
2023
* Maximum amount of time that a block timestamp is allowed to exceed the
2124
* current network-adjusted time before the block will be accepted.
@@ -215,26 +218,41 @@ class CBlockIndex
215218

216219
bool m_trimmed{false};
217220
bool m_trimmed_dynafed_block{false};
221+
bool m_stored_lvl{false};
218222

219223
friend class CBlockTreeDB;
220224

225+
static node::NodeContext *m_pcontext;
226+
221227
public:
228+
static void SetNodeContext(node::NodeContext *context) {m_pcontext = context;};
222229

223230
// Irrevocably remove blocksigning and dynafed-related stuff from this
224231
// in-memory copy of the block header.
225-
void trim() {
232+
bool trim() {
226233
assert_untrimmed();
234+
if (!m_stored_lvl) {
235+
// We can't trim in-memory data if it's not on disk yet, but we can if it's already been recovered once
236+
return false;
237+
}
227238
m_trimmed = true;
228239
m_trimmed_dynafed_block = !m_dynafed_params.value().IsNull();
229240
proof = std::nullopt;
230241
m_dynafed_params = std::nullopt;
231242
m_signblock_witness = std::nullopt;
243+
return true;
232244
}
233245

246+
void untrim();
247+
const CBlockIndex * untrim_to(CBlockIndex *pindexNew) const;
248+
234249
inline bool trimmed() const {
235250
return m_trimmed;
236251
}
237252

253+
inline void set_stored() {
254+
m_stored_lvl = true;
255+
}
238256
inline void assert_untrimmed() const {
239257
assert(!m_trimmed);
240258
}
@@ -501,6 +519,9 @@ class CDiskBlockIndex : public CBlockIndex
501519

502520
// For compatibility with elements 0.14 based chains
503521
if (g_signed_blocks) {
522+
if (!ser_action.ForRead()) {
523+
obj.assert_untrimmed();
524+
}
504525
if (is_dyna) {
505526
READWRITE(obj.m_dynafed_params.value());
506527
READWRITE(obj.m_signblock_witness.value().stack);

src/dynafed.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11

22
#include <dynafed.h>
33
#include <hash.h>
4+
#include <validation.h>
5+
#include <node/context.h>
46

57
bool NextBlockIsParameterTransition(const CBlockIndex* pindexPrev, const Consensus::Params& consensus, DynaFedParamEntry& winning_entry)
68
{
@@ -15,6 +17,10 @@ bool NextBlockIsParameterTransition(const CBlockIndex* pindexPrev, const Consens
1517
for (int32_t height = next_height - 1; height >= (int32_t)(next_height - consensus.dynamic_epoch_length); --height) {
1618
const CBlockIndex* p_epoch_walk = pindexPrev->GetAncestor(height);
1719
assert(p_epoch_walk);
20+
if (node::fTrimHeaders) {
21+
LOCK(cs_main);
22+
ForceUntrimHeader(p_epoch_walk);
23+
}
1824
const DynaFedParamEntry& proposal = p_epoch_walk->dynafed_params().m_proposed;
1925
const uint256 proposal_root = proposal.CalculateRoot();
2026
vote_tally[proposal_root]++;
@@ -60,6 +66,10 @@ DynaFedParamEntry ComputeNextBlockFullCurrentParameters(const CBlockIndex* pinde
6066
// may be pre-dynafed params
6167
const CBlockIndex* p_epoch_start = pindexPrev->GetAncestor(epoch_start_height);
6268
assert(p_epoch_start);
69+
if (node::fTrimHeaders) {
70+
LOCK(cs_main);
71+
ForceUntrimHeader(p_epoch_start);
72+
}
6373
if (p_epoch_start->dynafed_params().IsNull()) {
6474
// We need to construct the "full" current parameters of pre-dynafed
6575
// consensus
@@ -93,6 +103,10 @@ DynaFedParamEntry ComputeNextBlockCurrentParameters(const CBlockIndex* pindexPre
93103
{
94104
assert(pindexPrev);
95105

106+
if (node::fTrimHeaders) {
107+
LOCK(cs_main);
108+
ForceUntrimHeader(pindexPrev);
109+
}
96110
DynaFedParamEntry entry = ComputeNextBlockFullCurrentParameters(pindexPrev, consensus);
97111

98112
uint32_t next_height = pindexPrev->nHeight+1;

src/init.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,13 +1011,13 @@ bool AppInitParameterInteraction(const ArgsManager& args)
10111011
}
10121012

10131013
if (args.GetBoolArg("-trim_headers", false)) {
1014-
LogPrintf("Configured for header-trimming mode. This will reduce memory usage substantially, but we will be unable to serve as a full P2P peer, and certain header fields may be missing from JSON RPC output.\n");
1014+
LogPrintf("Configured for header-trimming mode. This will reduce memory usage substantially, but will increase IO usage when the headers need to be temporarily untrimmed.\n");
10151015
node::fTrimHeaders = true;
10161016
// This calculation is driven by GetValidFedpegScripts in pegins.cpp, which walks the chain
10171017
// back to current epoch start, and then an additional total_valid_epochs on top of that.
10181018
// We add one epoch here for the current partial epoch, and then another one for good luck.
10191019

1020-
node::nMustKeepFullHeaders = (chainparams.GetConsensus().total_valid_epochs + 2) * epoch_length;
1020+
node::nMustKeepFullHeaders = chainparams.GetConsensus().total_valid_epochs * epoch_length;
10211021
// This is the number of headers we can have in flight downloading at a time, beyond the
10221022
// set of blocks we've already validated. Capping this is necessary to keep memory usage
10231023
// bounded during IBD.
@@ -1243,6 +1243,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
12431243
const ArgsManager& args = *Assert(node.args);
12441244
const CChainParams& chainparams = Params();
12451245

1246+
CBlockIndex::SetNodeContext(&node);
12461247
auto opt_max_upload = ParseByteUnits(args.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET), ByteUnit::M);
12471248
if (!opt_max_upload) {
12481249
return InitError(strprintf(_("Unable to parse -maxuploadtarget: '%s'"), args.GetArg("-maxuploadtarget", "")));
@@ -1712,7 +1713,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
17121713

17131714
// if pruning, unset the service bit and perform the initial blockstore prune
17141715
// after any wallet rescanning has taken place.
1715-
if (fPruneMode || node::fTrimHeaders) {
1716+
if (fPruneMode) {
17161717
LogPrintf("Unsetting NODE_NETWORK on prune mode\n");
17171718
nLocalServices = ServiceFlags(nLocalServices & ~NODE_NETWORK);
17181719
if (!fReindex) {
@@ -1724,11 +1725,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
17241725
}
17251726
}
17261727

1727-
if (node::fTrimHeaders) {
1728-
LogPrintf("Unsetting NODE_NETWORK_LIMITED on header trim mode\n");
1729-
nLocalServices = ServiceFlags(nLocalServices & ~NODE_NETWORK_LIMITED);
1730-
}
1731-
17321728
// ********************************************************* Step 11: import blocks
17331729

17341730
if (!CheckDiskSpace(gArgs.GetDataDirNet())) {

src/net_processing.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3305,12 +3305,13 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
33053305
for (; pindex; pindex = m_chainman.ActiveChain().Next(pindex))
33063306
{
33073307
if (pindex->trimmed()) {
3308-
// For simplicity, if any of the headers they're asking for are trimmed,
3309-
// just drop the request.
3310-
LogPrint(BCLog::NET, "%s: ignoring getheaders from peer=%i which would return at least one trimmed header\n", __func__, pfrom.GetId());
3311-
return;
3308+
// Header is trimmed, reload from disk before sending
3309+
CBlockIndex tmpBlockIndexFull;
3310+
const CBlockIndex* pindexfull = pindex->untrim_to(&tmpBlockIndexFull);
3311+
vHeaders.push_back(pindexfull->GetBlockHeader());
3312+
} else {
3313+
vHeaders.push_back(pindex->GetBlockHeader());
33123314
}
3313-
vHeaders.push_back(pindex->GetBlockHeader());
33143315
if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
33153316
break;
33163317
}

src/node/blockstorage.cpp

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -223,15 +223,7 @@ bool BlockManager::LoadBlockIndex(
223223
{
224224
int trim_below_height = 0;
225225
if (fTrimHeaders) {
226-
int max_height = 0;
227-
if (!m_block_tree_db->WalkBlockIndexGutsForMaxHeight(&max_height)) {
228-
LogPrintf("LoadBlockIndex: Failed to WalkBlockIndexGutsForMaxHeight.\n");
229-
return false;
230-
}
231-
232-
int must_keep_headers = (consensus_params.total_valid_epochs + 2) * consensus_params.dynamic_epoch_length;
233-
int extra_headers_buffer = consensus_params.dynamic_epoch_length * 2; // XXX arbitrary
234-
trim_below_height = max_height - must_keep_headers - extra_headers_buffer;
226+
trim_below_height = std::numeric_limits<int>::max();
235227
}
236228
if (!m_block_tree_db->LoadBlockIndexGuts(consensus_params, [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); }, trim_below_height)) {
237229
return false;
@@ -337,6 +329,9 @@ bool BlockManager::LoadBlockIndex(
337329
}
338330
}
339331

332+
if (pindexBestHeader) {
333+
ForceUntrimHeader(pindexBestHeader);
334+
}
340335
return true;
341336
}
342337

@@ -803,23 +798,6 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus
803798
return true;
804799
}
805800

806-
bool ReadBlockHeaderFromDisk(CBlockHeader& header, const CBlockIndex* pindex, const Consensus::Params& consensusParams)
807-
{
808-
// Not very efficient: read a block and throw away all but the header.
809-
CBlock tmp;
810-
if (!ReadBlockFromDisk(tmp, pindex, consensusParams)) {
811-
return false;
812-
}
813-
const FlatFilePos block_pos{WITH_LOCK(cs_main, return pindex->GetBlockPos())};
814-
815-
header = tmp.GetBlockHeader();
816-
if (tmp.GetHash() != pindex->GetBlockHash()) {
817-
return error("ReadBlockheaderFromDisk(CBlockHeader&, CBlockIndex*): GetHash() doesn't match index for %s at %s",
818-
pindex->ToString(), block_pos.ToString());
819-
}
820-
return true;
821-
}
822-
823801
bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start)
824802
{
825803
FlatFilePos hpos = pos;

src/node/blockstorage.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class BlockManager
7676
{
7777
friend CChainState;
7878
friend ChainstateManager;
79+
friend CBlockIndex;
7980

8081
private:
8182
void FlushBlockFile(bool fFinalize = false, bool finalize_undo = false);
@@ -193,7 +194,6 @@ bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::P
193194
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams);
194195
bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start);
195196
// ELEMENTS:
196-
bool ReadBlockHeaderFromDisk(class CBlockHeader& header, const CBlockIndex* pindex, const Consensus::Params& consensusParams);
197197

198198
bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex);
199199

src/pegins.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
// ELEMENTS
2727
//
2828

29+
#include <validation.h>
30+
2931
namespace {
3032
static secp256k1_context* secp256k1_ctx_validation;
3133

@@ -487,6 +489,10 @@ std::vector<std::pair<CScript, CScript>> GetValidFedpegScripts(const CBlockIndex
487489
break;
488490
}
489491

492+
if (node::fTrimHeaders) {
493+
LOCK(cs_main);
494+
ForceUntrimHeader(p_epoch_start);
495+
}
490496
if (!p_epoch_start->dynafed_params().IsNull()) {
491497
fedpegscripts.push_back(std::make_pair(p_epoch_start->dynafed_params().m_current.m_fedpeg_program, p_epoch_start->dynafed_params().m_current.m_fedpegscript));
492498
} else {

src/qt/test/rpcnestedtests.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ void RPCNestedTests::rpcNestedTests()
4848

4949
TestingSetup test;
5050
m_node.setContext(&test.m_node);
51+
CBlockIndex::SetNodeContext(&test.m_node);
5152

5253
if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished();
5354

src/rest.cpp

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -232,13 +232,10 @@ static bool rest_headers(const std::any& context,
232232
case RetFormat::BINARY: {
233233
CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION);
234234
for (const CBlockIndex *pindex : headers) {
235-
if (pindex->trimmed()) {
236-
CBlockHeader tmp;
237-
node::ReadBlockHeaderFromDisk(tmp, pindex, Params().GetConsensus());
238-
ssHeader << tmp;
239-
} else {
240-
ssHeader << pindex->GetBlockHeader();
241-
}
235+
LOCK(cs_main);
236+
CBlockIndex tmpBlockIndexFull;
237+
const CBlockIndex* pindexfull=pindex->untrim_to(&tmpBlockIndexFull);
238+
ssHeader << pindexfull->GetBlockHeader();
242239
}
243240

244241
std::string binaryHeader = ssHeader.str();
@@ -250,14 +247,10 @@ static bool rest_headers(const std::any& context,
250247
case RetFormat::HEX: {
251248
CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION);
252249
for (const CBlockIndex *pindex : headers) {
253-
if (pindex->trimmed()) {
254-
CBlockHeader tmp;
255-
node::ReadBlockHeaderFromDisk(tmp, pindex, Params().GetConsensus());
256-
ssHeader << tmp;
257-
258-
} else {
259-
ssHeader << pindex->GetBlockHeader();
260-
}
250+
LOCK(cs_main);
251+
CBlockIndex tmpBlockIndexFull;
252+
const CBlockIndex* pindexfull=pindex->untrim_to(&tmpBlockIndexFull);
253+
ssHeader << pindexfull->GetBlockHeader();
261254
}
262255

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

0 commit comments

Comments
 (0)