From 0fbd0e6e9f391206ed5e9965784139099867a953 Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Mon, 24 Apr 2023 16:49:45 +0100 Subject: [PATCH 01/26] SKALED-1425 Retire consensus working mutex --- libethereum/SkaleHost.cpp | 38 +------------------------------------- libethereum/SkaleHost.h | 3 --- 2 files changed, 1 insertion(+), 40 deletions(-) diff --git a/libethereum/SkaleHost.cpp b/libethereum/SkaleHost.cpp index 1df6da4dc..c6511faf1 100644 --- a/libethereum/SkaleHost.cpp +++ b/libethereum/SkaleHost.cpp @@ -62,8 +62,6 @@ using namespace std; using namespace dev; using namespace dev::eth; -const int SkaleHost::EXIT_FORCEFULLTY_SECONDS = 60 * 4; - #ifndef CONSENSUS #define CONSENSUS 1 #endif @@ -385,12 +383,6 @@ ConsensusExtFace::transactions_vector SkaleHost::pendingTransactions( if ( m_exitNeeded ) return out_vector; - // HACK this should be field (or better do it another way) - static bool first_run = true; - if ( first_run ) { - m_consensusWorkingMutex.lock(); - first_run = false; - } if ( m_exitNeeded ) return out_vector; @@ -399,12 +391,8 @@ ConsensusExtFace::transactions_vector SkaleHost::pendingTransactions( if ( m_exitNeeded ) return out_vector; - unlock_guard< std::timed_mutex > unlocker( m_consensusWorkingMutex ); - - if ( m_exitNeeded ) { - unlocker.will_exit(); + if ( m_exitNeeded ) return out_vector; - } if ( need_restore_emptyBlockInterval ) { this->m_consensus->setEmptyBlockIntervalMs( this->emptyBlockIntervalMsForRestore.value() ); @@ -532,10 +520,6 @@ ConsensusExtFace::transactions_vector SkaleHost::pendingTransactions( } } - if ( this->m_exitNeeded ) - unlocker.will_exit(); - - if ( this->emptyBlockIntervalMsForRestore.has_value() ) need_restore_emptyBlockInterval = true; @@ -584,9 +568,6 @@ ConsensusExtFace::transactions_vector SkaleHost::pendingTransactions( m_debugTracer.tracepoint( "send_to_consensus" ); - if ( this->m_exitNeeded ) - unlocker.will_exit(); - return out_vector; } @@ -779,7 +760,6 @@ void SkaleHost::startWorking() { // TODO Should we do it at end of this func? (problem: broadcaster receives transaction and // recursively calls this func - so working is still false!) working = true; - m_exitedForcefully = false; if ( !this->m_client.chainParams().nodeInfo.syncNode ) { try { @@ -841,22 +821,6 @@ void SkaleHost::stopWorking() { if ( !working ) return; - bool locked = - m_consensusWorkingMutex.try_lock_for( std::chrono::seconds( EXIT_FORCEFULLTY_SECONDS ) ); - auto lock = locked ? std::make_unique< std::lock_guard< std::timed_mutex > >( - m_consensusWorkingMutex, std::adopt_lock ) : - std::unique_ptr< std::lock_guard< std::timed_mutex > >(); - ( void ) lock; // for Codacy - - // if we could not lock from 1st attempt - then exit forcefully! - if ( !locked ) { - m_exitedForcefully = true; - clog( VerbosityWarning, "skale-host" ) - << cc::fatal( "ATTENTION:" ) << " " - << cc::error( "Forcefully shutting down consensus!" ); - } - - m_exitNeeded = true; pauseConsensus( false ); diff --git a/libethereum/SkaleHost.h b/libethereum/SkaleHost.h index 3f3a7ed81..6ab7e01ca 100644 --- a/libethereum/SkaleHost.h +++ b/libethereum/SkaleHost.h @@ -87,7 +87,6 @@ class DefaultConsensusFactory : public ConsensusFactory { class SkaleHost { friend class ConsensusExtImpl; - static const int EXIT_FORCEFULLTY_SECONDS; struct my_hash { size_t operator()( const dev::eth::Transaction& tx ) const { return hash( tx.sha3() ); } @@ -114,7 +113,6 @@ class SkaleHost { void startWorking(); void stopWorking(); bool isWorking() const { return this->working; } - bool exitedForcefully() const { return m_exitedForcefully; } void noteNewTransactions(); void noteNewBlocks(); @@ -150,7 +148,6 @@ class SkaleHost { private: std::atomic_bool working = false; - std::atomic_bool m_exitedForcefully = false; std::unique_ptr< Broadcaster > m_broadcaster; From a3210a6771fda163a474352f5e94a060a19cbc35 Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Mon, 24 Apr 2023 17:55:45 +0100 Subject: [PATCH 02/26] SKALED-1425 Exit on timestamp --- libethereum/SkaleHost.cpp | 7 +++++++ libethereum/SkaleHost.h | 5 +++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/libethereum/SkaleHost.cpp b/libethereum/SkaleHost.cpp index c6511faf1..87b79bb61 100644 --- a/libethereum/SkaleHost.cpp +++ b/libethereum/SkaleHost.cpp @@ -598,6 +598,12 @@ void SkaleHost::createBlock( const ConsensusExtFace::transactions_vector& _appro std::lock_guard< std::recursive_mutex > lock( m_pending_createMutex ); + if ( m_ignoreNewBlocks ) { + clog( VerbosityWarning, "skale-host" ) << "WARNING: skaled got new block #" << _blockID + << " after timestamp-related exit initiated!"; + return; + } + LOG( m_debugLogger ) << cc::debug( "createBlock " ) << cc::notice( "ID" ) << cc::debug( " = " ) << cc::warn( "#" ) << cc::num10( _blockID ) << std::endl; m_debugTracer.tracepoint( "create_block" ); @@ -740,6 +746,7 @@ void SkaleHost::createBlock( const ConsensusExtFace::transactions_vector& _appro if ( m_instanceMonitor != nullptr ) { if ( m_instanceMonitor->isTimeToRotate( _timeStamp ) ) { m_instanceMonitor->prepareRotation(); + m_ignoreNewBlocks = true; m_consensus->exitGracefully(); ExitHandler::exitHandler( SIGTERM, ExitHandler::ec_rotation_complete ); clog( VerbosityInfo, "skale-host" ) << "Rotation is completed. Instance is exiting"; diff --git a/libethereum/SkaleHost.h b/libethereum/SkaleHost.h index 6ab7e01ca..ee02acee7 100644 --- a/libethereum/SkaleHost.h +++ b/libethereum/SkaleHost.h @@ -167,8 +167,6 @@ class SkaleHost { std::recursive_mutex m_pending_createMutex; // for race conditions between // pendingTransactions() and createBock() - std::timed_mutex m_consensusWorkingMutex; // unlocks when it's OK to exit - std::atomic_int m_bcast_counter = 0; void penalizePeer(){}; // fake function for now @@ -188,7 +186,10 @@ class SkaleHost { // creating block dev::eth::Client& m_client; dev::eth::TransactionQueue& m_tq; // transactions ready to go to consensus + std::shared_ptr< InstanceMonitor > m_instanceMonitor; + std::atomic_bool m_ignoreNewBlocks = false; // used when we need to exit at specific block + bool m_broadcastEnabled; dev::Logger m_debugLogger{ dev::createLogger( dev::VerbosityDebug, "skale-host" ) }; From 6f053e9a3dea7e8ee1c734e0b013648fb5f053a2 Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Fri, 28 Apr 2023 16:15:23 +0100 Subject: [PATCH 03/26] SKALED-1425 Adapt to changes Oracle interface --- libethereum/SkaleHost.cpp | 3 ++- test/unittests/libethereum/SkaleHost.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libethereum/SkaleHost.cpp b/libethereum/SkaleHost.cpp index 87b79bb61..384648e2d 100644 --- a/libethereum/SkaleHost.cpp +++ b/libethereum/SkaleHost.cpp @@ -955,7 +955,8 @@ std::array< std::string, 4 > SkaleHost::getIMABLSPublicKey() const { } uint64_t SkaleHost::submitOracleRequest( const string& _spec, string& _receipt ) { - return m_consensus->submitOracleRequest( _spec, _receipt ); + std::string error; + return m_consensus->submitOracleRequest( _spec, _receipt, error ); } uint64_t SkaleHost::checkOracleResult( const string& _receipt, string& _result ) { diff --git a/test/unittests/libethereum/SkaleHost.cpp b/test/unittests/libethereum/SkaleHost.cpp index 05f469d38..af8536ef9 100644 --- a/test/unittests/libethereum/SkaleHost.cpp +++ b/test/unittests/libethereum/SkaleHost.cpp @@ -81,7 +81,7 @@ class ConsensusTestStub : public ConsensusInterface { } uint64_t submitOracleRequest( const string& /*_spec*/, string& - /*_receipt*/) override { + /*_receipt*/, string& /*error*/) override { return 0; } From d57f6faa61be1d29b9466becd39c0d50e2447bd7 Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Mon, 15 May 2023 17:20:28 +0100 Subject: [PATCH 04/26] SKALED-1425 Update consensus --- libconsensus | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libconsensus b/libconsensus index 9c10f8749..2d3a3fe6c 160000 --- a/libconsensus +++ b/libconsensus @@ -1 +1 @@ -Subproject commit 9c10f87494b751ebcf0dffa2e20590bffa5cbde9 +Subproject commit 2d3a3fe6c2c38ce9562d9f98a6dd34e28aaa3ec7 From f79c64f60278a0eaa2573e44181ed16a19f135d7 Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Thu, 18 May 2023 18:16:14 +0100 Subject: [PATCH 05/26] SKALED-1425 Simplify termination calls in skaled --- skaled/main.cpp | 48 +----------------------------------------------- 1 file changed, 1 insertion(+), 47 deletions(-) diff --git a/skaled/main.cpp b/skaled/main.cpp index 2b702e068..99693560b 100644 --- a/skaled/main.cpp +++ b/skaled/main.cpp @@ -344,47 +344,6 @@ get_machine_ip_addresses_6() { // first-interface name, second-address static std::unique_ptr< Client > g_client; unique_ptr< ModularServer<> > g_jsonrpcIpcServer; -static volatile bool g_bStopActionsStarted = false; -static volatile bool g_bStopActionsComplete = false; - -static void stat_handle_stop_actions() { - if ( g_bStopActionsStarted ) - return; - g_bStopActionsStarted = true; - std::thread( [&]() { - skale::network::browser::refreshing_stop(); - /* - if ( g_jsonrpcIpcServer.get() ) { - std::cerr << ( "\n" + cc::fatal( "SIGNAL-HANDLER:" ) + " " + - cc::error( "Will stop RPC server now..." ) + "\n\n" ); - g_jsonrpcIpcServer->StopListening(); - g_jsonrpcIpcServer.reset( nullptr ); - std::cerr << ( "\n" + cc::fatal( "SIGNAL-HANDLER:" ) + " " + - cc::error( "Did stopped RPC server" ) + "\n\n" ); - } - */ - if ( g_client ) { - std::cerr << ( "\n" + cc::fatal( "SIGNAL-HANDLER:" ) + " " + - cc::error( "Will stop client now..." ) + "\n\n" ); - g_client->stopWorking(); - std::cerr << ( "\n" + cc::fatal( "SIGNAL-HANDLER:" ) + " " + - cc::error( "Did stopped client" ) + "\n\n" ); - } - g_bStopActionsComplete = true; - } ).detach(); -} - -static void stat_wait_stop_actions_complete() { - if ( g_bStopActionsComplete ) - return; - std::cerr << ( "\n" + cc::fatal( "SIGNAL-HANDLER:" ) + " " + - cc::error( "Will wait for stop actions complete..." ) + "\n\n" ); - while ( !g_bStopActionsComplete ) - std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); - std::cerr << ( "\n" + cc::fatal( "SIGNAL-HANDLER:" ) + " " + - cc::error( "Done waiting for stop actions] complete" ) + "\n\n" ); -} - static void stat_init_common_signal_handling() { skutils::signal::init_common_signal_handling( []( int nSignalNo ) -> void { std::string strMessagePrefix = skutils::signal::g_bStop ? @@ -424,8 +383,6 @@ static void stat_init_common_signal_handling() { break; } // switch - stat_handle_stop_actions(); - // try to exit nicely - then abort if ( !skutils::signal::g_bStop ) { static volatile bool g_bSelfKillStarted = false; @@ -2860,7 +2817,7 @@ int main( int argc, char** argv ) try { } skale::network::browser::refreshing_start( - configPath.string(), []() -> bool { return g_bStopActionsStarted; } ); + configPath.string(), []() -> bool { return ExitHandler::shouldExit(); } ); dev::setThreadName( "main" ); if ( g_client ) { @@ -2893,9 +2850,6 @@ int main( int argc, char** argv ) try { ( basename + ".html" ).c_str(), ( basename + ".csv" ).c_str(), nullptr ); MicroProfileShutdown(); - stat_handle_stop_actions(); - stat_wait_stop_actions_complete(); - // clog( VerbosityDebug, "main" ) << cc::debug( "Stopping task dispatcher..." ); // skutils::dispatch::shutdown(); // clog( VerbosityDebug, "main" ) << cc::debug( "Done, task dispatcher stopped" ); From 0777c298c2b8be6b9e0b228336636d327b901f80 Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Mon, 22 May 2023 17:20:36 +0100 Subject: [PATCH 06/26] SKALED-1425 New exit in consensus and no network-browser --- libconsensus | 2 +- libethereum/ValidationSchemes.cpp | 2 -- skaled/main.cpp | 25 +------------------------ 3 files changed, 2 insertions(+), 27 deletions(-) diff --git a/libconsensus b/libconsensus index 2d3a3fe6c..bbdb37e54 160000 --- a/libconsensus +++ b/libconsensus @@ -1 +1 @@ -Subproject commit 2d3a3fe6c2c38ce9562d9f98a6dd34e28aaa3ec7 +Subproject commit bbdb37e54c3329cfc108b7e0ccd66b952088abd9 diff --git a/libethereum/ValidationSchemes.cpp b/libethereum/ValidationSchemes.cpp index 6db14c81e..190431541 100644 --- a/libethereum/ValidationSchemes.cpp +++ b/libethereum/ValidationSchemes.cpp @@ -201,8 +201,6 @@ void validateConfigJson( js::mObject const& _obj ) { { "log-tx-params-limit", { { js::int_type }, JsonFieldPresence::Optional } }, { "no-ima-signing", { { js::bool_type }, JsonFieldPresence::Optional } }, { "skale-manager", { { js::obj_type }, JsonFieldPresence::Optional } }, - { "skale-network-browser-refresh", { { js::int_type }, JsonFieldPresence::Optional } }, - { "skale-network-browser-verbose", { { js::bool_type }, JsonFieldPresence::Optional } }, { "imaMainNet", { { js::str_type }, JsonFieldPresence::Optional } }, { "imaMessageProxySChain", { { js::str_type }, JsonFieldPresence::Optional } }, { "imaMessageProxyMainNet", { { js::str_type }, JsonFieldPresence::Optional } }, diff --git a/skaled/main.cpp b/skaled/main.cpp index 13d8f2b05..7dc974b6c 100644 --- a/skaled/main.cpp +++ b/skaled/main.cpp @@ -70,7 +70,6 @@ #include #include #include -#include #include #include #include @@ -932,13 +931,6 @@ int main( int argc, char** argv ) try { addClientOption( "sgx-url", po::value< string >()->value_name( "" ), "SGX server url" ); - addClientOption( "skale-network-browser-verbose", - "Turn on very detailed logging in SKALE NETWORK BROWSER\n" ); - addClientOption( "skale-network-browser-refresh", - po::value< size_t >()->value_name( "" ), - "Refresh time(in seconds) which SKALE NETWORK BROWSER will re-load all S-Chain " - "descriptions from Skale Manager" ); - // skale - snapshot download command addClientOption( "download-snapshot", po::value< string >()->value_name( "" ), "Download snapshot from other skaled node specified by web3/json-rpc url" ); @@ -1153,9 +1145,7 @@ int main( int argc, char** argv ) try { } std::cout << cc::bright( "skaled " ) << cc::sunny( Version ) << "\n" - << cc::bright( "client " ) << clientVersionColorized() << "\n" - << cc::debug( "Recent build intent is " ) - << cc::info( "5029, SKALE NETWORK BROWSER improvements" ) << "\n"; + << cc::bright( "client " ) << clientVersionColorized() << "\n"; std::cout.flush(); version(); @@ -1676,14 +1666,6 @@ int main( int argc, char** argv ) try { chainParams.nodeInfo.sgxServerUrl = strURL; } - if ( vm.count( "skale-network-browser-verbose" ) ) { - skale::network::browser::g_bVerboseLogging = true; - } - if ( vm.count( "skale-network-browser-refresh" ) ) { - skale::network::browser::g_nRefreshIntervalInSeconds = - vm["skale-network-browser-refresh"].as< size_t >(); - } - std::shared_ptr< SharedSpace > sharedSpace; if ( vm.count( "shared-space-path" ) ) { try { @@ -2887,9 +2869,6 @@ int main( int argc, char** argv ) try { << cc::debug( "Done, programmatic shutdown via Web3 is disabled" ); } - skale::network::browser::refreshing_start( - configPath.string(), []() -> bool { return ExitHandler::shouldExit(); } ); - dev::setThreadName( "main" ); if ( g_client ) { unsigned int n = g_client->blockChain().details().number; @@ -2901,8 +2880,6 @@ int main( int argc, char** argv ) try { this_thread::sleep_for( chrono::milliseconds( 1000 ) ); } - skale::network::browser::refreshing_stop(); - if ( g_jsonrpcIpcServer.get() ) { g_jsonrpcIpcServer->StopListening(); g_jsonrpcIpcServer.reset( nullptr ); From 8e6073d69f39ea33c60394a8acc1aa08cff59525 Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Mon, 22 May 2023 19:34:06 +0100 Subject: [PATCH 07/26] SKALED-1425 Refactoring signal handling --- libdevcore/Common.cpp | 32 ++++++++++-------------------- libdevcore/Common.h | 8 ++++---- libskutils/include/skutils/utils.h | 3 --- libskutils/src/utils.cpp | 3 --- skaled/main.cpp | 19 +++++++++++------- 5 files changed, 27 insertions(+), 38 deletions(-) diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index 26ad77d2b..daf0d8973 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -34,13 +34,11 @@ char const* Version = skale_get_buildinfo()->project_version; bytes const NullBytes; std::string const EmptyString; -std::shared_ptr< StatusAndControl > ExitHandler::statusAndControl; - bool ExitHandler::shouldExit() { - return skutils::signal::g_bStop; + return s_bStop; } int ExitHandler::getSignal() { - return skutils::signal::g_nStopSignal; + return s_nStopSignal; } void ExitHandler::exitHandler( int s ) { @@ -48,27 +46,17 @@ void ExitHandler::exitHandler( int s ) { } void ExitHandler::exitHandler( int s, ExitHandler::exit_code_t ec ) { - skutils::signal::g_nStopSignal = s; + s_nStopSignal = s; if ( ec != ec_success ) { - g_ec = ec; + s_ec = ec; } // indicate failure if signal is not INT or TERM! - if ( g_ec == ec_success && s != SIGINT && s != SIGTERM ) - g_ec = ExitHandler::ec_failure; - - if ( statusAndControl ) { - statusAndControl->setExitState( StatusAndControl::StartAgain, ( g_ec != ec_success ) ); - statusAndControl->setExitState( - StatusAndControl::StartFromSnapshot, ( g_ec == ec_state_root_mismatch ) ); - statusAndControl->setExitState( - StatusAndControl::ClearDataDir, ( g_ec == ec_state_root_mismatch ) ); - } // if - - skutils::signal::g_bStop = true; - // HACK wait for loop in main to send exit call to consensus et al. - std::this_thread::sleep_for( chrono::milliseconds( 2000 ) ); + if ( s_ec == ec_success && s != SIGINT && s != SIGTERM ) + s_ec = ExitHandler::ec_failure; + + s_bStop = true; } void InvariantChecker::checkInvariants( @@ -126,6 +114,8 @@ string inUnits( bigint const& _b, strings const& _units ) { return ret.str(); } -volatile ExitHandler::exit_code_t ExitHandler::g_ec = ExitHandler::ec_success; +std::atomic< ExitHandler::exit_code_t > ExitHandler::s_ec = ExitHandler::ec_success; +std::atomic_int ExitHandler::s_nStopSignal{ 0 }; +std::atomic_bool ExitHandler::s_bStop{ false }; } // namespace dev diff --git a/libdevcore/Common.h b/libdevcore/Common.h index 2706a4614..cc8e4bcec 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -353,12 +353,12 @@ class ExitHandler { static void exitHandler( int s, ExitHandler::exit_code_t ec ); static bool shouldExit(); static int getSignal(); - static exit_code_t requestedExitCode() { return g_ec; } - - static std::shared_ptr< StatusAndControl > statusAndControl; + static exit_code_t requestedExitCode() { return s_ec; } private: - static volatile exit_code_t g_ec; + static std::atomic< exit_code_t > s_ec; + static std::atomic_int s_nStopSignal; + static std::atomic_bool s_bStop; ExitHandler() = delete; }; diff --git a/libskutils/include/skutils/utils.h b/libskutils/include/skutils/utils.h index 722761ffe..a2841964b 100644 --- a/libskutils/include/skutils/utils.h +++ b/libskutils/include/skutils/utils.h @@ -580,9 +580,6 @@ extern char getch_no_wait(); namespace signal { -extern std::atomic_int g_nStopSignal; -extern std::atomic_bool g_bStop; - extern bool get_signal_description( int nSignalNo, std::string& strSignalName, std::string& strSignalDescription ); // returns true if signal name is known extern std::string signal2str( int nSignalNo, const char* strPrefix = nullptr, diff --git a/libskutils/src/utils.cpp b/libskutils/src/utils.cpp index 1c398316c..2c1b4b808 100644 --- a/libskutils/src/utils.cpp +++ b/libskutils/src/utils.cpp @@ -1300,9 +1300,6 @@ char getch_no_wait() { namespace signal { -std::atomic_int g_nStopSignal{ 0 }; -std::atomic_bool g_bStop{ false }; - bool get_signal_description( int nSignalNo, std::string& strSignalName, std::string& strSignalDescription ) { // returns true if signal name is known struct sig_desc_t { diff --git a/skaled/main.cpp b/skaled/main.cpp index 7dc974b6c..c73d4f53d 100644 --- a/skaled/main.cpp +++ b/skaled/main.cpp @@ -553,7 +553,7 @@ unique_ptr< ModularServer<> > g_jsonrpcIpcServer; static void stat_init_common_signal_handling() { skutils::signal::init_common_signal_handling( []( int nSignalNo ) -> void { - std::string strMessagePrefix = skutils::signal::g_bStop ? + std::string strMessagePrefix = ExitHandler::shouldExit() ? cc::error( "\nStop flag was already raised on. " ) + cc::fatal( "WILL FORCE TERMINATE." ) + cc::error( " Caught (second) signal. " ) : @@ -591,7 +591,7 @@ static void stat_init_common_signal_handling() { } // switch // try to exit nicely - then abort - if ( !skutils::signal::g_bStop ) { + if ( !ExitHandler::shouldExit() ) { static volatile bool g_bSelfKillStarted = false; if ( !g_bSelfKillStarted ) { g_bSelfKillStarted = true; @@ -653,15 +653,12 @@ static void stat_init_common_signal_handling() { // nice exit here: - if ( skutils::signal::g_bStop ) { + if ( ExitHandler::shouldExit() ) { std::cerr << ( "\n" + cc::fatal( "SIGNAL-HANDLER:" ) + " " + cc::error( "Will force exit now..." ) + "\n\n" ); _exit( 13 ); } - skutils::signal::g_bStop = true; - skutils::signal::g_nStopSignal = nSignalNo; - dev::ExitHandler::exitHandler( nSignalNo ); } ); } @@ -1221,7 +1218,6 @@ int main( int argc, char** argv ) try { std::shared_ptr< StatusAndControl > statusAndControl = std::make_shared< StatusAndControlFile >( boost::filesystem::path( configPath ).remove_filename() ); - ExitHandler::statusAndControl = statusAndControl; // for now, leave previous values in file (for case of crash) if ( vm.count( "main-net-url" ) ) { @@ -2880,6 +2876,15 @@ int main( int argc, char** argv ) try { this_thread::sleep_for( chrono::milliseconds( 1000 ) ); } + if ( statusAndControl ) { + statusAndControl->setExitState( StatusAndControl::StartAgain, + ( ExitHandler::requestedExitCode() != ExitHandler::ec_success ) ); + statusAndControl->setExitState( StatusAndControl::StartFromSnapshot, + ( ExitHandler::requestedExitCode() == ExitHandler::ec_state_root_mismatch ) ); + statusAndControl->setExitState( StatusAndControl::ClearDataDir, + ( ExitHandler::requestedExitCode() == ExitHandler::ec_state_root_mismatch ) ); + } // if + if ( g_jsonrpcIpcServer.get() ) { g_jsonrpcIpcServer->StopListening(); g_jsonrpcIpcServer.reset( nullptr ); From 526e8cf350c52b9347ac7f92037c9b2f7a50ab2f Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Tue, 23 May 2023 17:09:25 +0100 Subject: [PATCH 08/26] SKALED-1425 Single signal/exit handler --- libdevcore/Common.cpp | 112 +++++++++++++++++++++++++++- {skaled => libdevcore}/taskmon.cpp | 0 {skaled => libdevcore}/taskmon.h | 0 skaled/main.cpp | 116 +---------------------------- 4 files changed, 110 insertions(+), 118 deletions(-) rename {skaled => libdevcore}/taskmon.cpp (100%) rename {skaled => libdevcore}/taskmon.h (100%) diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index daf0d8973..7c7ea9761 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -20,6 +20,7 @@ #include "Common.h" #include "Exceptions.h" #include "Log.h" +#include "taskmon.h" #include @@ -45,15 +46,120 @@ void ExitHandler::exitHandler( int s ) { exitHandler( s, ec_success ); } -void ExitHandler::exitHandler( int s, ExitHandler::exit_code_t ec ) { - s_nStopSignal = s; +void ExitHandler::exitHandler( int nSignalNo, ExitHandler::exit_code_t ec ) { + std::string strMessagePrefix = ExitHandler::shouldExit() ? + cc::error( "\nStop flag was already raised on. " ) + + cc::fatal( "WILL FORCE TERMINATE." ) + + cc::error( " Caught (second) signal. " ) : + cc::error( "\nCaught (first) signal. " ); + std::cerr << strMessagePrefix << cc::error( skutils::signal::signal2str( nSignalNo ) ) + << "\n\n"; + std::cerr.flush(); + + switch ( nSignalNo ) { + case SIGINT: + case SIGTERM: + case SIGHUP: + // exit normally + // just fall through + break; + + case SIGSTOP: + case SIGTSTP: + case SIGPIPE: + // ignore + return; + break; + + case SIGQUIT: + // exit immediately + _exit( ExitHandler::ec_termninated_by_signal ); + break; + + default: + // abort signals + std::cout << "\n" << skutils::signal::generate_stack_trace() << "\n"; + std::cout.flush(); + + break; + } // switch + + // try to exit nicely - then abort + if ( !ExitHandler::shouldExit() ) { + static volatile bool g_bSelfKillStarted = false; + if ( !g_bSelfKillStarted ) { + g_bSelfKillStarted = true; + + auto start_time = std::chrono::steady_clock::now(); + + std::thread( [nSignalNo, start_time]() { + std::cerr << ( "\n" + cc::fatal( "SELF-KILL:" ) + " " + cc::error( "Will sleep " ) + + cc::size10( ExitHandler::KILL_TIMEOUT ) + + cc::error( " seconds before force exit..." ) + "\n\n" ); + std::cerr.flush(); + + clog( VerbosityInfo, "exit" ) << "THREADS timer started"; + + // while waiting, every 0.1s check whch threades exited + vector< string > threads; + for ( int i = 0; i < ExitHandler::KILL_TIMEOUT * 10; ++i ) { + auto end_time = std::chrono::steady_clock::now(); + float seconds = std::chrono::duration< float >( end_time - start_time ).count(); + + try { + vector< string > new_threads = taskmon::list_names(); + vector< string > threads_diff = taskmon::lists_diff( threads, new_threads ); + threads = new_threads; + + if ( threads_diff.size() ) { + cerr << seconds << " THREADS " << threads.size() << ":"; + for ( const string& t : threads_diff ) + cerr << " " << t; + cerr << endl; + } + } catch ( ... ) { + // swallow it + } + + std::this_thread::sleep_for( 100ms ); + } + + std::cerr << ( "\n" + cc::fatal( "SELF-KILL:" ) + " " + + cc::error( "Will force exit after sleeping " ) + + cc::size10( ExitHandler::KILL_TIMEOUT ) + cc::error( " second(s)" ) + + "\n\n" ); + std::cerr.flush(); + + // TODO deduplicate this with main() before return + ExitHandler::exit_code_t ec = ExitHandler::requestedExitCode(); + if ( ec == ExitHandler::ec_success ) { + if ( nSignalNo != SIGINT && nSignalNo != SIGTERM ) + ec = ExitHandler::ec_failure; + } + + _exit( ec ); + } ).detach(); + } // if( ! g_bSelfKillStarted ) + } // if ( !skutils::signal::g_bStop ) + + // nice exit here: + + if ( ExitHandler::shouldExit() ) { + std::cerr << ( "\n" + cc::fatal( "SIGNAL-HANDLER:" ) + " " + + cc::error( "Will force exit now..." ) + "\n\n" ); + _exit( 13 ); + } + + dev::ExitHandler::exitHandler( nSignalNo ); + + s_nStopSignal = nSignalNo; if ( ec != ec_success ) { s_ec = ec; } // indicate failure if signal is not INT or TERM! - if ( s_ec == ec_success && s != SIGINT && s != SIGTERM ) + if ( s_ec == ec_success && nSignalNo != SIGINT && nSignalNo != SIGTERM ) s_ec = ExitHandler::ec_failure; s_bStop = true; diff --git a/skaled/taskmon.cpp b/libdevcore/taskmon.cpp similarity index 100% rename from skaled/taskmon.cpp rename to libdevcore/taskmon.cpp diff --git a/skaled/taskmon.h b/libdevcore/taskmon.h similarity index 100% rename from skaled/taskmon.h rename to libdevcore/taskmon.h diff --git a/skaled/main.cpp b/skaled/main.cpp index c73d4f53d..8dea6b1a8 100644 --- a/skaled/main.cpp +++ b/skaled/main.cpp @@ -101,8 +101,6 @@ #include #include -#include "taskmon.h" - using namespace std; using namespace dev; using namespace dev::p2p; @@ -551,118 +549,6 @@ get_machine_ip_addresses_6() { // first-interface name, second-address static std::unique_ptr< Client > g_client; unique_ptr< ModularServer<> > g_jsonrpcIpcServer; -static void stat_init_common_signal_handling() { - skutils::signal::init_common_signal_handling( []( int nSignalNo ) -> void { - std::string strMessagePrefix = ExitHandler::shouldExit() ? - cc::error( "\nStop flag was already raised on. " ) + - cc::fatal( "WILL FORCE TERMINATE." ) + - cc::error( " Caught (second) signal. " ) : - cc::error( "\nCaught (first) signal. " ); - std::cerr << strMessagePrefix << cc::error( skutils::signal::signal2str( nSignalNo ) ) - << "\n\n"; - std::cerr.flush(); - - switch ( nSignalNo ) { - case SIGINT: - case SIGTERM: - case SIGHUP: - // exit normally - // just fall through - break; - - case SIGSTOP: - case SIGTSTP: - case SIGPIPE: - // ignore - return; - break; - - case SIGQUIT: - // exit immediately - _exit( ExitHandler::ec_termninated_by_signal ); - break; - - default: - // abort signals - std::cout << "\n" << skutils::signal::generate_stack_trace() << "\n"; - std::cout.flush(); - - break; - } // switch - - // try to exit nicely - then abort - if ( !ExitHandler::shouldExit() ) { - static volatile bool g_bSelfKillStarted = false; - if ( !g_bSelfKillStarted ) { - g_bSelfKillStarted = true; - - auto start_time = std::chrono::steady_clock::now(); - - std::thread( [nSignalNo, start_time]() { - std::cerr << ( "\n" + cc::fatal( "SELF-KILL:" ) + " " + - cc::error( "Will sleep " ) + - cc::size10( ExitHandler::KILL_TIMEOUT ) + - cc::error( " seconds before force exit..." ) + "\n\n" ); - std::cerr.flush(); - - clog( VerbosityInfo, "exit" ) << "THREADS timer started"; - - // while waiting, every 0.1s check whch threades exited - vector< string > threads; - for ( int i = 0; i < ExitHandler::KILL_TIMEOUT * 10; ++i ) { - auto end_time = std::chrono::steady_clock::now(); - float seconds = - std::chrono::duration< float >( end_time - start_time ).count(); - - try { - vector< string > new_threads = taskmon::list_names(); - vector< string > threads_diff = - taskmon::lists_diff( threads, new_threads ); - threads = new_threads; - - if ( threads_diff.size() ) { - cerr << seconds << " THREADS " << threads.size() << ":"; - for ( const string& t : threads_diff ) - cerr << " " << t; - cerr << endl; - } - } catch ( ... ) { - // swallow it - } - - std::this_thread::sleep_for( 100ms ); - } - - std::cerr << ( "\n" + cc::fatal( "SELF-KILL:" ) + " " + - cc::error( "Will force exit after sleeping " ) + - cc::size10( ExitHandler::KILL_TIMEOUT ) + - cc::error( " second(s)" ) + "\n\n" ); - std::cerr.flush(); - - // TODO deduplicate this with main() before return - ExitHandler::exit_code_t ec = ExitHandler::requestedExitCode(); - if ( ec == ExitHandler::ec_success ) { - if ( nSignalNo != SIGINT && nSignalNo != SIGTERM ) - ec = ExitHandler::ec_failure; - } - - _exit( ec ); - } ).detach(); - } // if( ! g_bSelfKillStarted ) - } // if ( !skutils::signal::g_bStop ) - - // nice exit here: - - if ( ExitHandler::shouldExit() ) { - std::cerr << ( "\n" + cc::fatal( "SIGNAL-HANDLER:" ) + " " + - cc::error( "Will force exit now..." ) + "\n\n" ); - _exit( 13 ); - } - - dev::ExitHandler::exitHandler( nSignalNo ); - } ); -} - int main( int argc, char** argv ) try { cc::_on_ = false; cc::_max_value_size_ = 2048; @@ -670,7 +556,7 @@ int main( int argc, char** argv ) try { BlockHeader::useTimestampHack = false; srand( time( nullptr ) ); setCLocale(); - stat_init_common_signal_handling(); // ensure initialized + skutils::signal::init_common_signal_handling( ExitHandler::exitHandler ); bool isExposeAllDebugInfo = false; // Init secp256k1 context by calling one of the functions. From 98ee437f8ba84e309836cfbdf10aa1d644f0e5bd Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Thu, 25 May 2023 17:29:26 +0100 Subject: [PATCH 09/26] SKALED-1425 No unneeded recursion at exit --- libdevcore/Common.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index 7c7ea9761..87ce9e760 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -150,8 +150,6 @@ void ExitHandler::exitHandler( int nSignalNo, ExitHandler::exit_code_t ec ) { _exit( 13 ); } - dev::ExitHandler::exitHandler( nSignalNo ); - s_nStopSignal = nSignalNo; if ( ec != ec_success ) { From b5106e2c3bfcc4840ef3ba28b5c330f3e31c8681 Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Mon, 29 May 2023 19:04:11 +0100 Subject: [PATCH 10/26] SKALED-1425 Refactor snapshot hash calculation --- libdevcore/Common.h | 2 +- libethereum/Client.cpp | 218 ++------------------ libethereum/Client.h | 56 ++--- libskale/SnapshotManager.cpp | 13 +- libskale/SnapshotManager.h | 18 +- skaled/main.cpp | 3 +- test/unittests/libskale/SnapshotManager.cpp | 8 +- 7 files changed, 56 insertions(+), 262 deletions(-) diff --git a/libdevcore/Common.h b/libdevcore/Common.h index cc8e4bcec..ce40987fd 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -336,7 +336,7 @@ int64_t utcTime(); class ExitHandler { public: - enum { KILL_TIMEOUT = 60 * 4 + 30 }; + enum { KILL_TIMEOUT = 60 }; // * 4 + 30 }; enum exit_code_t { ec_success = 0, diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index c7dfd41df..56c07ed95 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -26,12 +26,14 @@ #include "Defaults.h" #include "Executive.h" #include "SkaleHost.h" +#include "SnapshotAgent.h" #include "SnapshotStorage.h" #include "TransactionQueue.h" #include #include #include +#include #include #include @@ -129,7 +131,8 @@ Client::Client( ChainParams const& _params, int _networkID, m_preSeal( chainParams().accountStartNonce ), m_postSeal( chainParams().accountStartNonce ), m_working( chainParams().accountStartNonce ), - m_snapshotManager( _snapshotManager ), + m_snapshotAgent( make_shared< SnapshotAgent >( + _params.sChain.snapshotIntervalSec, _snapshotManager, m_debugTracer ) ), m_instanceMonitor( _instanceMonitor ), m_dbPath( _dbPath ) { #if ( defined __HAVE_SKALED_LOCK_FILE_INDICATING_CRITICAL_STOP__ ) @@ -141,7 +144,6 @@ Client::Client( ChainParams const& _params, int _networkID, << "TRACEPOINT " << name << " " << m_debugTracer.get_tracepoint_count( name ); } ); - m_debugHandler = [this]( const std::string& arg ) -> std::string { return DebugTracer_handler( arg, this->m_debugTracer ); }; @@ -174,13 +176,7 @@ void Client::stopWorking() { else cerror << "Instance of SkaleHost was not properly created."; - if ( m_snapshotHashComputing != nullptr ) { - try { - if ( m_snapshotHashComputing->joinable() ) - m_snapshotHashComputing->join(); - } catch ( ... ) { - } - } + m_snapshotAgent->terminate(); m_new_block_watch.uninstallAll(); m_new_pending_transaction_watch.uninstallAll(); @@ -306,14 +302,6 @@ void Client::init( WithExisting _forceAction, u256 _networkId ) { if ( m_dbPath.size() ) Defaults::setDBPath( m_dbPath ); - if ( chainParams().sChain.snapshotIntervalSec > 0 ) { - LOG( m_logger ) << "Snapshots enabled, snapshotIntervalSec is: " - << chainParams().sChain.snapshotIntervalSec; - if ( number() == 0 ) - doSnapshotAndComputeHash( 0 ); - initHashes(); - } - if ( ChainParams().sChain.nodeGroups.size() > 0 ) initIMABLSPublicKey(); @@ -321,6 +309,8 @@ void Client::init( WithExisting _forceAction, u256 _networkId ) { AmsterdamFixPatch::isEnabled( *this ); doWork( false ); + + m_snapshotAgent->init( number(), m_bc.info().timestamp() ); } ImportResult Client::queueBlock( bytes const& _block, bool _isSafe ) { @@ -528,44 +518,9 @@ size_t Client::importTransactionsAsBlock( const Transactions& _transactions, u256 _gasPrice, uint64_t _timestamp ) { // HACK here was m_blockImportMutex - but now it is acquired in SkaleHost!!! // TODO decouple Client and SkaleHost - int64_t snapshotIntervalSec = chainParams().sChain.snapshotIntervalSec; - // init last block creation time with only robust time source - timestamp of 1st block! - if ( number() == 0 ) { - last_snapshot_creation_time = _timestamp; - LOG( m_logger ) << "Init last snapshot creation time: " - << this->last_snapshot_creation_time; - } else if ( snapshotIntervalSec > 0 && this->isTimeToDoSnapshot( _timestamp ) ) { - LOG( m_logger ) << "Last snapshot creation time: " << this->last_snapshot_creation_time; - - if ( m_snapshotHashComputing != nullptr && m_snapshotHashComputing->joinable() ) - m_snapshotHashComputing->join(); - - // TODO Make this number configurable - // thread can be absent - if hash was already there - // snapshot can be absent too - // but hash cannot be absent - auto latest_snapshots = this->m_snapshotManager->getLatestSnasphots(); - if ( latest_snapshots.second ) { - assert( m_snapshotManager->isSnapshotHashPresent( latest_snapshots.second ) ); - this->last_snapshoted_block_with_hash = latest_snapshots.second; - m_snapshotManager->leaveNLastSnapshots( 2 ); - } - - // also there might be snapshot on disk - // and it's time to make it "last with hash" - if ( last_snapshoted_block_with_hash == 0 ) { - auto latest_snapshots = this->m_snapshotManager->getLatestSnasphots(); - if ( latest_snapshots.second ) { - uint64_t time_of_second = - blockInfo( this->hashFromNumber( latest_snapshots.second ) ).timestamp(); - if ( time_of_second == ( ( uint64_t ) last_snapshot_creation_time ) ) - this->last_snapshoted_block_with_hash = latest_snapshots.second; - } // if second - } // if == 0 - } + m_snapshotAgent->finishHashComputingAndUpdateHashesIfNeeded( number(), _timestamp ); - // // begin, detect partially executed block bool bIsPartial = false; dev::h256 shaLastTx = m_state.safeLastExecutedTransactionHash(); @@ -644,74 +599,7 @@ size_t Client::importTransactionsAsBlock( if ( chainParams().sChain.nodeGroups.size() > 0 ) updateIMABLSPublicKey(); - if ( snapshotIntervalSec > 0 ) { - unsigned block_number = this->number(); - - LOG( m_loggerDetail ) << "Block timestamp: " << _timestamp; - - if ( this->isTimeToDoSnapshot( _timestamp ) ) { - try { - boost::chrono::high_resolution_clock::time_point t1; - boost::chrono::high_resolution_clock::time_point t2; - LOG( m_logger ) << "DOING SNAPSHOT: " << block_number; - m_debugTracer.tracepoint( "doing_snapshot" ); - - t1 = boost::chrono::high_resolution_clock::now(); - m_snapshotManager->doSnapshot( block_number ); - t2 = boost::chrono::high_resolution_clock::now(); - this->snapshot_calculation_time_ms = - boost::chrono::duration_cast< boost::chrono::milliseconds >( t2 - t1 ).count(); - } catch ( SnapshotManager::SnapshotPresent& ex ) { - cerror << "WARNING " << dev::nested_exception_what( ex ); - } - - this->last_snapshot_creation_time = _timestamp; - - LOG( m_logger ) << "New snapshot creation time: " << this->last_snapshot_creation_time; - } - - // snapshots without hash can appear either from start, from downloading or from just - // creation - auto latest_snapshots = this->m_snapshotManager->getLatestSnasphots(); - - // start if thread is free and there is work - if ( ( m_snapshotHashComputing == nullptr || !m_snapshotHashComputing->joinable() ) && - latest_snapshots.second && - !m_snapshotManager->isSnapshotHashPresent( latest_snapshots.second ) ) { - m_snapshotHashComputing.reset( new std::thread( [this, latest_snapshots]() { - m_debugTracer.tracepoint( "computeSnapshotHash_start" ); - try { - boost::chrono::high_resolution_clock::time_point t1; - boost::chrono::high_resolution_clock::time_point t2; - - t1 = boost::chrono::high_resolution_clock::now(); - this->m_snapshotManager->computeSnapshotHash( latest_snapshots.second ); - t2 = boost::chrono::high_resolution_clock::now(); - this->snapshot_hash_calculation_time_ms = - boost::chrono::duration_cast< boost::chrono::milliseconds >( t2 - t1 ) - .count(); - LOG( m_logger ) - << "Computed hash for snapshot " << latest_snapshots.second << ": " - << m_snapshotManager->getSnapshotHash( latest_snapshots.second ); - m_debugTracer.tracepoint( "computeSnapshotHash_end" ); - - } catch ( const std::exception& ex ) { - cerror << cc::fatal( "CRITICAL" ) << " " - << cc::warn( dev::nested_exception_what( ex ) ) - << cc::error( " in computeSnapshotHash(). Exiting..." ); - cerror << "\n" << skutils::signal::generate_stack_trace() << "\n" << std::endl; - ExitHandler::exitHandler( SIGABRT, ExitHandler::ec_compute_snapshot_error ); - } catch ( ... ) { - cerror << cc::fatal( "CRITICAL" ) - << cc::error( - " unknown exception in computeSnapshotHash(). " - "Exiting..." ); - cerror << "\n" << skutils::signal::generate_stack_trace() << "\n" << std::endl; - ExitHandler::exitHandler( SIGABRT, ExitHandler::ec_compute_snapshot_error ); - } - } ) ); - } // if thread - } // if snapshots enabled + m_snapshotAgent->doSnapshotIfNeeded( number(), _timestamp ); // TEMPRORARY FIX! // TODO: REVIEW @@ -859,12 +747,6 @@ void Client::resetState() { onTransactionQueueReady(); } -bool Client::isTimeToDoSnapshot( uint64_t _timestamp ) const { - int snapshotIntervalSec = chainParams().sChain.snapshotIntervalSec; - return _timestamp / uint64_t( snapshotIntervalSec ) > - this->last_snapshot_creation_time / uint64_t( snapshotIntervalSec ); -} - void Client::setSchainExitTime( uint64_t _timestamp ) const { m_instanceMonitor->initRotationParams( _timestamp ); } @@ -924,9 +806,9 @@ void Client::rejigSealing() { // TODO Deduplicate code! dev::h256 stateRootToSet; - if ( this->last_snapshoted_block_with_hash > 0 ) { - dev::h256 state_root_hash = - this->m_snapshotManager->getSnapshotHash( last_snapshoted_block_with_hash ); + if ( m_snapshotAgent->getLatestSnapshotBlockNumer() > 0 ) { + dev::h256 state_root_hash = this->m_snapshotAgent->getSnapshotHash( + m_snapshotAgent->getLatestSnapshotBlockNumer() ); stateRootToSet = state_root_hash; } // propagate current! @@ -980,9 +862,9 @@ void Client::sealUnconditionally( bool submitToBlockChain ) { // latest hash is really updated after NEXT snapshot already started hash computation! // TODO Deduplicate code! dev::h256 stateRootToSet; - if ( this->last_snapshoted_block_with_hash > 0 ) { - dev::h256 state_root_hash = - this->m_snapshotManager->getSnapshotHash( last_snapshoted_block_with_hash ); + if ( m_snapshotAgent->getLatestSnapshotBlockNumer() > 0 ) { + dev::h256 state_root_hash = this->m_snapshotAgent->getSnapshotHash( + m_snapshotAgent->getLatestSnapshotBlockNumer() ); stateRootToSet = state_root_hash; } // propagate current! @@ -1378,76 +1260,6 @@ ExecutionResult Client::call( Address const& _from, u256 _value, Address _dest, return ret; } -void Client::doSnapshotAndComputeHash( unsigned _blockNumber ) { - LOG( m_logger ) << "DOING SNAPSHOT: " << _blockNumber; - m_debugTracer.tracepoint( "doing_snapshot" ); - - try { - m_snapshotManager->doSnapshot( _blockNumber ); - } catch ( SnapshotManager::SnapshotPresent& ex ) { - LOG( m_logger ) << "0 block snapshot is already present. Skipping."; - return; - } - - m_snapshotManager->computeSnapshotHash( _blockNumber ); - LOG( m_logger ) << "Computed hash for snapshot " << _blockNumber << ": " - << m_snapshotManager->getSnapshotHash( _blockNumber ); - m_debugTracer.tracepoint( "computeSnapshotHash_end" ); -} - -void Client::initHashes() { - int snapshotIntervalSec = chainParams().sChain.snapshotIntervalSec; - assert( snapshotIntervalSec > 0 ); - ( void ) snapshotIntervalSec; - - auto latest_snapshots = this->m_snapshotManager->getLatestSnasphots(); - - // if two - if ( latest_snapshots.first ) { - assert( latest_snapshots.first != 1 ); // 1 can never be snapshotted - - this->last_snapshoted_block_with_hash = latest_snapshots.first; - - // ignore second as it was "in hash computation" - // check that both are imported!! - // h256 h2 = this->hashFromNumber( latest_snapshots.second ); - // assert( h2 != h256() ); - // last_snapshot_creation_time = blockInfo( h2 ).timestamp(); - - last_snapshot_creation_time = - this->m_snapshotManager->getBlockTimestamp( latest_snapshots.second, chainParams() ); - - // one snapshot - } else if ( latest_snapshots.second ) { - assert( latest_snapshots.second != 1 ); // 1 can never be snapshotted - assert( this->number() > 0 ); // we created snapshot somehow - - // whether it is local or downloaded - we shall ignore it's hash but use it's time - // see also how last_snapshoted_block_with_hash is updated in importTransactionsAsBlock - // h256 h2 = this->hashFromNumber( latest_snapshots.second ); - // uint64_t time_of_second = blockInfo( h2 ).timestamp(); - - this->last_snapshoted_block_with_hash = -1; - // last_snapshot_creation_time = time_of_second; - - last_snapshot_creation_time = - this->m_snapshotManager->getBlockTimestamp( latest_snapshots.second, chainParams() ); - - // no snapshots yet - } else { - this->last_snapshoted_block_with_hash = -1; - - if ( this->number() >= 1 ) - last_snapshot_creation_time = blockInfo( this->hashFromNumber( 1 ) ).timestamp(); - else - this->last_snapshot_creation_time = 0; - } - - LOG( m_logger ) << "Latest snapshots init: " << latest_snapshots.first << " " - << latest_snapshots.second << " -> " << this->last_snapshoted_block_with_hash; - LOG( m_logger ) << "Fake Last snapshot creation time: " << last_snapshot_creation_time; -} - void Client::initIMABLSPublicKey() { if ( number() == 0 ) { imaBLSPublicKeyGroupIndex = 0; diff --git a/libethereum/Client.h b/libethereum/Client.h index 662ed9a6d..0bc7fd3ee 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -43,7 +43,6 @@ #include #include #include -#include #include #include "Block.h" @@ -52,6 +51,7 @@ #include "CommonNet.h" #include "InstanceMonitor.h" #include "SkaleHost.h" +#include "SnapshotAgent.h" #include "StateImporter.h" #include "ThreadSafeQueue.h" @@ -59,6 +59,7 @@ #include class ConsensusHost; +class SnapshotManager; namespace dev { namespace eth { @@ -268,41 +269,30 @@ class Client : public ClientBase, protected Worker { uint64_t _timestamp = ( uint64_t ) utcTime() ); boost::filesystem::path createSnapshotFile( unsigned _blockNumber ) { - if ( _blockNumber > this->getLatestSnapshotBlockNumer() && _blockNumber != 0 ) - throw std::invalid_argument( "Too new snapshot requested" ); - boost::filesystem::path path = m_snapshotManager->makeOrGetDiff( _blockNumber ); - // TODO Make constant 2 configurable - m_snapshotManager->leaveNLastDiffs( 2 ); - return path; + return m_snapshotAgent->createSnapshotFile( _blockNumber ); } // set exiting time for node rotation void setSchainExitTime( uint64_t _timestamp ) const; dev::h256 getSnapshotHash( unsigned _blockNumber ) const { - if ( _blockNumber > this->last_snapshoted_block_with_hash && _blockNumber != 0 ) - return dev::h256(); - - try { - dev::h256 res = this->m_snapshotManager->getSnapshotHash( _blockNumber ); - return res; - } catch ( const SnapshotManager::SnapshotAbsent& ) { - return dev::h256(); - } - - // fall through other exceptions + return m_snapshotAgent->getSnapshotHash( _blockNumber ); } uint64_t getBlockTimestampFromSnapshot( unsigned _blockNumber ) const { - return this->m_snapshotManager->getBlockTimestamp( _blockNumber, chainParams() ); + return m_snapshotAgent->getBlockTimestampFromSnapshot( _blockNumber ); } - int64_t getLatestSnapshotBlockNumer() const { return this->last_snapshoted_block_with_hash; } + int64_t getLatestSnapshotBlockNumer() const { + return m_snapshotAgent->getLatestSnapshotBlockNumer(); + } - uint64_t getSnapshotCalculationTime() const { return this->snapshot_calculation_time_ms; } + uint64_t getSnapshotCalculationTime() const { + return m_snapshotAgent->getSnapshotCalculationTime(); + } uint64_t getSnapshotHashCalculationTime() const { - return this->snapshot_hash_calculation_time_ms; + return m_snapshotAgent->getSnapshotHashCalculationTime(); } std::array< std::string, 4 > getIMABLSPublicKey() const { @@ -529,31 +519,17 @@ class Client : public ClientBase, protected Worker { Logger m_logger{ createLogger( VerbosityInfo, "client" ) }; Logger m_loggerDetail{ createLogger( VerbosityTrace, "client" ) }; + SkaleDebugTracer m_debugTracer; + SkaleDebugInterface::handler m_debugHandler; /// skale std::shared_ptr< SkaleHost > m_skaleHost; - std::shared_ptr< SnapshotManager > m_snapshotManager; + std::shared_ptr< SnapshotAgent > m_snapshotAgent; + const static dev::h256 empty_str_hash; std::shared_ptr< InstanceMonitor > m_instanceMonitor; fs::path m_dbPath; - SkaleDebugTracer m_debugTracer; - SkaleDebugInterface::handler m_debugHandler; - private: - inline bool isTimeToDoSnapshot( uint64_t _timestamp ) const; - void initHashes(); - void doSnapshotAndComputeHash( unsigned _blockNumber ); - - std::unique_ptr< std::thread > m_snapshotHashComputing; - // time of last physical snapshot - int64_t last_snapshot_creation_time = 0; - // usually this is snapshot before last! - int64_t last_snapshoted_block_with_hash = -1; - const static dev::h256 empty_str_hash; - - uint64_t snapshot_calculation_time_ms; - uint64_t snapshot_hash_calculation_time_ms; - void initIMABLSPublicKey(); void updateIMABLSPublicKey(); diff --git a/libskale/SnapshotManager.cpp b/libskale/SnapshotManager.cpp index 5fd0464d5..583e6d849 100644 --- a/libskale/SnapshotManager.cpp +++ b/libskale/SnapshotManager.cpp @@ -54,8 +54,10 @@ const std::string SnapshotManager::snapshot_hash_file_name = "snapshot_hash.txt" // - bad data dir // - not btrfs // - volumes don't exist -SnapshotManager::SnapshotManager( const fs::path& _dataDir, - const std::vector< std::string >& _volumes, const std::string& _diffsDir ) { +SnapshotManager::SnapshotManager( const dev::eth::ChainParams& _chain_params, + const fs::path& _dataDir, const std::vector< std::string >& _volumes, + const std::string& _diffsDir ) + : chain_params( _chain_params ) { assert( _volumes.size() > 0 ); data_dir = _dataDir; @@ -335,7 +337,7 @@ void SnapshotManager::leaveNLastSnapshots( unsigned n ) { } // for } -std::pair< int, int > SnapshotManager::getLatestSnasphots() const { +std::pair< int, int > SnapshotManager::getLatestSnapshots() const { map< int, fs::path, std::greater< int > > numbers; for ( auto& f : fs::directory_iterator( snapshots_dir ) ) { // HACK We exclude 0 snapshot forcefully @@ -490,6 +492,8 @@ void SnapshotManager::proceedRegularFile( std::string relativePath = path.string().substr( path.string().find( "filestorage" ) ); + cerr << path << endl; + std::string fileHashPathStr = path.string() + "._hash"; if ( !is_checking ) { dev::h256 fileHash; @@ -692,8 +696,7 @@ void SnapshotManager::computeSnapshotHash( unsigned _blockNumber, bool is_checki } } -uint64_t SnapshotManager::getBlockTimestamp( - unsigned _blockNumber, const dev::eth::ChainParams& chain_params ) const { +uint64_t SnapshotManager::getBlockTimestamp( unsigned _blockNumber ) const { fs::path snapshot_dir = snapshots_dir / to_string( _blockNumber ); try { diff --git a/libskale/SnapshotManager.h b/libskale/SnapshotManager.h index 2dd15280b..26aa1d411 100644 --- a/libskale/SnapshotManager.h +++ b/libskale/SnapshotManager.h @@ -22,8 +22,8 @@ * @date 2019 */ -#ifndef SNAPSHOTAGENT_H -#define SNAPSHOTAGENT_H +#ifndef SNAPSHOTMANAGER_H +#define SNAPSHOTMANAGER_H #include #include @@ -152,8 +152,9 @@ class SnapshotManager { /////////////// MORE INTERESTING STUFF //////////////// public: - SnapshotManager( const boost::filesystem::path& _dataDir, - const std::vector< std::string >& _volumes, const std::string& diffs_dir = std::string() ); + SnapshotManager( const dev::eth::ChainParams& _chain_params, + const boost::filesystem::path& _dataDir, const std::vector< std::string >& _volumes, + const std::string& diffs_dir = std::string() ); void doSnapshot( unsigned _blockNumber ); void restoreSnapshot( unsigned _blockNumber ); boost::filesystem::path makeOrGetDiff( unsigned _toBlock ); @@ -167,12 +168,11 @@ class SnapshotManager { void leaveNLastDiffs( unsigned n ); dev::h256 getSnapshotHash( unsigned _blockNumber ) const; - std::pair< int, int > getLatestSnasphots() const; + std::pair< int, int > getLatestSnapshots() const; bool isSnapshotHashPresent( unsigned _blockNumber ) const; void computeSnapshotHash( unsigned _blockNumber, bool is_checking = false ); - uint64_t getBlockTimestamp( - unsigned _blockNumber, const dev::eth::ChainParams& chain_params ) const; + uint64_t getBlockTimestamp( unsigned _blockNumber ) const; static boost::filesystem::path findMostRecentBlocksDBPath( const boost::filesystem::path& _dirPath ); @@ -186,6 +186,8 @@ class SnapshotManager { static const std::string snapshot_hash_file_name; mutable std::mutex hash_file_mutex; + dev::eth::ChainParams chain_params; + void cleanupDirectory( const boost::filesystem::path& p, const boost::filesystem::path& _keepDirectory = "" ); @@ -203,4 +205,4 @@ class SnapshotManager { void addLastPriceToHash( unsigned _blockNumber, secp256k1_sha256_t* ctx ) const; }; -#endif // SNAPSHOTAGENT_H +#endif // SNAPSHOTMANAGER_H diff --git a/skaled/main.cpp b/skaled/main.cpp index 8dea6b1a8..125294774 100644 --- a/skaled/main.cpp +++ b/skaled/main.cpp @@ -57,6 +57,7 @@ #include #include +#include #include #include @@ -1576,7 +1577,7 @@ int main( int argc, char** argv ) try { // auto mostRecentBlocksDBPath = (getDataDir() / ( "blocks_" + chainParams.nodeInfo.id.str() // + ".db" )) / "1.db"; - snapshotManager.reset( new SnapshotManager( getDataDir(), + snapshotManager.reset( new SnapshotManager( chainParams, getDataDir(), { BlockChain::getChainDirName( chainParams ), "filestorage", "prices_" + chainParams.nodeInfo.id.str() + ".db", "blocks_" + chainParams.nodeInfo.id.str() + ".db"/*, diff --git a/test/unittests/libskale/SnapshotManager.cpp b/test/unittests/libskale/SnapshotManager.cpp index b3d46dc1a..deac87f23 100644 --- a/test/unittests/libskale/SnapshotManager.cpp +++ b/test/unittests/libskale/SnapshotManager.cpp @@ -168,7 +168,7 @@ BOOST_FIXTURE_TEST_CASE( SimplePositiveTest, BtrfsFixture, BOOST_REQUIRE( fs::exists( fs::path( BTRFS_DIR_PATH ) / "vol1" / "d11" ) ); BOOST_REQUIRE( fs::exists( fs::path( BTRFS_DIR_PATH ) / "vol2" / "d21" ) ); - auto latest0 = mgr.getLatestSnasphots(); + auto latest0 = mgr.getLatestSnapshots(); std::pair< int, int > expected0 { 0, 0 }; BOOST_REQUIRE( latest0 == expected0 ); @@ -183,7 +183,7 @@ BOOST_FIXTURE_TEST_CASE( SimplePositiveTest, BtrfsFixture, BOOST_REQUIRE( fs::exists( fs::path( BTRFS_DIR_PATH ) / "vol1" / "d12" ) ); BOOST_REQUIRE( !fs::exists( fs::path( BTRFS_DIR_PATH ) / "vol2" / "d21" ) ); - auto latest1 = mgr.getLatestSnasphots(); + auto latest1 = mgr.getLatestSnapshots(); std::pair< int, int > expected1 { 0, 1 }; BOOST_REQUIRE( latest1 == expected1 ); @@ -215,12 +215,12 @@ BOOST_FIXTURE_TEST_CASE( SimplePositiveTest, BtrfsFixture, BOOST_REQUIRE( fs::exists( fs::path( BTRFS_DIR_PATH ) / "vol1" / "d12" ) ); BOOST_REQUIRE( !fs::exists( fs::path( BTRFS_DIR_PATH ) / "vol2" / "d21" ) ); - auto latest2 = mgr.getLatestSnasphots(); + auto latest2 = mgr.getLatestSnapshots(); std::pair< int, int > expected2 { 1, 2 }; BOOST_REQUIRE( latest2 == expected2 ); mgr.doSnapshot( 3 ); - auto latest3 = mgr.getLatestSnasphots(); + auto latest3 = mgr.getLatestSnapshots(); std::pair< int, int > expected3 { 2, 3 }; BOOST_REQUIRE( latest3 == expected3 ); From f064b89074783e65b9489fe0e8e4d555ee3e46bb Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Mon, 29 May 2023 19:41:08 +0100 Subject: [PATCH 11/26] SKALED-1425 SnapshotAgent --- libethereum/SnapshotAgent.cpp | 230 ++++++++++++++++++++++++++++++++++ libethereum/SnapshotAgent.h | 64 ++++++++++ 2 files changed, 294 insertions(+) create mode 100644 libethereum/SnapshotAgent.cpp create mode 100644 libethereum/SnapshotAgent.h diff --git a/libethereum/SnapshotAgent.cpp b/libethereum/SnapshotAgent.cpp new file mode 100644 index 000000000..f7a9d00ca --- /dev/null +++ b/libethereum/SnapshotAgent.cpp @@ -0,0 +1,230 @@ +#include "SnapshotAgent.h" + +#include + +#include + +#include + +using namespace dev; + +SnapshotAgent::SnapshotAgent( int64_t _snapshotIntervalSec, + std::shared_ptr< SnapshotManager > _snapshotManager, SkaleDebugTracer& _debugTracer ) + : m_snapshotIntervalSec( _snapshotIntervalSec ), + m_snapshotManager( _snapshotManager ), + m_debugTracer( _debugTracer ) { + if ( m_snapshotIntervalSec > 0 ) { + LOG( m_logger ) << "Snapshots enabled, snapshotIntervalSec is: " << m_snapshotIntervalSec; + } +} + +void SnapshotAgent::finishHashComputingAndUpdateHashesIfNeeded( + unsigned block_number, uint64_t _timestamp ) { + // init last block creation time with only robust time source - timestamp of 1st block! + if ( block_number == 0 ) { + last_snapshot_creation_time = _timestamp; + LOG( m_logger ) << "Init last snapshot creation time: " + << this->last_snapshot_creation_time; + } else if ( m_snapshotIntervalSec > 0 && this->isTimeToDoSnapshot( _timestamp ) ) { + LOG( m_logger ) << "Last snapshot creation time: " << this->last_snapshot_creation_time; + + if ( m_snapshotHashComputing != nullptr && m_snapshotHashComputing->joinable() ) { + m_snapshotHashComputing->join(); + this->last_snapshoted_block_with_hash = this->block_number_under_hash_computation; + this->block_number_under_hash_computation = -1; + } + + // TODO Make this number configurable + // thread can be absent - if hash was already there + // snapshot can be absent too + // but hash cannot be absent + auto latest_snapshots = this->m_snapshotManager->getLatestSnapshots(); + if ( latest_snapshots.second ) { + assert( m_snapshotManager->isSnapshotHashPresent( latest_snapshots.second ) ); + this->last_snapshoted_block_with_hash = latest_snapshots.second; + m_snapshotManager->leaveNLastSnapshots( 2 ); + } + } +} + +void SnapshotAgent::doSnapshotIfNeeded( unsigned block_number, uint64_t _timestamp ) { + if ( m_snapshotIntervalSec <= 0 ) + return; + + LOG( m_loggerDetail ) << "Block timestamp: " << _timestamp; + + if ( this->isTimeToDoSnapshot( _timestamp ) ) { + try { + boost::chrono::high_resolution_clock::time_point t1; + boost::chrono::high_resolution_clock::time_point t2; + LOG( m_logger ) << "DOING SNAPSHOT: " << block_number; + m_debugTracer.tracepoint( "doing_snapshot" ); + + t1 = boost::chrono::high_resolution_clock::now(); + m_snapshotManager->doSnapshot( block_number ); + t2 = boost::chrono::high_resolution_clock::now(); + this->snapshot_calculation_time_ms = + boost::chrono::duration_cast< boost::chrono::milliseconds >( t2 - t1 ).count(); + } catch ( SnapshotManager::SnapshotPresent& ex ) { + cerror << "WARNING " << dev::nested_exception_what( ex ); + } + + this->last_snapshot_creation_time = _timestamp; + + LOG( m_logger ) << "New snapshot creation time: " << this->last_snapshot_creation_time; + } + + // snapshots without hash can appear either from start, from downloading or from just + // creation + auto latest_snapshots = this->m_snapshotManager->getLatestSnapshots(); + + // start if thread is free and there is work + if ( ( m_snapshotHashComputing == nullptr || !m_snapshotHashComputing->joinable() ) && + latest_snapshots.second && + !m_snapshotManager->isSnapshotHashPresent( latest_snapshots.second ) ) { + block_number_under_hash_computation = latest_snapshots.second; + m_snapshotHashComputing.reset( new std::thread( [this]() { + m_debugTracer.tracepoint( "computeSnapshotHash_start" ); + try { + boost::chrono::high_resolution_clock::time_point t1; + boost::chrono::high_resolution_clock::time_point t2; + + t1 = boost::chrono::high_resolution_clock::now(); + this->m_snapshotManager->computeSnapshotHash( + this->block_number_under_hash_computation ); + t2 = boost::chrono::high_resolution_clock::now(); + this->snapshot_hash_calculation_time_ms = + boost::chrono::duration_cast< boost::chrono::milliseconds >( t2 - t1 ).count(); + LOG( m_logger ) << "Computed hash for snapshot " + << this->block_number_under_hash_computation << ": " + << m_snapshotManager->getSnapshotHash( + this->block_number_under_hash_computation ); + m_debugTracer.tracepoint( "computeSnapshotHash_end" ); + + } catch ( const std::exception& ex ) { + cerror << cc::fatal( "CRITICAL" ) << " " + << cc::warn( dev::nested_exception_what( ex ) ) + << cc::error( " in computeSnapshotHash(). Exiting..." ); + cerror << "\n" << skutils::signal::generate_stack_trace() << "\n" << std::endl; + ExitHandler::exitHandler( SIGABRT, ExitHandler::ec_compute_snapshot_error ); + } catch ( ... ) { + cerror << cc::fatal( "CRITICAL" ) + << cc::error( + " unknown exception in computeSnapshotHash(). " + "Exiting..." ); + cerror << "\n" << skutils::signal::generate_stack_trace() << "\n" << std::endl; + ExitHandler::exitHandler( SIGABRT, ExitHandler::ec_compute_snapshot_error ); + } + } ) ); + } // if thread +} + +boost::filesystem::path SnapshotAgent::createSnapshotFile( unsigned _blockNumber ) { + if ( _blockNumber > this->getLatestSnapshotBlockNumer() && _blockNumber != 0 ) + throw std::invalid_argument( "Too new snapshot requested" ); + boost::filesystem::path path = m_snapshotManager->makeOrGetDiff( _blockNumber ); + // TODO Make constant 2 configurable + m_snapshotManager->leaveNLastDiffs( 2 ); + return path; +} + +void SnapshotAgent::terminate() { + if ( m_snapshotHashComputing != nullptr ) { + try { + if ( m_snapshotHashComputing->joinable() ) + m_snapshotHashComputing->join(); + } catch ( ... ) { + } + } +} + +dev::h256 SnapshotAgent::getSnapshotHash( unsigned _blockNumber ) const { + if ( _blockNumber > this->last_snapshoted_block_with_hash && _blockNumber != 0 ) + return dev::h256(); + + try { + dev::h256 res = this->m_snapshotManager->getSnapshotHash( _blockNumber ); + return res; + } catch ( const SnapshotManager::SnapshotAbsent& ) { + return dev::h256(); + } + + // fall through other exceptions +} + +uint64_t SnapshotAgent::getBlockTimestampFromSnapshot( unsigned _blockNumber ) const { + return this->m_snapshotManager->getBlockTimestamp( _blockNumber ); +} + +void SnapshotAgent::doSnapshotAndComputeHash( unsigned _blockNumber ) { + LOG( m_logger ) << "DOING SNAPSHOT: " << _blockNumber; + m_debugTracer.tracepoint( "doing_snapshot" ); + + try { + m_snapshotManager->doSnapshot( _blockNumber ); + } catch ( SnapshotManager::SnapshotPresent& ex ) { + LOG( m_logger ) << "0 block snapshot is already present. Skipping."; + return; + } + + m_snapshotManager->computeSnapshotHash( _blockNumber ); + LOG( m_logger ) << "Computed hash for snapshot " << _blockNumber << ": " + << m_snapshotManager->getSnapshotHash( _blockNumber ); + m_debugTracer.tracepoint( "computeSnapshotHash_end" ); +} + +void SnapshotAgent::init( unsigned _currentBlockNumber, int64_t _currentBlockTime ) { + if ( m_snapshotIntervalSec < 0 ) + return; + + if ( _currentBlockNumber == 0 ) + doSnapshotAndComputeHash( 0 ); + + auto latest_snapshots = this->m_snapshotManager->getLatestSnapshots(); + + // if two + if ( latest_snapshots.first ) { + assert( latest_snapshots.first != 1 ); // 1 can never be snapshotted + + this->last_snapshoted_block_with_hash = latest_snapshots.first; + + // ignore second as it was "in hash computation" + // check that both are imported!! + // h256 h2 = this->hashFromNumber( latest_snapshots.second ); + // assert( h2 != h256() ); + // last_snapshot_creation_time = blockInfo( h2 ).timestamp(); + + last_snapshot_creation_time = + this->m_snapshotManager->getBlockTimestamp( latest_snapshots.second ); + + // one snapshot + } else if ( latest_snapshots.second ) { + assert( latest_snapshots.second != 1 ); // 1 can never be snapshotted + assert( _currentBlockTime > 0 ); // we created snapshot somehow + + // whether it is local or downloaded - we shall ignore it's hash but use it's time + // see also how last_snapshoted_block_with_hash is updated in importTransactionsAsBlock + // h256 h2 = this->hashFromNumber( latest_snapshots.second ); + // uint64_t time_of_second = blockInfo( h2 ).timestamp(); + + this->last_snapshoted_block_with_hash = -1; + // last_snapshot_creation_time = time_of_second; + + last_snapshot_creation_time = + this->m_snapshotManager->getBlockTimestamp( latest_snapshots.second ); + + // no snapshots yet + } else { + this->last_snapshoted_block_with_hash = -1; + last_snapshot_creation_time = _currentBlockTime; + } + + LOG( m_logger ) << "Latest snapshots init: " << latest_snapshots.first << " " + << latest_snapshots.second << " -> " << this->last_snapshoted_block_with_hash; + LOG( m_logger ) << "Fake Last snapshot creation time: " << last_snapshot_creation_time; +} + +bool SnapshotAgent::isTimeToDoSnapshot( uint64_t _timestamp ) const { + return _timestamp / uint64_t( m_snapshotIntervalSec ) > + this->last_snapshot_creation_time / uint64_t( m_snapshotIntervalSec ); +} diff --git a/libethereum/SnapshotAgent.h b/libethereum/SnapshotAgent.h new file mode 100644 index 000000000..98099ab50 --- /dev/null +++ b/libethereum/SnapshotAgent.h @@ -0,0 +1,64 @@ +#ifndef SNAPSHOTAGENT_H +#define SNAPSHOTAGENT_H + +#include +#include + +#include + +#include +#include + +class SnapshotManager; + +// Knows all about snapshots and maintains all dynamic behavior related to them: +// - keeping time of snapshot creation +// - hash computation +// - serialization +class SnapshotAgent { +public: + SnapshotAgent( int64_t _snapshotIntervalSec, + std::shared_ptr< SnapshotManager > _snapshotManager, SkaleDebugTracer& _debugTracer ); + + void init( unsigned _currentBlockNumber, int64_t _currentBlockTime ); + + void finishHashComputingAndUpdateHashesIfNeeded( unsigned block_number, uint64_t _timestamp ); + void doSnapshotIfNeeded( unsigned block_number, uint64_t _timestamp ); + + boost::filesystem::path createSnapshotFile( unsigned _blockNumber ); + + void terminate(); + + dev::h256 getSnapshotHash( unsigned _blockNumber ) const; + uint64_t getBlockTimestampFromSnapshot( unsigned _blockNumber ) const; + int64_t getLatestSnapshotBlockNumer() const { return this->last_snapshoted_block_with_hash; } + uint64_t getSnapshotCalculationTime() const { return this->snapshot_calculation_time_ms; } + uint64_t getSnapshotHashCalculationTime() const { + return this->snapshot_hash_calculation_time_ms; + } + +private: + int64_t m_snapshotIntervalSec; + std::shared_ptr< SnapshotManager > m_snapshotManager; + + inline bool isTimeToDoSnapshot( uint64_t _timestamp ) const; + void doSnapshotAndComputeHash( unsigned _blockNumber ); + + std::unique_ptr< std::thread > m_snapshotHashComputing; + uint64_t block_number_under_hash_computation = -1; + + // time of last physical snapshot + int64_t last_snapshot_creation_time = 0; + // usually this is snapshot before last! + int64_t last_snapshoted_block_with_hash = -1; + + uint64_t snapshot_calculation_time_ms; + uint64_t snapshot_hash_calculation_time_ms; + + dev::Logger m_logger{ createLogger( dev::VerbosityInfo, "SnapshotAgent" ) }; + dev::Logger m_loggerDetail{ createLogger( dev::VerbosityTrace, "SnapshotAgent" ) }; + + SkaleDebugTracer& m_debugTracer; +}; + +#endif // SNAPSHOTAGENT_H From 2834771955a16decdfa2389073273d6add48d86c Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Tue, 30 May 2023 18:29:13 +0100 Subject: [PATCH 12/26] SKALED-1425 Bug fixes --- libdevcore/Common.h | 2 +- libethereum/SnapshotAgent.cpp | 81 +++++++++++---------- libethereum/SnapshotAgent.h | 2 +- libskale/SnapshotManager.cpp | 2 - test/unittests/libethereum/ClientTest.cpp | 3 +- test/unittests/libskale/HashSnapshot.cpp | 2 +- test/unittests/libskale/SnapshotManager.cpp | 28 +++---- 7 files changed, 62 insertions(+), 58 deletions(-) diff --git a/libdevcore/Common.h b/libdevcore/Common.h index ce40987fd..cc8e4bcec 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -336,7 +336,7 @@ int64_t utcTime(); class ExitHandler { public: - enum { KILL_TIMEOUT = 60 }; // * 4 + 30 }; + enum { KILL_TIMEOUT = 60 * 4 + 30 }; enum exit_code_t { ec_success = 0, diff --git a/libethereum/SnapshotAgent.cpp b/libethereum/SnapshotAgent.cpp index f7a9d00ca..a8f63fbed 100644 --- a/libethereum/SnapshotAgent.cpp +++ b/libethereum/SnapshotAgent.cpp @@ -28,11 +28,8 @@ void SnapshotAgent::finishHashComputingAndUpdateHashesIfNeeded( } else if ( m_snapshotIntervalSec > 0 && this->isTimeToDoSnapshot( _timestamp ) ) { LOG( m_logger ) << "Last snapshot creation time: " << this->last_snapshot_creation_time; - if ( m_snapshotHashComputing != nullptr && m_snapshotHashComputing->joinable() ) { + if ( m_snapshotHashComputing != nullptr && m_snapshotHashComputing->joinable() ) m_snapshotHashComputing->join(); - this->last_snapshoted_block_with_hash = this->block_number_under_hash_computation; - this->block_number_under_hash_computation = -1; - } // TODO Make this number configurable // thread can be absent - if hash was already there @@ -82,40 +79,8 @@ void SnapshotAgent::doSnapshotIfNeeded( unsigned block_number, uint64_t _timesta if ( ( m_snapshotHashComputing == nullptr || !m_snapshotHashComputing->joinable() ) && latest_snapshots.second && !m_snapshotManager->isSnapshotHashPresent( latest_snapshots.second ) ) { - block_number_under_hash_computation = latest_snapshots.second; - m_snapshotHashComputing.reset( new std::thread( [this]() { - m_debugTracer.tracepoint( "computeSnapshotHash_start" ); - try { - boost::chrono::high_resolution_clock::time_point t1; - boost::chrono::high_resolution_clock::time_point t2; - - t1 = boost::chrono::high_resolution_clock::now(); - this->m_snapshotManager->computeSnapshotHash( - this->block_number_under_hash_computation ); - t2 = boost::chrono::high_resolution_clock::now(); - this->snapshot_hash_calculation_time_ms = - boost::chrono::duration_cast< boost::chrono::milliseconds >( t2 - t1 ).count(); - LOG( m_logger ) << "Computed hash for snapshot " - << this->block_number_under_hash_computation << ": " - << m_snapshotManager->getSnapshotHash( - this->block_number_under_hash_computation ); - m_debugTracer.tracepoint( "computeSnapshotHash_end" ); - - } catch ( const std::exception& ex ) { - cerror << cc::fatal( "CRITICAL" ) << " " - << cc::warn( dev::nested_exception_what( ex ) ) - << cc::error( " in computeSnapshotHash(). Exiting..." ); - cerror << "\n" << skutils::signal::generate_stack_trace() << "\n" << std::endl; - ExitHandler::exitHandler( SIGABRT, ExitHandler::ec_compute_snapshot_error ); - } catch ( ... ) { - cerror << cc::fatal( "CRITICAL" ) - << cc::error( - " unknown exception in computeSnapshotHash(). " - "Exiting..." ); - cerror << "\n" << skutils::signal::generate_stack_trace() << "\n" << std::endl; - ExitHandler::exitHandler( SIGABRT, ExitHandler::ec_compute_snapshot_error ); - } - } ) ); + startHashComputingThread(); + } // if thread } @@ -197,6 +162,9 @@ void SnapshotAgent::init( unsigned _currentBlockNumber, int64_t _currentBlockTim last_snapshot_creation_time = this->m_snapshotManager->getBlockTimestamp( latest_snapshots.second ); + if ( !m_snapshotManager->isSnapshotHashPresent( latest_snapshots.second ) ) + startHashComputingThread(); + // one snapshot } else if ( latest_snapshots.second ) { assert( latest_snapshots.second != 1 ); // 1 can never be snapshotted @@ -213,6 +181,9 @@ void SnapshotAgent::init( unsigned _currentBlockNumber, int64_t _currentBlockTim last_snapshot_creation_time = this->m_snapshotManager->getBlockTimestamp( latest_snapshots.second ); + if ( !m_snapshotManager->isSnapshotHashPresent( latest_snapshots.second ) ) + startHashComputingThread(); + // no snapshots yet } else { this->last_snapshoted_block_with_hash = -1; @@ -228,3 +199,37 @@ bool SnapshotAgent::isTimeToDoSnapshot( uint64_t _timestamp ) const { return _timestamp / uint64_t( m_snapshotIntervalSec ) > this->last_snapshot_creation_time / uint64_t( m_snapshotIntervalSec ); } + +void SnapshotAgent::startHashComputingThread() { + auto latest_snapshots = this->m_snapshotManager->getLatestSnapshots(); + + m_snapshotHashComputing.reset( new std::thread( [this, latest_snapshots]() { + m_debugTracer.tracepoint( "computeSnapshotHash_start" ); + try { + boost::chrono::high_resolution_clock::time_point t1; + boost::chrono::high_resolution_clock::time_point t2; + + t1 = boost::chrono::high_resolution_clock::now(); + this->m_snapshotManager->computeSnapshotHash( latest_snapshots.second ); + t2 = boost::chrono::high_resolution_clock::now(); + this->snapshot_hash_calculation_time_ms = + boost::chrono::duration_cast< boost::chrono::milliseconds >( t2 - t1 ).count(); + LOG( m_logger ) << "Computed hash for snapshot " << latest_snapshots.second << ": " + << m_snapshotManager->getSnapshotHash( latest_snapshots.second ); + m_debugTracer.tracepoint( "computeSnapshotHash_end" ); + + } catch ( const std::exception& ex ) { + cerror << cc::fatal( "CRITICAL" ) << " " << cc::warn( dev::nested_exception_what( ex ) ) + << cc::error( " in computeSnapshotHash(). Exiting..." ); + cerror << "\n" << skutils::signal::generate_stack_trace() << "\n" << std::endl; + ExitHandler::exitHandler( SIGABRT, ExitHandler::ec_compute_snapshot_error ); + } catch ( ... ) { + cerror << cc::fatal( "CRITICAL" ) + << cc::error( + " unknown exception in computeSnapshotHash(). " + "Exiting..." ); + cerror << "\n" << skutils::signal::generate_stack_trace() << "\n" << std::endl; + ExitHandler::exitHandler( SIGABRT, ExitHandler::ec_compute_snapshot_error ); + } + } ) ); +} diff --git a/libethereum/SnapshotAgent.h b/libethereum/SnapshotAgent.h index 98099ab50..cd8a76e8c 100644 --- a/libethereum/SnapshotAgent.h +++ b/libethereum/SnapshotAgent.h @@ -43,9 +43,9 @@ class SnapshotAgent { inline bool isTimeToDoSnapshot( uint64_t _timestamp ) const; void doSnapshotAndComputeHash( unsigned _blockNumber ); + void startHashComputingThread(); std::unique_ptr< std::thread > m_snapshotHashComputing; - uint64_t block_number_under_hash_computation = -1; // time of last physical snapshot int64_t last_snapshot_creation_time = 0; diff --git a/libskale/SnapshotManager.cpp b/libskale/SnapshotManager.cpp index 583e6d849..36d05fcbd 100644 --- a/libskale/SnapshotManager.cpp +++ b/libskale/SnapshotManager.cpp @@ -492,8 +492,6 @@ void SnapshotManager::proceedRegularFile( std::string relativePath = path.string().substr( path.string().find( "filestorage" ) ); - cerr << path << endl; - std::string fileHashPathStr = path.string() + "._hash"; if ( !is_checking ) { dev::h256 fileHash; diff --git a/test/unittests/libethereum/ClientTest.cpp b/test/unittests/libethereum/ClientTest.cpp index 17dd8ad25..c49302cad 100644 --- a/test/unittests/libethereum/ClientTest.cpp +++ b/test/unittests/libethereum/ClientTest.cpp @@ -30,6 +30,7 @@ #include #include #include +#include using namespace std; using namespace dev; @@ -261,7 +262,7 @@ class TestClientSnapshotsFixture : public TestOutputHelperFixture, public Fixtur // ), dir, // dir, chainParams, WithExisting::Kill, {"eth"}, testingMode ) ); std::shared_ptr< SnapshotManager > mgr; - mgr.reset( new SnapshotManager( m_tmpDir.path(), { BlockChain::getChainDirName( chainParams ), "vol2", "filestorage"} ) ); + mgr.reset( new SnapshotManager( chainParams, m_tmpDir.path(), { BlockChain::getChainDirName( chainParams ), "vol2", "filestorage"} ) ); // boost::filesystem::create_directory( // m_tmpDir.path() / "vol1" / "12041" ); // boost::filesystem::create_directory( diff --git a/test/unittests/libskale/HashSnapshot.cpp b/test/unittests/libskale/HashSnapshot.cpp index 564f9dc41..77ca9f4fe 100644 --- a/test/unittests/libskale/HashSnapshot.cpp +++ b/test/unittests/libskale/HashSnapshot.cpp @@ -283,7 +283,7 @@ struct SnapshotHashingFixture : public TestOutputHelperFixture, public FixtureCo // "eth tests", tempDir.path(), "", chainParams, WithExisting::Kill, {"eth"}, // true ) ); - mgr.reset( new SnapshotManager( boost::filesystem::path( BTRFS_DIR_PATH ), + mgr.reset( new SnapshotManager( chainParams, boost::filesystem::path( BTRFS_DIR_PATH ), {BlockChain::getChainDirName( chainParams ), "filestorage"} ) ); boost::filesystem::create_directory( diff --git a/test/unittests/libskale/SnapshotManager.cpp b/test/unittests/libskale/SnapshotManager.cpp index deac87f23..a50951bf0 100644 --- a/test/unittests/libskale/SnapshotManager.cpp +++ b/test/unittests/libskale/SnapshotManager.cpp @@ -160,7 +160,7 @@ BOOST_AUTO_TEST_SUITE( BtrfsTestSuite, BOOST_FIXTURE_TEST_CASE( SimplePositiveTest, BtrfsFixture, *boost::unit_test::precondition( dev::test::run_not_express ) ) { - SnapshotManager mgr( fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); + SnapshotManager mgr( dev::eth::ChainParams(), fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); // add files 1 fs::create_directory( fs::path( BTRFS_DIR_PATH ) / "vol1" / "d11" ); @@ -231,14 +231,14 @@ BOOST_FIXTURE_TEST_CASE( SimplePositiveTest, BtrfsFixture, BOOST_FIXTURE_TEST_CASE( NoBtrfsTest, NoBtrfsFixture, *boost::unit_test::precondition( dev::test::run_not_express ) ) { - BOOST_REQUIRE_THROW( SnapshotManager mgr( fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ), + BOOST_REQUIRE_THROW( SnapshotManager mgr( dev::eth::ChainParams(), fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ), SnapshotManager::CannotPerformBtrfsOperation ); } BOOST_FIXTURE_TEST_CASE( BadPathTest, BtrfsFixture, *boost::unit_test::precondition( dev::test::run_not_express ) ) { BOOST_REQUIRE_EXCEPTION( - SnapshotManager mgr( fs::path( BTRFS_DIR_PATH ) / "_invalid", {"vol1", "vol2"} ), + SnapshotManager mgr( dev::eth::ChainParams(), fs::path( BTRFS_DIR_PATH ) / "_invalid", {"vol1", "vol2"} ), SnapshotManager::InvalidPath, [this]( const SnapshotManager::InvalidPath& ex ) -> bool { return ex.path == fs::path( BTRFS_DIR_PATH ) / "_invalid"; } ); @@ -267,17 +267,17 @@ BOOST_FIXTURE_TEST_CASE( InaccessiblePathTest, BtrfsFixture, dropRoot(); - BOOST_REQUIRE_EXCEPTION( SnapshotManager mgr( fs::path( BTRFS_DIR_PATH ) / "_no_w", {"vol1"} ), + BOOST_REQUIRE_EXCEPTION( SnapshotManager mgr( dev::eth::ChainParams(), fs::path( BTRFS_DIR_PATH ) / "_no_w", {"vol1"} ), SnapshotManager::CannotCreate, [this]( const SnapshotManager::CannotCreate& ex ) -> bool { return ex.path == fs::path( BTRFS_DIR_PATH ) / "_no_w" / "snapshots"; } ); - BOOST_REQUIRE_EXCEPTION( SnapshotManager mgr( fs::path( BTRFS_DIR_PATH ) / "_no_x", {"vol1"} ), + BOOST_REQUIRE_EXCEPTION( SnapshotManager mgr( dev::eth::ChainParams(), fs::path( BTRFS_DIR_PATH ) / "_no_x", {"vol1"} ), SnapshotManager::CannotCreate, [this]( const SnapshotManager::CannotCreate& ex ) -> bool { return ex.path == fs::path( BTRFS_DIR_PATH ) / "_no_x" / "snapshots"; } ); - BOOST_REQUIRE_EXCEPTION( SnapshotManager mgr( fs::path( BTRFS_DIR_PATH ) / "_no_r", {"vol1"} ), + BOOST_REQUIRE_EXCEPTION( SnapshotManager mgr( dev::eth::ChainParams(), fs::path( BTRFS_DIR_PATH ) / "_no_r", {"vol1"} ), SnapshotManager::CannotCreate, [this]( const SnapshotManager::CannotCreate& ex ) -> bool { return ex.path == fs::path( BTRFS_DIR_PATH ) / "_no_x" / "snapshots"; } ); @@ -285,7 +285,7 @@ BOOST_FIXTURE_TEST_CASE( InaccessiblePathTest, BtrfsFixture, BOOST_FIXTURE_TEST_CASE( SnapshotTest, BtrfsFixture, *boost::unit_test::precondition( dev::test::run_not_express ) ) { - SnapshotManager mgr( fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); + SnapshotManager mgr( dev::eth::ChainParams(), fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); BOOST_REQUIRE_NO_THROW( mgr.doSnapshot( 2 ) ); BOOST_REQUIRE_THROW( mgr.doSnapshot( 2 ), SnapshotManager::SnapshotPresent ); @@ -314,7 +314,7 @@ BOOST_FIXTURE_TEST_CASE( SnapshotTest, BtrfsFixture, BOOST_FIXTURE_TEST_CASE( RestoreTest, BtrfsFixture, *boost::unit_test::precondition( dev::test::run_not_express ) ) { - SnapshotManager mgr( fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); + SnapshotManager mgr( dev::eth::ChainParams(), fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); BOOST_REQUIRE_THROW( mgr.restoreSnapshot( 2 ), SnapshotManager::SnapshotAbsent ); @@ -330,7 +330,7 @@ BOOST_FIXTURE_TEST_CASE( RestoreTest, BtrfsFixture, BOOST_FIXTURE_TEST_CASE( DiffTest, BtrfsFixture, *boost::unit_test::precondition( dev::test::run_not_express ) ) { - SnapshotManager mgr( fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); + SnapshotManager mgr( dev::eth::ChainParams(), fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); mgr.doSnapshot( 2 ); fs::create_directory( fs::path( BTRFS_DIR_PATH ) / "vol1" / "dir" ); mgr.doSnapshot( 4 ); @@ -363,7 +363,7 @@ BOOST_FIXTURE_TEST_CASE( DiffTest, BtrfsFixture, BOOST_FIXTURE_TEST_CASE( ImportTest, BtrfsFixture, *boost::unit_test::precondition( dev::test::run_not_express ) ) { - SnapshotManager mgr( fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); + SnapshotManager mgr( dev::eth::ChainParams(), fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); BOOST_REQUIRE_THROW( mgr.importDiff( 8 ), SnapshotManager::InvalidPath ); @@ -400,7 +400,7 @@ BOOST_FIXTURE_TEST_CASE( ImportTest, BtrfsFixture, BOOST_FIXTURE_TEST_CASE( SnapshotRotationTest, BtrfsFixture, *boost::unit_test::precondition( dev::test::run_not_express ) ) { - SnapshotManager mgr( fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); + SnapshotManager mgr( dev::eth::ChainParams(), fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); BOOST_REQUIRE_NO_THROW( mgr.doSnapshot( 1 ) ); sleep( 1 ); @@ -421,7 +421,7 @@ BOOST_FIXTURE_TEST_CASE( SnapshotRotationTest, BtrfsFixture, BOOST_FIXTURE_TEST_CASE( DiffRotationTest, BtrfsFixture, *boost::unit_test::precondition( dev::test::run_not_express ) ) { - SnapshotManager mgr( fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); + SnapshotManager mgr( dev::eth::ChainParams(), fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); fs::path diff12 = mgr.getDiffPath( 2 ); { @@ -451,7 +451,7 @@ BOOST_FIXTURE_TEST_CASE( DiffRotationTest, BtrfsFixture, BOOST_FIXTURE_TEST_CASE( RemoveSnapshotTest, BtrfsFixture, *boost::unit_test::precondition( dev::test::run_not_express ) ) { - SnapshotManager mgr( fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); + SnapshotManager mgr( dev::eth::ChainParams(), fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); mgr.doSnapshot( 1 ); mgr.doSnapshot( 2 ); @@ -469,7 +469,7 @@ BOOST_FIXTURE_TEST_CASE( RemoveSnapshotTest, BtrfsFixture, BOOST_FIXTURE_TEST_CASE( CleanupTest, BtrfsFixture, *boost::unit_test::precondition( dev::test::run_not_express ) ) { - SnapshotManager mgr( fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); + SnapshotManager mgr( dev::eth::ChainParams(), fs::path( BTRFS_DIR_PATH ), {"vol1", "vol2"} ); mgr.doSnapshot( 1 ); mgr.doSnapshot( 2 ); From 33564142b6aa0d5cc4020d7d8dff18769327d60f Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Wed, 31 May 2023 15:30:04 +0100 Subject: [PATCH 13/26] SKALED-1425 SnapshotAgent little refactoring --- libethereum/Client.cpp | 10 +- libethereum/Client.h | 1 + libethereum/SnapshotAgent.cpp | 166 +++++++++++++++++----------------- libethereum/SnapshotAgent.h | 17 ++-- 4 files changed, 98 insertions(+), 96 deletions(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 56c07ed95..3a41b25b8 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -309,8 +309,6 @@ void Client::init( WithExisting _forceAction, u256 _networkId ) { AmsterdamFixPatch::isEnabled( *this ); doWork( false ); - - m_snapshotAgent->init( number(), m_bc.info().timestamp() ); } ImportResult Client::queueBlock( bytes const& _block, bool _isSafe ) { @@ -519,7 +517,13 @@ size_t Client::importTransactionsAsBlock( // HACK here was m_blockImportMutex - but now it is acquired in SkaleHost!!! // TODO decouple Client and SkaleHost - m_snapshotAgent->finishHashComputingAndUpdateHashesIfNeeded( number(), _timestamp ); + // on schain creation, SnapshotAgent needs timestamp of block 1 + // so we use this HACK + if ( !m_snapshotAgentInited ) { + m_snapshotAgent->init( number(), m_bc.info().timestamp() ); + m_snapshotAgentInited = true; + } + m_snapshotAgent->finishHashComputingAndUpdateHashesIfNeeded( _timestamp ); // begin, detect partially executed block bool bIsPartial = false; diff --git a/libethereum/Client.h b/libethereum/Client.h index 0bc7fd3ee..1fa619b55 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -525,6 +525,7 @@ class Client : public ClientBase, protected Worker { /// skale std::shared_ptr< SkaleHost > m_skaleHost; std::shared_ptr< SnapshotAgent > m_snapshotAgent; + bool m_snapshotAgentInited = false; const static dev::h256 empty_str_hash; std::shared_ptr< InstanceMonitor > m_instanceMonitor; fs::path m_dbPath; diff --git a/libethereum/SnapshotAgent.cpp b/libethereum/SnapshotAgent.cpp index a8f63fbed..36d44724b 100644 --- a/libethereum/SnapshotAgent.cpp +++ b/libethereum/SnapshotAgent.cpp @@ -18,14 +18,67 @@ SnapshotAgent::SnapshotAgent( int64_t _snapshotIntervalSec, } } -void SnapshotAgent::finishHashComputingAndUpdateHashesIfNeeded( - unsigned block_number, uint64_t _timestamp ) { - // init last block creation time with only robust time source - timestamp of 1st block! - if ( block_number == 0 ) { - last_snapshot_creation_time = _timestamp; - LOG( m_logger ) << "Init last snapshot creation time: " - << this->last_snapshot_creation_time; - } else if ( m_snapshotIntervalSec > 0 && this->isTimeToDoSnapshot( _timestamp ) ) { +void SnapshotAgent::init( unsigned _currentBlockNumber, int64_t _timestampOfBlock1 ) { + if ( m_snapshotIntervalSec < 0 ) + return; + + if ( _currentBlockNumber == 0 ) + doSnapshotAndComputeHash( 0 ); + + auto latest_snapshots = this->m_snapshotManager->getLatestSnapshots(); + + // if two + if ( latest_snapshots.first ) { + assert( latest_snapshots.first != 1 ); // 1 can never be snapshotted + + this->last_snapshoted_block_with_hash = latest_snapshots.first; + + // ignore second as it was "in hash computation" + // check that both are imported!! + // h256 h2 = this->hashFromNumber( latest_snapshots.second ); + // assert( h2 != h256() ); + // last_snapshot_creation_time = blockInfo( h2 ).timestamp(); + + last_snapshot_creation_time = + this->m_snapshotManager->getBlockTimestamp( latest_snapshots.second ); + + if ( !m_snapshotManager->isSnapshotHashPresent( latest_snapshots.second ) ) + startHashComputingThread(); + + // one snapshot + } else if ( latest_snapshots.second ) { + assert( latest_snapshots.second != 1 ); // 1 can never be snapshotted + assert( _timestampOfBlock1 > 0 ); // we created snapshot somehow + + // whether it is local or downloaded - we shall ignore it's hash but use it's time + // see also how last_snapshoted_block_with_hash is updated in importTransactionsAsBlock + // h256 h2 = this->hashFromNumber( latest_snapshots.second ); + // uint64_t time_of_second = blockInfo( h2 ).timestamp(); + + this->last_snapshoted_block_with_hash = -1; + // last_snapshot_creation_time = time_of_second; + + last_snapshot_creation_time = + this->m_snapshotManager->getBlockTimestamp( latest_snapshots.second ); + + if ( !m_snapshotManager->isSnapshotHashPresent( latest_snapshots.second ) ) + startHashComputingThread(); + + // no snapshots yet + } else { + this->last_snapshoted_block_with_hash = -1; + // init last block creation time with only robust time source - timestamp of 1st block! + last_snapshot_creation_time = _timestampOfBlock1; + } + + LOG( m_logger ) << "Latest snapshots init: " << latest_snapshots.first << " " + << latest_snapshots.second << " -> " << this->last_snapshoted_block_with_hash; + + LOG( m_logger ) << "Init last snapshot creation time: " << this->last_snapshot_creation_time; +} + +void SnapshotAgent::finishHashComputingAndUpdateHashesIfNeeded( int64_t _timestamp ) { + if ( m_snapshotIntervalSec > 0 && this->isTimeToDoSnapshot( _timestamp ) ) { LOG( m_logger ) << "Last snapshot creation time: " << this->last_snapshot_creation_time; if ( m_snapshotHashComputing != nullptr && m_snapshotHashComputing->joinable() ) @@ -44,7 +97,7 @@ void SnapshotAgent::finishHashComputingAndUpdateHashesIfNeeded( } } -void SnapshotAgent::doSnapshotIfNeeded( unsigned block_number, uint64_t _timestamp ) { +void SnapshotAgent::doSnapshotIfNeeded( unsigned _currentBlockNumber, int64_t _timestamp ) { if ( m_snapshotIntervalSec <= 0 ) return; @@ -54,11 +107,11 @@ void SnapshotAgent::doSnapshotIfNeeded( unsigned block_number, uint64_t _timesta try { boost::chrono::high_resolution_clock::time_point t1; boost::chrono::high_resolution_clock::time_point t2; - LOG( m_logger ) << "DOING SNAPSHOT: " << block_number; + LOG( m_logger ) << "DOING SNAPSHOT: " << _currentBlockNumber; m_debugTracer.tracepoint( "doing_snapshot" ); t1 = boost::chrono::high_resolution_clock::now(); - m_snapshotManager->doSnapshot( block_number ); + m_snapshotManager->doSnapshot( _currentBlockNumber ); t2 = boost::chrono::high_resolution_clock::now(); this->snapshot_calculation_time_ms = boost::chrono::duration_cast< boost::chrono::milliseconds >( t2 - t1 ).count(); @@ -121,80 +174,6 @@ uint64_t SnapshotAgent::getBlockTimestampFromSnapshot( unsigned _blockNumber ) c return this->m_snapshotManager->getBlockTimestamp( _blockNumber ); } -void SnapshotAgent::doSnapshotAndComputeHash( unsigned _blockNumber ) { - LOG( m_logger ) << "DOING SNAPSHOT: " << _blockNumber; - m_debugTracer.tracepoint( "doing_snapshot" ); - - try { - m_snapshotManager->doSnapshot( _blockNumber ); - } catch ( SnapshotManager::SnapshotPresent& ex ) { - LOG( m_logger ) << "0 block snapshot is already present. Skipping."; - return; - } - - m_snapshotManager->computeSnapshotHash( _blockNumber ); - LOG( m_logger ) << "Computed hash for snapshot " << _blockNumber << ": " - << m_snapshotManager->getSnapshotHash( _blockNumber ); - m_debugTracer.tracepoint( "computeSnapshotHash_end" ); -} - -void SnapshotAgent::init( unsigned _currentBlockNumber, int64_t _currentBlockTime ) { - if ( m_snapshotIntervalSec < 0 ) - return; - - if ( _currentBlockNumber == 0 ) - doSnapshotAndComputeHash( 0 ); - - auto latest_snapshots = this->m_snapshotManager->getLatestSnapshots(); - - // if two - if ( latest_snapshots.first ) { - assert( latest_snapshots.first != 1 ); // 1 can never be snapshotted - - this->last_snapshoted_block_with_hash = latest_snapshots.first; - - // ignore second as it was "in hash computation" - // check that both are imported!! - // h256 h2 = this->hashFromNumber( latest_snapshots.second ); - // assert( h2 != h256() ); - // last_snapshot_creation_time = blockInfo( h2 ).timestamp(); - - last_snapshot_creation_time = - this->m_snapshotManager->getBlockTimestamp( latest_snapshots.second ); - - if ( !m_snapshotManager->isSnapshotHashPresent( latest_snapshots.second ) ) - startHashComputingThread(); - - // one snapshot - } else if ( latest_snapshots.second ) { - assert( latest_snapshots.second != 1 ); // 1 can never be snapshotted - assert( _currentBlockTime > 0 ); // we created snapshot somehow - - // whether it is local or downloaded - we shall ignore it's hash but use it's time - // see also how last_snapshoted_block_with_hash is updated in importTransactionsAsBlock - // h256 h2 = this->hashFromNumber( latest_snapshots.second ); - // uint64_t time_of_second = blockInfo( h2 ).timestamp(); - - this->last_snapshoted_block_with_hash = -1; - // last_snapshot_creation_time = time_of_second; - - last_snapshot_creation_time = - this->m_snapshotManager->getBlockTimestamp( latest_snapshots.second ); - - if ( !m_snapshotManager->isSnapshotHashPresent( latest_snapshots.second ) ) - startHashComputingThread(); - - // no snapshots yet - } else { - this->last_snapshoted_block_with_hash = -1; - last_snapshot_creation_time = _currentBlockTime; - } - - LOG( m_logger ) << "Latest snapshots init: " << latest_snapshots.first << " " - << latest_snapshots.second << " -> " << this->last_snapshoted_block_with_hash; - LOG( m_logger ) << "Fake Last snapshot creation time: " << last_snapshot_creation_time; -} - bool SnapshotAgent::isTimeToDoSnapshot( uint64_t _timestamp ) const { return _timestamp / uint64_t( m_snapshotIntervalSec ) > this->last_snapshot_creation_time / uint64_t( m_snapshotIntervalSec ); @@ -233,3 +212,20 @@ void SnapshotAgent::startHashComputingThread() { } } ) ); } + +void SnapshotAgent::doSnapshotAndComputeHash( unsigned _blockNumber ) { + LOG( m_logger ) << "DOING SNAPSHOT: " << _blockNumber; + m_debugTracer.tracepoint( "doing_snapshot" ); + + try { + m_snapshotManager->doSnapshot( _blockNumber ); + } catch ( SnapshotManager::SnapshotPresent& ex ) { + LOG( m_logger ) << "0 block snapshot is already present. Skipping."; + return; + } + + m_snapshotManager->computeSnapshotHash( _blockNumber ); + LOG( m_logger ) << "Computed hash for snapshot " << _blockNumber << ": " + << m_snapshotManager->getSnapshotHash( _blockNumber ); + m_debugTracer.tracepoint( "computeSnapshotHash_end" ); +} diff --git a/libethereum/SnapshotAgent.h b/libethereum/SnapshotAgent.h index cd8a76e8c..140e0c4cd 100644 --- a/libethereum/SnapshotAgent.h +++ b/libethereum/SnapshotAgent.h @@ -20,10 +20,11 @@ class SnapshotAgent { SnapshotAgent( int64_t _snapshotIntervalSec, std::shared_ptr< SnapshotManager > _snapshotManager, SkaleDebugTracer& _debugTracer ); - void init( unsigned _currentBlockNumber, int64_t _currentBlockTime ); + // timestamp of 1st block is the only robust time source + void init( unsigned _currentBlockNumber, int64_t _timestampOfBlock1 ); - void finishHashComputingAndUpdateHashesIfNeeded( unsigned block_number, uint64_t _timestamp ); - void doSnapshotIfNeeded( unsigned block_number, uint64_t _timestamp ); + void finishHashComputingAndUpdateHashesIfNeeded( int64_t _timestamp ); + void doSnapshotIfNeeded( unsigned _currentBlockNumber, int64_t _timestamp ); boost::filesystem::path createSnapshotFile( unsigned _blockNumber ); @@ -38,6 +39,11 @@ class SnapshotAgent { } private: + // time of last physical snapshot + int64_t last_snapshot_creation_time = 0; + // usually this is snapshot before last! + int64_t last_snapshoted_block_with_hash = -1; + int64_t m_snapshotIntervalSec; std::shared_ptr< SnapshotManager > m_snapshotManager; @@ -47,11 +53,6 @@ class SnapshotAgent { std::unique_ptr< std::thread > m_snapshotHashComputing; - // time of last physical snapshot - int64_t last_snapshot_creation_time = 0; - // usually this is snapshot before last! - int64_t last_snapshoted_block_with_hash = -1; - uint64_t snapshot_calculation_time_ms; uint64_t snapshot_hash_calculation_time_ms; From 60355dd64571ff20df08a6f8aff6cd224668e8d2 Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Wed, 31 May 2023 15:30:49 +0100 Subject: [PATCH 14/26] SKALED-1425 Update consensus --- libconsensus | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libconsensus b/libconsensus index bbdb37e54..dbd791b6d 160000 --- a/libconsensus +++ b/libconsensus @@ -1 +1 @@ -Subproject commit bbdb37e54c3329cfc108b7e0ccd66b952088abd9 +Subproject commit dbd791b6db2a420b4b05609ac8642ccec63e64de From 0bf216c3103139ea0894d8c6db5b4a83d653b052 Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Wed, 31 May 2023 19:16:24 +0100 Subject: [PATCH 15/26] SKALED-1425 Small bug fix --- libethereum/SnapshotAgent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/SnapshotAgent.cpp b/libethereum/SnapshotAgent.cpp index 36d44724b..8d525a03b 100644 --- a/libethereum/SnapshotAgent.cpp +++ b/libethereum/SnapshotAgent.cpp @@ -19,7 +19,7 @@ SnapshotAgent::SnapshotAgent( int64_t _snapshotIntervalSec, } void SnapshotAgent::init( unsigned _currentBlockNumber, int64_t _timestampOfBlock1 ) { - if ( m_snapshotIntervalSec < 0 ) + if ( m_snapshotIntervalSec <= 0 ) return; if ( _currentBlockNumber == 0 ) From 2bc193d5d8a6e5c41f2fb21399a4fcc522f09a6a Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Fri, 2 Jun 2023 13:55:38 +0100 Subject: [PATCH 16/26] SKALED-1425 Real exit of hash thread --- libethereum/SnapshotAgent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/SnapshotAgent.cpp b/libethereum/SnapshotAgent.cpp index 8d525a03b..746587bae 100644 --- a/libethereum/SnapshotAgent.cpp +++ b/libethereum/SnapshotAgent.cpp @@ -150,7 +150,7 @@ void SnapshotAgent::terminate() { if ( m_snapshotHashComputing != nullptr ) { try { if ( m_snapshotHashComputing->joinable() ) - m_snapshotHashComputing->join(); + m_snapshotHashComputing->detach(); } catch ( ... ) { } } From abf65b0c4c3efa18fb41d10ee9cd4776ea2e7dbe Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Wed, 7 Jun 2023 14:08:50 +0100 Subject: [PATCH 17/26] SKALED-1425 Temporarily use RelWithDebInfo build --- .github/workflows/publish.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f2ae2f22a..bdeee077d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -90,7 +90,7 @@ jobs: export CC=gcc-9 export CXX=g++-9 export TARGET=all - export CMAKE_BUILD_TYPE=Release + export CMAKE_BUILD_TYPE=RelWithDebInfo cd deps ./clean.sh rm -f ./libwebsockets-from-git.tar.gz @@ -101,7 +101,7 @@ jobs: export CC=gcc-9 export CXX=g++-9 export TARGET=all - export CMAKE_BUILD_TYPE=Release + export CMAKE_BUILD_TYPE=RelWithDebInfo mkdir -p build cd build # -DCMAKE_C_FLAGS=-O3 -DCMAKE_CXX_FLAGS=-O3 @@ -112,18 +112,18 @@ jobs: export CC=gcc-9 export CXX=g++-9 export TARGET=all - export CMAKE_BUILD_TYPE=Release + export CMAKE_BUILD_TYPE=RelWithDebInfo cd build make skaled -j$(nproc) - echo "Ensure release mode skaled does not have any debug markers" - strip skaled/skaled + #echo "Ensure release mode skaled does not have any debug markers" + #strip skaled/skaled cd .. - name: Configure historic state build run: | export CC=gcc-9 export CXX=g++-9 export TARGET=all - export CMAKE_BUILD_TYPE=Release + export CMAKE_BUILD_TYPE=RelWithDebInfo mkdir -p build-historic cd build-historic # -DCMAKE_C_FLAGS=-O3 -DCMAKE_CXX_FLAGS=-O3 @@ -134,11 +134,11 @@ jobs: export CC=gcc-9 export CXX=g++-9 export TARGET=all - export CMAKE_BUILD_TYPE=Release + export CMAKE_BUILD_TYPE=RelWithDebInfo cd build-historic make skaled -j$(nproc) - echo "Ensure release mode skaled does not have any debug markers" - strip skaled/skaled + #echo "Ensure release mode skaled does not have any debug markers" + #strip skaled/skaled cd .. - name: Build and publish container run: | From d4b8ab5c4e423070f5e654973d2eece34f37dc9a Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Wed, 7 Jun 2023 16:30:09 +0100 Subject: [PATCH 18/26] SKALED-1425 RelWithDebInfo --- .github/workflows/custom_build.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/custom_build.yml b/.github/workflows/custom_build.yml index 421bebb79..0a2a4f0d4 100644 --- a/.github/workflows/custom_build.yml +++ b/.github/workflows/custom_build.yml @@ -95,7 +95,7 @@ jobs: export CC=gcc-9 export CXX=g++-9 export TARGET=all - export CMAKE_BUILD_TYPE=Release + export CMAKE_BUILD_TYPE=RelWithDebInfo cd deps ./clean.sh rm -f ./libwebsockets-from-git.tar.gz @@ -106,7 +106,7 @@ jobs: export CC=gcc-9 export CXX=g++-9 export TARGET=all - export CMAKE_BUILD_TYPE=Release + export CMAKE_BUILD_TYPE=RelWithDebInfo mkdir -p build cd build cmake -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE ${{ github.event.inputs.cmake_options }} .. @@ -116,11 +116,11 @@ jobs: export CC=gcc-9 export CXX=g++-9 export TARGET=all - export CMAKE_BUILD_TYPE=Release + export CMAKE_BUILD_TYPE=RelWithDebInfo cd build make skaled -j$(nproc) - echo "Ensure release mode skaled does not have any debug markers" - strip skaled/skaled + #echo "Ensure release mode skaled does not have any debug markers" + #strip skaled/skaled cd .. - name: Build and publish container From f2e5fa453da4aa095fe68259fac08cf23977a79c Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Thu, 8 Jun 2023 22:43:38 +0100 Subject: [PATCH 19/26] SKALED-1425 Disable warnings for sanitizer --- libskutils/include/skutils/http_pg.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libskutils/include/skutils/http_pg.h b/libskutils/include/skutils/http_pg.h index dc26c0d52..5a7b06c9b 100644 --- a/libskutils/include/skutils/http_pg.h +++ b/libskutils/include/skutils/http_pg.h @@ -8,6 +8,7 @@ #pragma GCC diagnostic ignored "-Waddress" #pragma GCC diagnostic ignored "-Wnonnull-compare" #pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wattributes" #include #include From f55c7307de84ca99588828faf2cdca73f36a4da5 Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Fri, 9 Jun 2023 13:51:11 +0100 Subject: [PATCH 20/26] SKALED-1425 More logging in consensus --- libconsensus | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libconsensus b/libconsensus index dbd791b6d..300060d66 160000 --- a/libconsensus +++ b/libconsensus @@ -1 +1 @@ -Subproject commit dbd791b6db2a420b4b05609ac8642ccec63e64de +Subproject commit 300060d6602ae72075a64c0f2557324110080051 From c5afda827c1c47a0265f3f50b36d2a619c8346d9 Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Fri, 9 Jun 2023 16:57:45 +0100 Subject: [PATCH 21/26] SKALED-1425 Use Release build --- .github/workflows/publish.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index bdeee077d..7540d6d6e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -90,7 +90,7 @@ jobs: export CC=gcc-9 export CXX=g++-9 export TARGET=all - export CMAKE_BUILD_TYPE=RelWithDebInfo + export CMAKE_BUILD_TYPE=Release cd deps ./clean.sh rm -f ./libwebsockets-from-git.tar.gz @@ -101,7 +101,7 @@ jobs: export CC=gcc-9 export CXX=g++-9 export TARGET=all - export CMAKE_BUILD_TYPE=RelWithDebInfo + export CMAKE_BUILD_TYPE=Release mkdir -p build cd build # -DCMAKE_C_FLAGS=-O3 -DCMAKE_CXX_FLAGS=-O3 @@ -112,18 +112,18 @@ jobs: export CC=gcc-9 export CXX=g++-9 export TARGET=all - export CMAKE_BUILD_TYPE=RelWithDebInfo + export CMAKE_BUILD_TYPE=Release cd build make skaled -j$(nproc) #echo "Ensure release mode skaled does not have any debug markers" - #strip skaled/skaled + strip skaled/skaled cd .. - name: Configure historic state build run: | export CC=gcc-9 export CXX=g++-9 export TARGET=all - export CMAKE_BUILD_TYPE=RelWithDebInfo + export CMAKE_BUILD_TYPE=Release mkdir -p build-historic cd build-historic # -DCMAKE_C_FLAGS=-O3 -DCMAKE_CXX_FLAGS=-O3 @@ -134,11 +134,11 @@ jobs: export CC=gcc-9 export CXX=g++-9 export TARGET=all - export CMAKE_BUILD_TYPE=RelWithDebInfo + export CMAKE_BUILD_TYPE=Release cd build-historic make skaled -j$(nproc) #echo "Ensure release mode skaled does not have any debug markers" - #strip skaled/skaled + strip skaled/skaled cd .. - name: Build and publish container run: | From 9ca2dbcb3f06e1d922cc41d89de01b83906261a0 Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Mon, 12 Jun 2023 15:50:49 +0100 Subject: [PATCH 22/26] Use old consenus and Debug build to see problem location --- .github/workflows/custom_build.yml | 6 +++--- libconsensus | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/custom_build.yml b/.github/workflows/custom_build.yml index 0a2a4f0d4..771ed7379 100644 --- a/.github/workflows/custom_build.yml +++ b/.github/workflows/custom_build.yml @@ -95,7 +95,7 @@ jobs: export CC=gcc-9 export CXX=g++-9 export TARGET=all - export CMAKE_BUILD_TYPE=RelWithDebInfo + export CMAKE_BUILD_TYPE=Debug cd deps ./clean.sh rm -f ./libwebsockets-from-git.tar.gz @@ -106,7 +106,7 @@ jobs: export CC=gcc-9 export CXX=g++-9 export TARGET=all - export CMAKE_BUILD_TYPE=RelWithDebInfo + export CMAKE_BUILD_TYPE=Debug mkdir -p build cd build cmake -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE ${{ github.event.inputs.cmake_options }} .. @@ -116,7 +116,7 @@ jobs: export CC=gcc-9 export CXX=g++-9 export TARGET=all - export CMAKE_BUILD_TYPE=RelWithDebInfo + export CMAKE_BUILD_TYPE=Debug cd build make skaled -j$(nproc) #echo "Ensure release mode skaled does not have any debug markers" diff --git a/libconsensus b/libconsensus index 300060d66..dbd791b6d 160000 --- a/libconsensus +++ b/libconsensus @@ -1 +1 @@ -Subproject commit 300060d6602ae72075a64c0f2557324110080051 +Subproject commit dbd791b6db2a420b4b05609ac8642ccec63e64de From 81114a4c056636dbe8c0f85cd096fe3090a6e8de Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Mon, 12 Jun 2023 16:55:42 +0100 Subject: [PATCH 23/26] Use DEBUG=1 in deps --- .github/workflows/custom_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/custom_build.yml b/.github/workflows/custom_build.yml index 771ed7379..aca1fac06 100644 --- a/.github/workflows/custom_build.yml +++ b/.github/workflows/custom_build.yml @@ -99,7 +99,7 @@ jobs: cd deps ./clean.sh rm -f ./libwebsockets-from-git.tar.gz - ./build.sh PARALLEL_COUNT=$(nproc) + ./build.sh PARALLEL_COUNT=$(nproc) DEBUG=1 cd .. - name: Configure all run: | From 5d3132c5ebb7a738a79e378a900f0006b6ae004b Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 13 Jun 2023 13:15:43 +0100 Subject: [PATCH 24/26] 1425 fix snapshot agent init --- libethereum/Client.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 57a4722fa..eed16ae51 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -522,7 +522,8 @@ size_t Client::importTransactionsAsBlock( // on schain creation, SnapshotAgent needs timestamp of block 1 // so we use this HACK if ( !m_snapshotAgentInited ) { - m_snapshotAgent->init( number(), m_bc.info().timestamp() ); + m_snapshotAgent->init( + number(), number() > 0 ? blockInfo( hashFromNumber( 1 ) ).timestamp() : _timestamp ); m_snapshotAgentInited = true; } m_snapshotAgent->finishHashComputingAndUpdateHashesIfNeeded( _timestamp ); From 5ab13c21470ba683fc1a1664f813ad25643b73ab Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Thu, 15 Jun 2023 13:19:26 +0100 Subject: [PATCH 25/26] 1425 add more consensus logs --- libconsensus | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libconsensus b/libconsensus index dbd791b6d..5c6814d54 160000 --- a/libconsensus +++ b/libconsensus @@ -1 +1 @@ -Subproject commit dbd791b6db2a420b4b05609ac8642ccec63e64de +Subproject commit 5c6814d543ea132f64bb9fdc497f1fd1fa68f38f From 191111479fddcb298b3dec5ab922cd424bd0badd Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Fri, 16 Jun 2023 13:46:50 +0100 Subject: [PATCH 26/26] update consensus --- libconsensus | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libconsensus b/libconsensus index 5c6814d54..2b097b289 160000 --- a/libconsensus +++ b/libconsensus @@ -1 +1 @@ -Subproject commit 5c6814d543ea132f64bb9fdc497f1fd1fa68f38f +Subproject commit 2b097b289ed2577b98747e57165c9f2b9a37c2be