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

Allow start from lib #185

Merged
merged 15 commits into from
Jan 26, 2024
16 changes: 16 additions & 0 deletions src/block_conversion_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ class block_conversion_plugin_impl : std::enable_shared_from_this<block_conversi
}

if( lib_timestamp ) {
// Minus 1 to make sure the resulting block is a completed EVM block built from irreversible EOS blocks.
auto evm_lib = timestamp_to_evm_block_num(*lib_timestamp) - 1;

// Remove irreversible native blocks
Expand All @@ -313,9 +314,15 @@ class block_conversion_plugin_impl : std::enable_shared_from_this<block_conversi
}

// Remove irreversible evm blocks
// The block at height evm_lib is actually irreversible as well.
// We want to keep at least one irreversible block in the array to deal with forks.

while(evm_blocks.front().header.number < evm_lib) {
evm_blocks.pop_front();
}

// Record the height of this complete EVM block from irreversible EOS blocks.
evm_lib_ = evm_lib;
}
}
);
Expand All @@ -332,6 +339,10 @@ class block_conversion_plugin_impl : std::enable_shared_from_this<block_conversi
return evmtx;
}

uint64_t get_evm_lib() {
return evm_lib_;
}

void shutdown() {}

std::list<channels::native_block> native_blocks;
Expand All @@ -340,6 +351,7 @@ class block_conversion_plugin_impl : std::enable_shared_from_this<block_conversi
channels::native_blocks::channel_type::handle native_blocks_subscription;
std::optional<eosevm::block_mapping> bm;
uint64_t evm_contract_name = 0;
uint64_t evm_lib_;
};

block_conversion_plugin::block_conversion_plugin() : my(new block_conversion_plugin_impl()) {}
Expand All @@ -361,3 +373,7 @@ void block_conversion_plugin::plugin_shutdown() {
my->shutdown();
SILK_INFO << "Shutdown block_conversion plugin";
}

uint64_t block_conversion_plugin::get_evm_lib() {
return my->get_evm_lib();
}
1 change: 1 addition & 0 deletions src/block_conversion_plugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class block_conversion_plugin : public appbase::plugin<block_conversion_plugin>
void plugin_shutdown();

uint32_t get_block_stride() const;
uint64_t get_evm_lib();

private:
std::unique_ptr<class block_conversion_plugin_impl> my;
Expand Down
39 changes: 37 additions & 2 deletions src/blockchain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,31 @@
#include <map>
#include <string>

#include <boost/asio/io_context.hpp>

#include <silkworm/node/stagedsync/types.hpp>
#include <silkworm/node/stagedsync/execution_engine.hpp>

class ExecutionEngineEx : public silkworm::stagedsync::ExecutionEngine {
public :

ExecutionEngineEx(boost::asio::io_context& io, silkworm::NodeSettings& settings, silkworm::db::RWAccess dba) : ExecutionEngine(io, settings, dba) {

}
silkworm::db::RWTxn& get_tx() {
return main_chain_.tx();
}
};

