Skip to content

Commit 726eb4d

Browse files
authored
Dynamic trie pruning (#1556)
* Prune unused trie nodes on old and discarded block states
1 parent affcdc0 commit 726eb4d

File tree

115 files changed

+3226
-644
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

115 files changed

+3226
-644
lines changed

CMakeLists.txt

+6
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ if("${CMAKE_CXX_COMPILER_ID}" MATCHES "^(AppleClang|Clang|GNU)$")
9595
add_flag(-Werror=sign-compare) # warn the user if they compare a signed and unsigned numbers
9696
add_flag(-Werror=reorder) # field '$1' will be initialized after field '$2'
9797
add_flag(-Werror=mismatched-tags) # warning: class '$1' was previously declared as struct
98+
add_flag(-Werror=switch) # unhandled values in a switch statement
9899
# cmake-format: on
99100
else()
100101
# promote to errors
@@ -104,6 +105,7 @@ if("${CMAKE_CXX_COMPILER_ID}" MATCHES "^(AppleClang|Clang|GNU)$")
104105
add_flag(-Werror-non-virtual-dtor) # warn the user if a class with virtual functions has a non-virtual destructor. This helps catch hard to track down memory errors
105106
add_flag(-Werror-sign-compare) # warn the user if they compare a signed and unsigned numbers
106107
add_flag(-Werror-reorder) # field '$1' will be initialized after field '$2'
108+
add_flag(-Werror-switch) # unhandled values in a switch statement
107109
# cmake-format: on
108110
endif()
109111
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
@@ -112,6 +114,9 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
112114
# https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md#msvc
113115
endif()
114116

117+
print("C flags: ${CMAKE_C_FLAGS}")
118+
print("CXX flags: ${CMAKE_CXX_FLAGS}")
119+
115120
if(COVERAGE)
116121
include(cmake/coverage.cmake)
117122
endif()
@@ -164,6 +169,7 @@ kagome_install_setup(
164169
core/scale
165170
core/storage
166171
core/subscription
172+
core/telemetry
167173
core/utils)
168174

169175
include(CMakePackageConfigHelpers)

core/api/service/child_state/impl/child_state_api_impl.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ namespace kagome::api {
129129
storage_->getEphemeralBatchAt(child_root_hash));
130130
auto res = child_storage_trie_reader->tryGet(key);
131131
return common::map_result_optional(
132-
std::move(res), [](common::BufferOrView &&r) { return r.into(); });
132+
std::move(res),
133+
[](common::BufferOrView &&r) { return r.intoBuffer(); });
133134
}
134135

135136
outcome::result<std::optional<primitives::BlockHash>>

core/api/service/state/impl/state_api_impl.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ namespace kagome::api {
122122
OUTCOME_TRY(trie_reader, storage_->getEphemeralBatchAt(header.state_root));
123123
auto res = trie_reader->tryGet(key);
124124
return common::map_result_optional(
125-
std::move(res), [](common::BufferOrView &&r) { return r.into(); });
125+
std::move(res), [](common::BufferOrView &&r) { return r.intoBuffer(); });
126126
}
127127

