Skip to content

Commit 4d3884f

Browse files
authored
Add context gap aware finalization (#995)
* Add context gap aware finalization * Fix build
1 parent bd9a744 commit 4d3884f

File tree

6 files changed

+63
-12
lines changed

6 files changed

+63
-12
lines changed

cmake/functions.cmake

+5-1
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,13 @@ function(addtest test_name)
4646
gtest
4747
Threads::Threads
4848
)
49+
50+
# generate 7-digit random number to run UT with different seeds
51+
string(RANDOM LENGTH 7 ALPHABET 0123456789 _SEED)
52+
math(EXPR number "${_SEED} + 0") # Remove extra leading 0s.
4953
add_test(
5054
NAME ${test_name}
51-
COMMAND $<TARGET_FILE:${test_name}>
55+
COMMAND $<TARGET_FILE:${test_name}> ${_SEED}
5256
)
5357
set_target_properties(${test_name} PROPERTIES
5458
CXX_STANDARD 17

include/veriblock/pop/algorithm.hpp

+8
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,14 @@ T& as_mut(const T& t) {
146146
return const_cast<T&>(t);
147147
}
148148

149+
//! returns min value in a container (vector, array...), or "default" value if
150+
//! container is empty
151+
template <typename T, typename Container>
152+
const T min_or_default(Container& c, const T default_) {
153+
const auto it = std::min_element(c.begin(), c.end());
154+
return it == c.end() ? default_ : *it;
155+
}
156+
149157
} // namespace altintegration
150158

151159
#endif // VERIBLOCK_POP_CPP_ALGORITHM_HPP

include/veriblock/pop/blockchain/base_block_tree.hpp

+26-6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#ifndef ALTINTEGRATION_BASE_BLOCK_TREE_HPP
77
#define ALTINTEGRATION_BASE_BLOCK_TREE_HPP
88