using sys = sys_plugin;
class blockchain_plugin_impl : std::enable_shared_from_this<blockchain_plugin_impl> {
public:
blockchain_plugin_impl() = default;

silkworm::db::RWTxn& get_tx() {
return exec_engine->get_tx();
}

inline void init() {
SILK_DEBUG << "blockchain_plugin_impl INIT";
db_env = appbase::app().get_plugin<engine_plugin>().get_db();
Expand All @@ -26,12 +43,26 @@ class blockchain_plugin_impl : std::enable_shared_from_this<blockchain_plugin_im

SILK_DEBUG << "EVM Block " << new_block->header.number;
if(!exec_engine) {
exec_engine = std::make_unique<silkworm::stagedsync::ExecutionEngine>(appbase::app().get_io_context(), *node_settings, silkworm::db::RWAccess{*db_env});
exec_engine = std::make_unique<ExecutionEngineEx>(appbase::app().get_io_context(), *node_settings, silkworm::db::RWAccess{*db_env});
exec_engine->open();
}

exec_engine->insert_block(new_block);
if(!(++block_count % 5000) || !new_block->irreversible) {
// Get the last complete EVM block from irreversible EOS blocks.
// The height is uint64_t so we can get it as a whole without worrying about atomicity.
// Even some data races happen, it's fine in our scenario to read old data as starting from earlier blocks is always safer.
uint64_t evm_lib = appbase::app().get_plugin<block_conversion_plugin>().get_evm_lib();
SILK_INFO << "Storing EVM Lib: " << "#" << evm_lib;

// Storing the EVM block height of the last complete block from irreversible EOS blocks.
// We have to do this in this thread with the tx instance stored in exec_engine due to the lmitation of MDBX.
// Note there's no need to commit here as the tx is borrowed. ExecutionEngine will manange the commits.
// There's some other advantage to save this height in this way:
// If the system is shut down during catching up irreversible blocks, i.e. in the middle of the 5000 block run,
// saving the height in this way can minimize the possibility having a stored height that is higher than the canonical header.
write_runtime_states_u64(exec_engine->get_tx(), evm_lib, silkworm::db::RuntimeState::kLibProcessed);

exec_engine->verify_chain(new_block->header.hash());
block_count=0;
}
Expand All @@ -56,7 +87,7 @@ class blockchain_plugin_impl : std::enable_shared_from_this<blockchain_plugin_im
silkworm::NodeSettings* node_settings;
mdbx::env* db_env;
channels::evm_blocks::channel_type::handle evm_blocks_subscription;
std::unique_ptr<silkworm::stagedsync::ExecutionEngine> exec_engine;
std::unique_ptr<ExecutionEngineEx> exec_engine;
};

blockchain_plugin::blockchain_plugin() : my(new blockchain_plugin_impl()) {}
Expand All @@ -78,3 +109,7 @@ void blockchain_plugin::plugin_shutdown() {
my->shutdown();
SILK_INFO << "Shutdown Blockchain plugin";
}

silkworm::db::RWTxn& blockchain_plugin::get_tx() {
return my->get_tx();
}
1 change: 1 addition & 0 deletions src/blockchain_plugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class blockchain_plugin : public appbase::plugin<blockchain_plugin> {
void plugin_initialize(const appbase::variables_map& options);
void plugin_startup();
void plugin_shutdown();
silkworm::db::RWTxn& get_tx();

private:
std::unique_ptr<class blockchain_plugin_impl> my;
Expand Down
38 changes: 34 additions & 4 deletions src/engine_plugin.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "engine_plugin.hpp"
#include "blockchain_plugin.hpp"
#include "channels.hpp"

#include <filesystem>
Expand Down Expand Up @@ -138,15 +139,39 @@ class engine_plugin_impl : std::enable_shared_from_this<engine_plugin_impl> {

std::optional<silkworm::Block> get_canonical_block_at_height(std::optional<uint64_t> height) {
uint64_t target = 0;
SILK_INFO << "Determining effective canonical header.";
if (!height) {
auto lib = get_stored_evm_lib();
auto header = get_head_canonical_header();
if(!header) return {};
target = header->number;
if (lib) {
SILK_INFO << "Stored LIB at: " << "#" << *lib;
target = *lib;
// Make sure we start from number smaller than or equal to head if possible.
// But ignore the case where head is not avaiable
if (header && target > header->number) {
target = header->number;
SILK_INFO << "Canonical header is at lower height, set the target height to: " << "#" << target;
}
}
else {
SILK_INFO << "Stored LIB not available.";
// no lib, might be the first run from an old db.
// Use the old logic.
if (!header) {
SILK_INFO << "Failed to read canonical header";
return {};
}
else {
target = header->number;
SILK_INFO << "Canonical header at: " << "#" << target;
}
}
}
else {
// Do not check canonical header.
// If there's anything wrong in that table, overriding here has some chance to fix it.
// Do not check canonical header or lib.
// If there's anything wrong, overriding here has some chance to fix it.
target = *height;
SILK_INFO << "Command line options set the canonical height as " << "#" << target;
}

silkworm::db::ROTxn txn(db_env);
Expand All @@ -156,6 +181,11 @@ class engine_plugin_impl : std::enable_shared_from_this<engine_plugin_impl> {
return block;
}

std::optional<uint64_t> get_stored_evm_lib() {
silkworm::db::ROTxn txn(db_env);
return read_runtime_states_u64(txn, silkworm::db::RuntimeState::kLibProcessed);
}

std::optional<silkworm::BlockHeader> get_genesis_header() {
silkworm::db::ROTxn txn(db_env);
return silkworm::db::read_canonical_header(txn, 0);
Expand Down
Loading