128128
outcome::result<std::vector<StateApiImpl::StorageChangeSet>>
@@ -164,7 +164,7 @@ namespace kagome::api {
164164
OUTCOME_TRY(opt_get, batch->tryGet(key));
165165
auto opt_value = common::map_optional(
166166
std::move(opt_get),
167-
[](common::BufferOrView &&r) { return r.into(); });
167+
[](common::BufferOrView &&r) { return r.intoBuffer(); });
168168
auto it = last_values.find(key);
169169
if (it == last_values.end() || it->second != opt_value) {
170170
change.changes.push_back(StorageChangeSet::Change{key, opt_value});

core/application/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ target_link_libraries(app_config
3737
chain_spec
3838
build_version
3939
)
40+
kagome_install(app_config)
4041

4142
add_library(chain_spec
4243
impl/chain_spec_impl.cpp

core/application/app_configuration.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,8 @@ namespace kagome::application {
252252
*/
253253
virtual StorageBackend storageBackend() const = 0;
254254

255+
virtual std::optional<size_t> statePruningDepth() const = 0;
256+
255257
/**
256258
* @return database state cache size in MiB
257259
*/

core/application/impl/app_configuration_impl.cpp

+25-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
#include "application/impl/app_configuration_impl.hpp"
77

8-
#include <fstream>
98
#include <limits>
109
#include <regex>
1110
#include <string>
@@ -18,7 +17,6 @@
1817
#include <boost/uuid/uuid_io.hpp>
1918
#include <charconv>
2019
#include <libp2p/layer/websocket/wss_adaptor.hpp>
21-
#include "filesystem/common.hpp"
2220

2321
#include "api/transport/tuner.hpp"
2422
#include "application/build_version.hpp"
@@ -27,6 +25,7 @@
2725
#include "chain_spec_impl.hpp"
2826
#include "common/hexutil.hpp"
2927
#include "common/uri.hpp"
28+
#include "filesystem/common.hpp"
3029
#include "filesystem/directories.hpp"
3130
#include "utils/read_file.hpp"
3231

@@ -248,7 +247,8 @@ namespace kagome::application {
248247
offchain_worker_mode_{def_offchain_worker_mode},
249248
enable_offchain_indexing_{def_enable_offchain_indexing},
250249
recovery_state_{def_block_to_recover},
251-
db_cache_size_{def_db_cache_size} {
250+
db_cache_size_{def_db_cache_size},
251+
state_pruning_depth_{} {
252252
SL_INFO(logger_, "Soramitsu Kagome started. Version: {} ", buildVersion());
253253
}
254254

@@ -790,6 +790,7 @@ namespace kagome::application {
790790
("db-cache", po::value<uint32_t>()->default_value(def_db_cache_size), "Limit the memory the database cache can use <MiB>")
791791
("enable-offchain-indexing", po::value<bool>(), "enable Offchain Indexing API, which allow block import to write to offchain DB)")
792792
("recovery", po::value<std::string>(), "recovers block storage to state after provided block presented by number or hash, and stop after that")
793+
("state-pruning", po::value<std::string>()->default_value("archive"), "state pruning policy. 'archive' or the number of finalized blocks to keep.")
793794
;
794795

795796
po::options_description network_desc("Network options");
@@ -1445,6 +1446,27 @@ namespace kagome::application {
14451446
return false;
14461447
}
14471448

1449+
if (auto state_pruning_opt =
1450+
find_argument<std::string>(vm, "state-pruning");
1451+
state_pruning_opt.has_value()) {
1452+
const auto& val = state_pruning_opt.value();
1453+
if (val == "archive") {
1454+
state_pruning_depth_ = std::nullopt;
1455+
} else {
1456+
uint32_t depth{};
1457+
auto [_, err] = std::from_chars(&*val.begin(), &*val.end(), depth);
1458+
if (err == std::errc{}) {
1459+
state_pruning_depth_ = depth;
1460+
} else {
1461+
SL_ERROR(logger_,
1462+
"Failed to parse state-pruning param (which should be "
1463+
"either 'archive' or an integer): {}",
1464+
err);
1465+
return false;
1466+
}
1467+
}
1468+
}
1469+
14481470
// if something wrong with config print help message
14491471
if (not validate_config()) {
14501472
std::cout << desc << std::endl;

core/application/impl/app_configuration_impl.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,9 @@ namespace kagome::application {
184184
uint32_t dbCacheSize() const override {
185185
return db_cache_size_;
186186
}
187+
std::optional<size_t> statePruningDepth() const override {
188+
return state_pruning_depth_;
189+
}
187190
std::optional<std::string_view> devMnemonicPhrase() const override {
188191
if (dev_mnemonic_phrase_) {
189192
return *dev_mnemonic_phrase_;
@@ -337,6 +340,7 @@ namespace kagome::application {
337340
std::optional<primitives::BlockId> recovery_state_;
338341
StorageBackend storage_backend_ = StorageBackend::RocksDB;
339342
uint32_t db_cache_size_;
343+
std::optional<size_t> state_pruning_depth_;
340344
std::optional<std::string> dev_mnemonic_phrase_;
341345
std::string node_wss_pem_;
342346
std::optional<BenchmarkConfigSection> benchmark_config_;

core/application/impl/chain_spec_impl.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,10 @@ namespace kagome::application {
254254

255255
auto read_key_block = [](const auto &tree,
256256
GenesisRawData &data) -> outcome::result<void> {
257-
for (const auto &[child_key, child_value] : tree) {
257+
for (const auto &[key, value] : tree) {
258258
// get rid of leading 0x for key and value and unhex
259-
OUTCOME_TRY(key_processed, common::unhexWith0x(child_key));
260-
OUTCOME_TRY(value_processed, common::unhexWith0x(child_value.data()));
259+
OUTCOME_TRY(key_processed, common::unhexWith0x(key));
260+
OUTCOME_TRY(value_processed, common::unhexWith0x(value.data()));
261261
data.emplace_back(std::move(key_processed), std::move(value_processed));
262262
}
263263
return outcome::success();

core/authority_discovery/query/query_impl.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ namespace kagome::authority_discovery {
122122
auto authority = queue_.back();
123123
queue_.pop_back();
124124

125-
common::Buffer hash = crypto::sha256(authority);
125+
common::Buffer hash{crypto::sha256(authority)};
126126
scheduler_->schedule([=, wp = weak_from_this()] {
127127
if (auto self = wp.lock()) {
128128
std::ignore = kademlia_->getValue(
@@ -131,12 +131,12 @@ namespace kagome::authority_discovery {
131131
--active_;
132132
pop();
133133
if (res.has_error()) {
134-
SL_WARN(log_, "Kademlia can't get value: {}", res.error());
134+
SL_DEBUG(log_, "Kademlia can't get value: {}", res.error());
135135
return;
136136
}
137137
auto r = add(authority, std::move(res.value()));
138138
if (not r) {
139-
SL_WARN(log_, "Can't add: {}", r.error());
139+
SL_DEBUG(log_, "Can't add: {}", r.error());
140140
}
141141
});
142142
}

core/benchmark/block_execution_benchmark.cpp

+17-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ OUTCOME_CPP_DEFINE_CATEGORY(kagome::benchmark,
2020
using E = kagome::benchmark::BlockExecutionBenchmark::Error;
2121
case E::BLOCK_WEIGHT_DECODE_FAILED:
2222
return "Failed to decode block weight";
23+
case E::BLOCK_NOT_FOUND:
24+
return "A block expected to be present in the block tree is not found";
2325
}
2426
return "Unknown BlockExecutionBenchmark error";
2527
}
@@ -221,8 +223,12 @@ namespace kagome::benchmark {
221223
block_tree_->getBlockHash(config.start),
222224
"retrieving hash of block {}",
223225
config.start);
226+
if (!current_hash) {
227+
SL_ERROR(logger_, "Start block {} is not found!", config.start);
228+
return Error::BLOCK_NOT_FOUND;
229+
}
224230

225-
primitives::BlockInfo current_block_info = {config.start, current_hash};
231+
primitives::BlockInfo current_block_info = {config.start, *current_hash};
226232
std::vector<primitives::BlockHash> block_hashes;
227233
std::vector<primitives::Block> blocks;
228234
while (current_block_info.number <= config.end) {
@@ -244,7 +250,14 @@ namespace kagome::benchmark {
244250
"retrieving hash of block {}",
245251
current_block_info.number + 1);
246252
current_block_info.number += 1;
247-
current_block_info.hash = next_hash;
253+
254+
if (!next_hash) {
255+
SL_ERROR(logger_,
256+
"Next block {} is not found!",
257+
current_block_info.number + 1);
258+
return Error::BLOCK_NOT_FOUND;
259+
}
260+
current_block_info.hash = *next_hash;
248261
}
249262

250263
std::chrono::steady_clock clock;
@@ -291,7 +304,8 @@ namespace kagome::benchmark {
291304
*trie_storage_,
292305
blocks[stat.getBlock().number - config.start].header.state_root));
293306
fmt::print(
294-
"Block #{}: consumed {} ns out of declared {} ns on average. ({} %)\n",
307+
"Block #{}: consumed {} ns out of declared {} ns on average. ({} "
308+
"%)\n",
295309
stat.getBlock().number,
296310
stat.avg().count(),
297311
block_weight_ns.count(),

core/benchmark/block_execution_benchmark.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ namespace kagome::benchmark {
3232
public:
3333
enum class Error {
3434
BLOCK_WEIGHT_DECODE_FAILED,
35+
BLOCK_NOT_FOUND,
3536
};
3637

3738
struct Config {

core/blockchain/block_tree.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ namespace kagome::blockchain {
4343
* @param block_number of the block header we are looking for
4444
* @return result containing block hash if it exists, error otherwise
4545
*/
46-
virtual outcome::result<primitives::BlockHash> getBlockHash(
46+
virtual outcome::result<std::optional<primitives::BlockHash>> getBlockHash(
4747
primitives::BlockNumber block_number) const = 0;
4848

4949
/**

0 commit comments

Comments
 (0)