9+
#include <limits>
910
#include <unordered_map>
1011
#include <unordered_set>
1112
#include <veriblock/pop/algorithm.hpp>
@@ -431,8 +432,12 @@ struct BaseBlockTree {
431432

432433
protected:
433434
//! @private
434-
void finalizeBlocks(int32_t maxReorgBlocks,
435-
int32_t preserveBlocksBehindFinal) {
435+
void finalizeBlocks(
436+
int32_t maxReorgBlocks,
437+
int32_t preserveBlocksBehindFinal,
438+
// we should not finalize blocks
439+
// above this height
440+
int32_t maxFinalizeBlockHeight = std::numeric_limits<int32_t>::max()) {
436441
auto* tip = this->getBestChain().tip();
437442
VBK_ASSERT_MSG(tip, "%s tree must be bootstrapped", block_t::name());
438443
VBK_ASSERT(!this->isLoadingBlocks_);
@@ -447,6 +452,17 @@ struct BaseBlockTree {
447452
firstBlockHeight = std::max(bootstrapBlockHeight, firstBlockHeight);
448453
auto* finalizedIndex = this->getBestChain()[firstBlockHeight];
449454
VBK_ASSERT(finalizedIndex != nullptr);
455+
if (finalizedIndex->getHeight() >= maxFinalizeBlockHeight) {
456+
// we should not finalize blocks with height higher than
457+
// maxFinalizeBlockHeight
458+
VBK_LOG_INFO(
459+
"Skipping finalization of %s because its height >= %d (max "
460+
"possible height to finalize)",
461+
finalizedIndex->toShortPrettyString(),
462+
maxFinalizeBlockHeight);
463+
return;
464+
}
465+
450466
this->finalizeBlockImpl(*finalizedIndex, preserveBlocksBehindFinal);
451467
}
452468

@@ -967,13 +983,17 @@ struct BaseBlockTree {
967983
// update active chain
968984
VBK_ASSERT(firstBlockHeight >= rootBlockHeight);
969985
size_t deallocatedBlocks = firstBlockHeight - rootBlockHeight;
970-
if (deallocatedBlocks > 0) {
971-
VBK_LOG_WARN(
972-
"%s tree deallocated blocks: %d", block_t::name(), deallocatedBlocks);
973-
}
974986
activeChain_ = Chain<index_t>(firstBlockHeight, activeChain_.tip());
975987
appliedBlockCount = activeChain_.blocksCount();
976988

989+
if (deallocatedBlocks > 0) {
990+
VBK_LOG_WARN("Deallocated %d blocks in %s tree. Active chain %d..%d",
991+
deallocatedBlocks,
992+
block_t::name(),
993+
activeChain_.first()->getHeight(),
994+
activeChain_.tip()->getHeight());
995+
}
996+
977997
// fourth, mark `index` and all predecessors as finalized
978998
index_t* ptr = finalizedBlock;
979999
while (ptr != nullptr && !ptr->finalized) {

include/veriblock/pop/blockchain/blocktree.hpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@
99
#include <algorithm>
1010
#include <memory>
1111
#include <unordered_map>
12-
#include <veriblock/pop/fmt.hpp>
13-
#include <veriblock/pop/stateless_validation.hpp>
14-
#include <veriblock/pop/storage/block_reader.hpp>
15-
#include <veriblock/pop/validation_state.hpp>
1612

1713
#include "base_block_tree.hpp"
1814
#include "block_index.hpp"
1915
#include "blockchain_util.hpp"
2016
#include "chain.hpp"
2117
#include "tree_algo.hpp"
18+
#include "veriblock/pop/fmt.hpp"
19+
#include "veriblock/pop/stateless_validation.hpp"
20+
#include "veriblock/pop/storage/block_reader.hpp"
21+
#include "veriblock/pop/validation_state.hpp"
2222

2323
namespace altintegration {
2424

src/pop/blockchain/pop/vbk_block_tree.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <algorithm>
99
#include <cstddef>
10+
#include <limits>
1011
#include <map>
1112
#include <memory>
1213
#include <set>
@@ -459,9 +460,15 @@ void VbkBlockTree::finalizeBlocks() {
459460
VBK_ASSERT(!this->isLoadingBlocks_);
460461
VBK_ASSERT(appliedBlockCount == activeChain_.blocksCount());
461462

463+
const auto* btctip = btc().getBestChain().tip();
464+
VBK_ASSERT(btctip != nullptr);
465+
int32_t minVbkRefHeight =
466+
min_or_default(btctip->getRefs(), std::numeric_limits<int32_t>::max());
467+
462468
// first, finalize VBK
463469
base::finalizeBlocks(this->getParams().getMaxReorgBlocks(),
464-
this->getParams().preserveBlocksBehindFinal());
470+
this->getParams().preserveBlocksBehindFinal(),
471+
/*maxFinalizeBlockHeihht=*/minVbkRefHeight);
465472

466473
// then, finalize BTC
467474
btc().finalizeBlocks();

test/pop/blockchain/altblock_finalization_test_2.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ struct AltBlockFinalization2 : public MemPoolFixture {
2222
tip = mineAltBlocks(alttree.getRoot(), 100);
2323
ASSERT_TRUE(alttree.setState(*tip, state));
2424
totalBlocks = alttree.getBlocks().size();
25+
26+
alttree.btc().getBestChain().tip()->addRef(1000000u);
27+
}
28+
29+
void disableBtcContextGapCheck() {
30+
alttree.btc().getBestChain().tip()->removeRef(0);
31+
alttree.btc().getBestChain().tip()->addRef(1000000u);
2532
}
2633
};
2734

@@ -61,6 +68,8 @@ TEST_F(AltBlockFinalization2, FinalizeVbkTip) {
6168
// save state
6269
save(alttree);
6370

71+
// this allows to bypass context gap finalization check
72+
disableBtcContextGapCheck();
6473
alttree.finalizeBlocks();
6574

6675
ASSERT_EQ(alttree.getBlocks().size(), 2);
@@ -106,6 +115,7 @@ TEST_F(AltBlockFinalization2, FinalizeMaxVbks) {
106115
save(alttree);
107116

108117
// finalize block
118+
disableBtcContextGapCheck();
109119
alttree.finalizeBlocks();
110120

111121
ASSERT_EQ(alttree.getBlocks().size(), 2);
@@ -160,6 +170,7 @@ TEST_F(AltBlockFinalization2, FinalizedVbkBlock_1) {
160170
auto *vbktip = alttree.vbk().getBestChain().tip();
161171

162172
// finalize block
173+
disableBtcContextGapCheck();
163174
alttree.finalizeBlocks();
164175

165176
// check the state after finalization
@@ -221,6 +232,7 @@ TEST_F(AltBlockFinalization2, FinalizedVbkBlock_2) {
221232
auto *vbktip = alttree.vbk().getBestChain().tip();
222233

223234
// finalize block
235+
disableBtcContextGapCheck();
224236
alttree.finalizeBlocks();
225237

226238
// check the state after finalization

0 commit comments

Comments
 (0)