Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

node: revalidate canonical chain with one forward cycle at startup #1511

Merged
merged 10 commits into from
Sep 11, 2023
1 change: 1 addition & 0 deletions silkworm/node/common/settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ struct NodeSettings {
uint32_t sync_loop_throttle_seconds{0}; // Minimum interval amongst sync cycle
uint32_t sync_loop_log_interval_seconds{30}; // Interval for sync loop to emit logs
std::string node_name; // The node identifying name
bool parallel_fork_tracking_enabled{false}; // Whether to track multiple parallel forks at head
};

} // namespace silkworm
19 changes: 11 additions & 8 deletions silkworm/node/stagedsync/execution_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ std::optional<ExecutionEngine::ForkingPath> ExecutionEngine::find_forking_point(
if (path.forking_point == main_chain_.last_chosen_head()) return {std::move(path)};

// search remaining path on main chain
if (main_chain_.is_canonical(path.forking_point)) return {std::move(path)};
if (main_chain_.is_finalized_canonical(path.forking_point)) return {std::move(path)};

auto forking_point = main_chain_.find_forking_point(path.forking_point.hash);
if (!forking_point) return {}; // not found
Expand All @@ -152,7 +152,7 @@ concurrency::AwaitableFuture<VerificationResult> ExecutionEngine::verify_chain(H

auto fork = find_fork_by_head(forks_, head_block_hash);
if (fork == forks_.end()) {
if (main_chain_.is_canonical(head_block_hash)) {
if (main_chain_.is_finalized_canonical(head_block_hash)) {
SILK_DEBUG << "ExecutionEngine: chain " << head_block_hash.to_hex() << " already verified";
concurrency::AwaitablePromise<VerificationResult> promise{io_context_.get_executor()};
promise.set_value(ValidChain{last_fork_choice_});
Expand All @@ -176,13 +176,16 @@ bool ExecutionEngine::notify_fork_choice_update(Hash head_block_hash, std::optio
if (!updated) return false;

last_fork_choice_ = main_chain_.last_chosen_head();
fork_tracking_active_ = true;
if (head_block_hash == main_chain_.current_head().hash and node_settings_.parallel_fork_tracking_enabled) {
log::Info("ExecutionEngine") << "activate parallel fork tracking at head " << head_block_hash.to_hex();
fork_tracking_active_ = true;
}
} else {
// chose the fork with the given head
auto f = find_fork_by_head(forks_, head_block_hash);

if (f == forks_.end()) {
if (main_chain_.is_canonical(head_block_hash)) {
if (main_chain_.is_finalized_canonical(head_block_hash)) {
SILK_DEBUG << "ExecutionEngine: chain " << head_block_hash.to_hex() << " already chosen";
return true;
} else {
Expand Down Expand Up @@ -269,17 +272,17 @@ std::optional<BlockBody> ExecutionEngine::get_body(Hash header_hash) const {
}

std::optional<BlockHeader> ExecutionEngine::get_canonical_header(BlockNum bn) const {
auto hash = main_chain_.get_canonical_hash(bn);
auto hash = main_chain_.get_finalized_canonical_hash(bn);
if (!hash) return {};
return main_chain_.get_header(*hash);
}

std::optional<Hash> ExecutionEngine::get_canonical_hash(BlockNum bn) const {
return main_chain_.get_canonical_hash(bn);
return main_chain_.get_finalized_canonical_hash(bn);
}

std::optional<BlockBody> ExecutionEngine::get_canonical_body(BlockNum bn) const {
auto hash = main_chain_.get_canonical_hash(bn);
auto hash = main_chain_.get_finalized_canonical_hash(bn);
if (!hash) return {};
return main_chain_.get_body(*hash);
}
Expand All @@ -291,7 +294,7 @@ std::optional<BlockNum> ExecutionEngine::get_block_number(Hash header_hash) cons
}

bool ExecutionEngine::is_canonical(Hash header_hash) const {
return main_chain_.is_canonical(header_hash);
return main_chain_.is_finalized_canonical(header_hash);
}

} // namespace silkworm::stagedsync
26 changes: 10 additions & 16 deletions silkworm/node/stagedsync/execution_pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,11 @@ class ExecutionPipeline::LogTimer : public Timer {
: Timer{
pipeline->node_settings_->asio_context.get_executor(),
pipeline->node_settings_->sync_loop_log_interval_seconds * 1'000,
[this] { return execute(); },
true},
pipeline_{pipeline} {
start();
}

~LogTimer() {
stop();
}
[this] { return expired(); },
/*.auto_start=*/true},
pipeline_{pipeline} {}

bool execute() {
bool expired() {
if (pipeline_->is_stopping()) {
log::Info(pipeline_->get_log_prefix()) << "stopping ...";
return false;
Expand Down Expand Up @@ -157,12 +151,12 @@ void ExecutionPipeline::load_stages() {
db::stages::kTxLookupKey,
db::stages::kLogIndexKey,
db::stages::kHistoryIndexKey,
db::stages::kHashStateKey, // Needs to happen before unwinding Execution
db::stages::kHashStateKey,
db::stages::kIntermediateHashesKey, // Needs to happen after unwinding HashState
db::stages::kExecutionKey,
db::stages::kSendersKey,
db::stages::kBlockBodiesKey,
db::stages::kBlockHashesKey, // Decanonify block hashes
db::stages::kBlockHashesKey, // De-canonify block hashes
db::stages::kHeadersKey,
});
}
Expand Down Expand Up @@ -214,15 +208,15 @@ Stage::Result ExecutionPipeline::forward(db::RWTxn& cycle_txn, BlockNum target_h

if (stage_result != Stage::Result::kSuccess) { /* clang-format off */
auto result_description = std::string(magic_enum::enum_name<Stage::Result>(stage_result));
log::Error(get_log_prefix(), {"op", "Forward", "returned", });
log::Error(get_log_prefix(), {"op", "Forward", "returned", result_description});
log::Error("ExecPipeline") << "Forward interrupted due to stage " << current_stage_->first << " failure";
return stage_result;
} /* clang-format on */

auto stage_head_number_ = db::stages::read_stage_progress(cycle_txn, current_stage_->first);
if (stage_head_number_ != target_height) {
auto stage_head_number = db::stages::read_stage_progress(cycle_txn, current_stage_->first);
if (stage_head_number != target_height) {
throw std::logic_error("Sync pipeline: stage returned success with an height different from target=" +
to_string(target_height) + " reached= " + to_string(stage_head_number_));
to_string(target_height) + " reached= " + to_string(stage_head_number));
}

auto [_, stage_duration] = stages_stop_watch.lap();
Expand Down
11 changes: 6 additions & 5 deletions silkworm/node/stagedsync/execution_pipeline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,13 @@ class ExecutionPipeline : public Stoppable {
silkworm::NodeSettings* node_settings_;
std::unique_ptr<SyncContext> sync_context_; // context shared across stages

using Stage_Container = std::map<const char*, std::unique_ptr<stagedsync::Stage>>;
Stage_Container stages_;
using StageContainer = std::map<const char*, std::unique_ptr<stagedsync::Stage>>;
StageContainer stages_;
StageContainer::iterator current_stage_;

Stage_Container::iterator current_stage_;
std::vector<const char*> stages_forward_order_;
std::vector<const char*> stages_unwind_order_;
using StageNames = std::vector<const char*>;
StageNames stages_forward_order_;
StageNames stages_unwind_order_;
std::atomic<size_t> current_stages_count_{0};
std::atomic<size_t> current_stage_number_{0};

Expand Down
Loading