From 685fd9176132db9ec9f3e4709eeaf2153022a570 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Fri, 20 Oct 2023 17:02:26 +0100 Subject: [PATCH 01/30] 1702 add owner field to nodes in chain params --- libethcore/ChainOperationParams.h | 8 ++++++-- libethereum/ChainParams.cpp | 7 +++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/libethcore/ChainOperationParams.h b/libethcore/ChainOperationParams.h index ec57fe4ed..9bbe6dcb4 100644 --- a/libethcore/ChainOperationParams.h +++ b/libethcore/ChainOperationParams.h @@ -78,6 +78,7 @@ struct NodeInfo { uint16_t port; std::string ip6; uint16_t port6; + std::string owner; std::string sgxServerUrl; std::string keyShareName; std::string ecdsaKeyName; @@ -89,7 +90,7 @@ struct NodeInfo { NodeInfo( std::string _name = "TestNode", u256 _id = 1, std::string _ip = "127.0.0.11", uint16_t _port = 11111, std::string _ip6 = "::1", uint16_t _port6 = 11111, - std::string _sgxServerUrl = "", std::string _ecdsaKeyName = "", + std::string _owner = "", std::string _sgxServerUrl = "", std::string _ecdsaKeyName = "", std::string _keyShareName = "", const std::array< std::string, 4 >& _BLSPublicKeys = { "1085704699902305713594457076223282948137075635957851808699051999328" @@ -110,6 +111,7 @@ struct NodeInfo { port = _port; ip6 = _ip6; port6 = _port6; + owner = _owner; sgxServerUrl = _sgxServerUrl; ecdsaKeyName = _ecdsaKeyName; keyShareName = _keyShareName; @@ -131,6 +133,7 @@ struct sChainNode { u256 port6; u256 sChainIndex; std::string publicKey; + std::string owner; std::array< std::string, 4 > blsPublicKey; }; @@ -140,6 +143,7 @@ struct GroupNode { u256 id; u256 schainIndex; std::string publicKey; + std::string owner; }; /// skale @@ -184,7 +188,7 @@ struct SChain { // HACK This creates one node and allows to run tests - BUT when loading config we need to // delete this explicitly!! sChainNode me = { u256( 1 ), "127.0.0.11", u256( 11111 ), "::1", u256( 11111 ), u256( 1 ), - "0xfa", { "0", "1", "0", "1" } }; + "0xfa", "", { "0", "1", "0", "1" } }; nodes.push_back( me ); } }; diff --git a/libethereum/ChainParams.cpp b/libethereum/ChainParams.cpp index fb48f748d..bbb2a1247 100644 --- a/libethereum/ChainParams.cpp +++ b/libethereum/ChainParams.cpp @@ -113,6 +113,7 @@ ChainParams ChainParams::loadConfig( auto nodeName = infoObj.at( "nodeName" ).get_str(); auto nodeID = infoObj.at( "nodeID" ).get_uint64(); + std::string owner = infoObj.at( "owner" ).get_str(); bool syncNode = false; bool archiveMode = false; bool syncFromCatchup = false; @@ -187,7 +188,7 @@ ChainParams ChainParams::loadConfig( } cp.nodeInfo = { nodeName, nodeID, ip, static_cast< uint16_t >( port ), ip6, - static_cast< uint16_t >( port6 ), sgxServerUrl, ecdsaKeyName, keyShareName, + static_cast< uint16_t >( port6 ), owner, sgxServerUrl, ecdsaKeyName, keyShareName, BLSPublicKeys, commonBLSPublicKeys, syncNode, archiveMode, syncFromCatchup }; auto sChainObj = skaleObj.at( "sChain" ).get_obj(); @@ -287,7 +288,8 @@ ChainParams ChainParams::loadConfig( u256 sChainIndex = groupNodeConfObj[0].get_uint64(); u256 id = groupNodeConfObj[1].get_uint64(); std::string publicKey = groupNodeConfObj[2].get_str(); - groupNodes.push_back( { id, sChainIndex, publicKey } ); + std::string owner = groupNodeConfObj[3].get_str(); + groupNodes.push_back( { id, sChainIndex, publicKey, owner } ); } std::sort( groupNodes.begin(), groupNodes.end(), []( const GroupNode& lhs, const GroupNode& rhs ) { @@ -322,6 +324,7 @@ ChainParams ChainParams::loadConfig( node.id = nodeConfObj.at( "nodeID" ).get_uint64(); node.ip = nodeConfObj.at( "ip" ).get_str(); node.port = nodeConfObj.at( "basePort" ).get_uint64(); + node.owner = nodeConfObj.at( "owner" ).get_str(); try { node.ip6 = nodeConfObj.at( "ip6" ).get_str(); } catch ( ... ) { From a733b76de45622be7bb0807a855d838662d69fd2 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 24 Oct 2023 15:51:32 +0100 Subject: [PATCH 02/30] 1702 use historicGroupIndex --- libethereum/ChainParams.cpp | 13 +++- libethereum/Client.cpp | 18 ++--- libethereum/Client.h | 24 +++++-- libethereum/Precompiled.cpp | 69 ++++++++++++++++--- libethereum/SkaleHost.cpp | 12 ++++ libethereum/SkaleHost.h | 9 +++ test/unittests/libethereum/ClientTest.cpp | 16 +++-- .../mapreduce_consensus/ConsensusEngine.cpp | 2 +- 8 files changed, 131 insertions(+), 32 deletions(-) diff --git a/libethereum/ChainParams.cpp b/libethereum/ChainParams.cpp index bbb2a1247..0d80616ee 100644 --- a/libethereum/ChainParams.cpp +++ b/libethereum/ChainParams.cpp @@ -113,13 +113,16 @@ ChainParams ChainParams::loadConfig( auto nodeName = infoObj.at( "nodeName" ).get_str(); auto nodeID = infoObj.at( "nodeID" ).get_uint64(); - std::string owner = infoObj.at( "owner" ).get_str(); bool syncNode = false; bool archiveMode = false; bool syncFromCatchup = false; - std::string ip, ip6, keyShareName, sgxServerUrl; + std::string ip, ip6, keyShareName, sgxServerUrl, owner; size_t t = 0; uint64_t port = 0, port6 = 0; + try { + owner = infoObj.at( "owner" ).get_str(); + } catch ( ... ) { + } try { ip = infoObj.at( "bindIP" ).get_str(); } catch ( ... ) { @@ -324,7 +327,11 @@ ChainParams ChainParams::loadConfig( node.id = nodeConfObj.at( "nodeID" ).get_uint64(); node.ip = nodeConfObj.at( "ip" ).get_str(); node.port = nodeConfObj.at( "basePort" ).get_uint64(); - node.owner = nodeConfObj.at( "owner" ).get_str(); + try { + node.owner = nodeConfObj.at( "owner" ).get_str(); + } catch ( ... ) { + node.owner = ""; + } try { node.ip6 = nodeConfObj.at( "ip6" ).get_str(); } catch ( ... ) { diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 06cec9516..35bc83642 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -312,7 +312,7 @@ void Client::init( WithExisting _forceAction, u256 _networkId ) { Defaults::setDBPath( m_dbPath ); if ( ChainParams().sChain.nodeGroups.size() > 0 ) - initIMABLSPublicKey(); + initHistoricGroupIndex(); // init snapshots for not newly created chains if ( number() ) { @@ -619,7 +619,7 @@ size_t Client::importTransactionsAsBlock( } if ( chainParams().sChain.nodeGroups.size() > 0 ) - updateIMABLSPublicKey(); + updateHistoricGroupIndex(); m_snapshotAgent->doSnapshotIfNeeded( number(), _timestamp ); @@ -1285,9 +1285,9 @@ ExecutionResult Client::call( Address const& _from, u256 _value, Address _dest, return ret; } -void Client::initIMABLSPublicKey() { +void Client::initHistoricGroupIndex() { if ( number() == 0 ) { - imaBLSPublicKeyGroupIndex = 0; + historicGroupIndex = 0; return; } @@ -1308,15 +1308,15 @@ void Client::initIMABLSPublicKey() { it = prevIt; } - imaBLSPublicKeyGroupIndex = std::distance( chainParams().sChain.nodeGroups.begin(), it ); + historicGroupIndex = std::distance( chainParams().sChain.nodeGroups.begin(), it ); } -void Client::updateIMABLSPublicKey() { +void Client::updateHistoricGroupIndex() { uint64_t blockTimestamp = blockInfo( hashFromNumber( number() ) ).timestamp(); - uint64_t currentFinishTs = chainParams().sChain.nodeGroups[imaBLSPublicKeyGroupIndex].finishTs; + uint64_t currentFinishTs = chainParams().sChain.nodeGroups[historicGroupIndex].finishTs; if ( blockTimestamp >= currentFinishTs ) - ++imaBLSPublicKeyGroupIndex; - assert( imaBLSPublicKeyGroupIndex < chainParams().sChain.nodeGroups.size() ); + ++historicGroupIndex; + assert( historicGroupIndex < chainParams().sChain.nodeGroups.size() ); } // new block watch diff --git a/libethereum/Client.h b/libethereum/Client.h index 2e3155612..90f491282 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -297,7 +297,22 @@ class Client : public ClientBase, protected Worker { } std::array< std::string, 4 > getIMABLSPublicKey() const { - return chainParams().sChain.nodeGroups[imaBLSPublicKeyGroupIndex].blsPublicKey; + return chainParams().sChain.nodeGroups[historicGroupIndex].blsPublicKey; + } + + // get node id for historic node in chain + std::string getHistoricNodeId( unsigned _id ) const { + return chainParams().sChain.nodeGroups[historicGroupIndex].nodes[_id].id.str(); + } + + // get schain index for historic node in chain + std::string getHistoricNodeIndex( unsigned _idx ) const { + return chainParams().sChain.nodeGroups[historicGroupIndex].nodes[_idx].schainIndex.str(); + } + + // get node owner for historic node in chain + std::string getHistoricNodeOwner( unsigned _idx ) const { + return chainParams().sChain.nodeGroups[historicGroupIndex].nodes[_idx].owner; } void doStateDbCompaction() const { m_state.getOriginalDb()->doCompaction(); } @@ -532,10 +547,11 @@ class Client : public ClientBase, protected Worker { fs::path m_dbPath; private: - void initIMABLSPublicKey(); - void updateIMABLSPublicKey(); + void initHistoricGroupIndex(); + void updateHistoricGroupIndex(); - unsigned imaBLSPublicKeyGroupIndex = 0; + // which group corresponds to the current block timestamp on this node + unsigned historicGroupIndex = 0; public: FILE* performance_fd; diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index 6a0a1c63f..964a1a072 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -756,22 +756,57 @@ static dev::u256 stat_parse_u256_hex_or_dec( const std::string& strValue ) { return uValue; } +static bool isCallToHistoricData( const std::string& callData ) { + return skutils::tools::wildcmp( "skaleConfig.sChain.nodes.*", callData.c_str() ); +} + +static std::pair< std::string, unsigned > parseHistoricFieldReuqest( const std::string& callData ) { + unsigned id = std::stoul( callData.substr( callData.find( '[' ), callData.find( ']' ) + 1 ) ); + std::string fieldName; + if ( callData.find( "id" ) != std::string::npos ) { + fieldName = "id"; + } else if ( callData.find( "schainIndex" ) != std::string::npos ) { + fieldName = "schainIndex"; + } else if ( callData.find( "owner" ) != std::string::npos ) { + fieldName = "owner"; + } else { + fieldName = "unknown field"; + } + return { fieldName, id }; +} + ETH_REGISTER_PRECOMPILED( getConfigVariableUint256 )( bytesConstRef _in ) { try { size_t lengthName; std::string rawName; convertBytesToString( _in, 0, rawName, lengthName ); + std::cout << "PATH: " << rawName << '\n'; if ( !stat_is_accessible_json_path( rawName ) ) throw std::runtime_error( "Security poicy violation, inaccessible configuration JSON path: " + rawName ); if ( !g_configAccesssor ) throw std::runtime_error( "Config accessor was not initialized" ); - nlohmann::json joConfig = g_configAccesssor->getConfigJSON(); - nlohmann::json joValue = - skutils::json_config_file_accessor::stat_extract_at_path( joConfig, rawName ); - std::string strValue = skutils::tools::trim_copy( - joValue.is_string() ? joValue.get< std::string >() : joValue.dump() ); + + std::string strValue; + if ( isCallToHistoricData( rawName ) ) { + std::string field; + unsigned id; + std::tie( field, id ) = parseHistoricFieldReuqest( rawName ); + if ( field == "id" ) { + strValue = g_skaleHost->getHistoricNodeId( id ); + } else if ( field == "schainIndex" ) { + strValue = g_skaleHost->getHistoricNodeIndex( id ); + } else { + throw std::runtime_error( "Incorrect config field" ); + } + } else { + nlohmann::json joConfig = g_configAccesssor->getConfigJSON(); + nlohmann::json joValue = + skutils::json_config_file_accessor::stat_extract_at_path( joConfig, rawName ); + strValue = skutils::tools::trim_copy( + joValue.is_string() ? joValue.get< std::string >() : joValue.dump() ); + } // dev::u256 uValue( strValue.c_str() ); dev::u256 uValue = stat_parse_u256_hex_or_dec( strValue ); @@ -807,11 +842,25 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableAddress )( bytesConstRef _in ) { if ( !g_configAccesssor ) throw std::runtime_error( "Config accessor was not initialized" ); - nlohmann::json joConfig = g_configAccesssor->getConfigJSON(); - nlohmann::json joValue = - skutils::json_config_file_accessor::stat_extract_at_path( joConfig, rawName ); - std::string strValue = skutils::tools::trim_copy( - joValue.is_string() ? joValue.get< std::string >() : joValue.dump() ); + + std::string strValue; + if ( isCallToHistoricData( rawName ) ) { + std::string field; + unsigned id; + std::tie( field, id ) = parseHistoricFieldReuqest( rawName ); + if ( field == "owner" ) { + strValue = g_skaleHost->getHistoricNodeOwner( id ); + } else { + throw std::runtime_error( "Incorrect config field" ); + } + } else { + nlohmann::json joConfig = g_configAccesssor->getConfigJSON(); + nlohmann::json joValue = + skutils::json_config_file_accessor::stat_extract_at_path( joConfig, rawName ); + strValue = skutils::tools::trim_copy( + joValue.is_string() ? joValue.get< std::string >() : joValue.dump() ); + } + dev::u256 uValue( strValue.c_str() ); bytes response = toBigEndian( uValue ); diff --git a/libethereum/SkaleHost.cpp b/libethereum/SkaleHost.cpp index 8a3b54109..53a318180 100644 --- a/libethereum/SkaleHost.cpp +++ b/libethereum/SkaleHost.cpp @@ -950,6 +950,18 @@ std::array< std::string, 4 > SkaleHost::getIMABLSPublicKey() const { return m_client.getIMABLSPublicKey(); } +std::string SkaleHost::getHistoricNodeId( unsigned _id ) const { + return m_client.getHistoricNodeId( _id ); +} + +std::string SkaleHost::getHistoricNodeIndex( unsigned _index ) const { + return m_client.getHistoricNodeIndex( _index ); +} + +std::string SkaleHost::getHistoricNodeOwner( unsigned _idx ) const { + return m_client.getHistoricNodeOwner( _idx ); +} + uint64_t SkaleHost::submitOracleRequest( const string& _spec, string& _receipt, string& _errorMessage ) { return m_consensus->submitOracleRequest( _spec, _receipt, _errorMessage ); diff --git a/libethereum/SkaleHost.h b/libethereum/SkaleHost.h index bb79d5d60..b5ae631c9 100644 --- a/libethereum/SkaleHost.h +++ b/libethereum/SkaleHost.h @@ -126,6 +126,15 @@ class SkaleHost { std::map< std::string, uint64_t > getConsensusDbUsage() const; std::array< std::string, 4 > getIMABLSPublicKey() const; + // get node id for historic node in chain + std::string getHistoricNodeId( unsigned _id ) const; + + // get schain index for historic node in chain + std::string getHistoricNodeIndex( unsigned _idx ) const; + + // get node owner for historic node in chain + std::string getHistoricNodeOwner( unsigned _idx ) const; + uint64_t submitOracleRequest( const string& _spec, string& _receipt, string& _errorMessage ); uint64_t checkOracleResult( const string& _receipt, string& _result ); diff --git a/test/unittests/libethereum/ClientTest.cpp b/test/unittests/libethereum/ClientTest.cpp index c49302cad..40c7872f9 100644 --- a/test/unittests/libethereum/ClientTest.cpp +++ b/test/unittests/libethereum/ClientTest.cpp @@ -871,7 +871,8 @@ static std::string const c_genesisInfoSkaleIMABLSPublicKeyTest = std::string() + "30": [ 0, 30, - "0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b" + "0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b", + "0x23bbe8db4e347b4e8c937c1c8350e4b5ed33adb3db69cbdb7a38e1f40a1b82fe" ] }, "finish_ts": null, @@ -887,7 +888,8 @@ static std::string const c_genesisInfoSkaleIMABLSPublicKeyTest = std::string() + "26": [ 3, 26, - "0x3a581d62b12232dade30c3710215a271984841657449d1f474295a13737b778266f57e298f123ae80cbab7cc35ead1b62a387556f94b326d5c65d4a7aa2abcba" + "0x3a581d62b12232dade30c3710215a271984841657449d1f474295a13737b778266f57e298f123ae80cbab7cc35ead1b62a387556f94b326d5c65d4a7aa2abcba", + "0x47bbe8db4e347b4e8c937c1c8350e4b7ed30adb3db69bbdb7a38c1f40a1b82fd" ] }, "finish_ts": 4294967290, @@ -900,7 +902,7 @@ static std::string const c_genesisInfoSkaleIMABLSPublicKeyTest = std::string() + } }, "nodes": [ - { "nodeID": 1112, "ip": "127.0.0.1", "basePort": )E"+std::to_string( rand_port ) + R"E(, "schainIndex" : 1, "publicKey": "0xfa"} + { "nodeID": 1112, "ip": "127.0.0.1", "basePort": )E"+std::to_string( rand_port ) + R"E(, "schainIndex" : 1, "publicKey": "0xfa", "owner": "0x47bbe8db4e347b4e8c937c1c8350e4b7ed30adb3db69bbdb7a38c1f40a1b82fd"} ] } }, @@ -923,9 +925,10 @@ BOOST_AUTO_TEST_CASE( initAndUpdateIMABLSPUblicKey ) { std::array< std::string, 4 > imaBLSPublicKeyOnStartUp = { "12457351342169393659284905310882617316356538373005664536506840512800919345414", "11573096151310346982175966190385407867176668720531590318594794283907348596326", "13929944172721019694880576097738949215943314024940461401664534665129747139387", "7375214420811287025501422512322868338311819657776589198925786170409964211914" }; - BOOST_REQUIRE( testClient->getIMABLSPublicKey() == imaBLSPublicKeyOnStartUp ); - + BOOST_REQUIRE( testClient->getHistoricNodeOwner( 0 ) == "0x47bbe8db4e347b4e8c937c1c8350e4b7ed30adb3db69bbdb7a38c1f40a1b82fd" ); + BOOST_REQUIRE( testClient->getHistoricNodeId( 0 ) == "26" ); + BOOST_REQUIRE( testClient->getHistoricNodeIndex( 0 ) == "3" ); BOOST_REQUIRE( testClient->mineBlocks( 1 ) ); @@ -934,6 +937,9 @@ BOOST_AUTO_TEST_CASE( initAndUpdateIMABLSPUblicKey ) { std::array< std::string, 4 > imaBLSPublicKeyAfterBlock = { "10860211539819517237363395256510340030868592687836950245163587507107792195621", "2419969454136313127863904023626922181546178935031521540751337209075607503568", "3399776985251727272800732947224655319335094876742988846345707000254666193993", "16982202412630419037827505223148517434545454619191931299977913428346639096984" }; BOOST_REQUIRE( testClient->getIMABLSPublicKey() == imaBLSPublicKeyAfterBlock ); + BOOST_REQUIRE( testClient->getHistoricNodeOwner( 0 ) == "0x23bbe8db4e347b4e8c937c1c8350e4b5ed33adb3db69cbdb7a38e1f40a1b82fe" ); + BOOST_REQUIRE( testClient->getHistoricNodeId( 0 ) == "30" ); + BOOST_REQUIRE( testClient->getHistoricNodeIndex( 0 ) == "0" ); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/unittests/mapreduce_consensus/ConsensusEngine.cpp b/test/unittests/mapreduce_consensus/ConsensusEngine.cpp index 8b78e0bd1..320415246 100644 --- a/test/unittests/mapreduce_consensus/ConsensusEngine.cpp +++ b/test/unittests/mapreduce_consensus/ConsensusEngine.cpp @@ -214,7 +214,7 @@ class ConsensusExtFaceFixture : public ConsensusExtFace { chainParams.nodeInfo.port = chainParams.nodeInfo.port6 = rand_port; chainParams.sChain.nodes[0].port = chainParams.sChain.nodes[0].port6 = rand_port; - sChainNode node2{u256( 2 ), "127.0.0.12", u256( 11111 ), "::1", u256( 11111 ), u256( 1 ), "0xfa", {"0", "1", "0", "1"}}; + sChainNode node2{u256( 2 ), "127.0.0.12", u256( 11111 ), "::1", u256( 11111 ), u256( 1 ), "0xfa", "", {"0", "1", "0", "1"}}; chainParams.sChain.nodes.push_back( node2 ); ////////////////////////////////////////////// From b7cd5a5e3d91faaa7c46b37a34cc8e24edc88d03 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 24 Oct 2023 17:51:29 +0100 Subject: [PATCH 03/30] 1702 update precompiled to work with oracle --- libethereum/Precompiled.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index 964a1a072..ef2416f2d 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -761,7 +761,8 @@ static bool isCallToHistoricData( const std::string& callData ) { } static std::pair< std::string, unsigned > parseHistoricFieldReuqest( const std::string& callData ) { - unsigned id = std::stoul( callData.substr( callData.find( '[' ), callData.find( ']' ) + 1 ) ); + size_t numberLength = callData.find( ']' ) - callData.find( '[' ) - 1; + unsigned id = std::stoul( callData.substr( callData.find( '[' ) + 1, numberLength ) ); std::string fieldName; if ( callData.find( "id" ) != std::string::npos ) { fieldName = "id"; @@ -780,7 +781,6 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableUint256 )( bytesConstRef _in ) { size_t lengthName; std::string rawName; convertBytesToString( _in, 0, rawName, lengthName ); - std::cout << "PATH: " << rawName << '\n'; if ( !stat_is_accessible_json_path( rawName ) ) throw std::runtime_error( "Security poicy violation, inaccessible configuration JSON path: " + rawName ); From 295b85030738626b37d925f0aeade62763122530 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 30 Oct 2023 17:51:34 +0000 Subject: [PATCH 04/30] 1702 improve tests --- libethereum/Precompiled.cpp | 7 +- .../unittests/libethereum/PrecompiledTest.cpp | 201 +++++++++++++++++- 2 files changed, 197 insertions(+), 11 deletions(-) diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index ef2416f2d..a4211a67b 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -790,6 +790,9 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableUint256 )( bytesConstRef _in ) { std::string strValue; if ( isCallToHistoricData( rawName ) ) { + if ( !g_skaleHost ) + throw std::runtime_error( "SkaleHost accessor was not initialized" ); + std::string field; unsigned id; std::tie( field, id ) = parseHistoricFieldReuqest( rawName ); @@ -813,7 +816,6 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableUint256 )( bytesConstRef _in ) { // std::cout << "------------ Loaded config var \"" // << rawName << "\" value is " << uValue // << "\n"; - bytes response = toBigEndian( uValue ); return { true, response }; } catch ( std::exception& ex ) { @@ -845,6 +847,9 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableAddress )( bytesConstRef _in ) { std::string strValue; if ( isCallToHistoricData( rawName ) ) { + if ( !g_skaleHost ) + throw std::runtime_error( "SkaleHost accessor was not initialized" ); + std::string field; unsigned id; std::tie( field, id ) = parseHistoricFieldReuqest( rawName ); diff --git a/test/unittests/libethereum/PrecompiledTest.cpp b/test/unittests/libethereum/PrecompiledTest.cpp index 861cbb595..1bdc069ea 100644 --- a/test/unittests/libethereum/PrecompiledTest.cpp +++ b/test/unittests/libethereum/PrecompiledTest.cpp @@ -24,6 +24,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -37,6 +40,20 @@ using namespace dev::eth; using namespace dev::test; namespace ut = boost::unit_test; +std::string numberToHex( size_t inputNumber ) { + std::stringstream sstream; + sstream << std::hex << inputNumber; + std::string hexNumber = sstream.str(); + hexNumber.insert( hexNumber.begin(), 64 - hexNumber.length(), '0' ); + return hexNumber; +} + +std::string stringToHex( std::string inputString ) { + std::string hexString = toHex( inputString.begin(), inputString.end(), "" ); + hexString.insert( hexString.begin() + hexString.length(), 64 - hexString.length(), '0' ); + return hexString; +} + BOOST_FIXTURE_TEST_SUITE( PrecompiledTests, TestOutputHelperFixture ) BOOST_AUTO_TEST_CASE( modexpFermatTheorem, @@ -1557,18 +1574,182 @@ BOOST_AUTO_TEST_CASE( ecpairingCost ) { BOOST_CHECK_EQUAL( static_cast< int >( costIstanbul ), in.size() / 192 * 34000 + 45000 ); } -std::string numberToHex( size_t inputNumber ) { - std::stringstream sstream; - sstream << std::hex << inputNumber; - std::string hexNumber = sstream.str(); - hexNumber.insert( hexNumber.begin(), 64 - hexNumber.length(), '0' ); - return hexNumber; +static std::string const genesisInfoSkaleConfigTest = std::string() + + R"E( +{ + "sealEngine": "Ethash", + "params": { + "accountStartNonce": "0x00", + "homesteadForkBlock": "0x00", + "EIP150ForkBlock": "0x00", + "EIP158ForkBlock": "0x00", + "byzantiumForkBlock": "0x00", + "constantinopleForkBlock": "0x00", + "constantinopleFixForkBlock": "0x00", + "networkID" : "12313219", + "chainID": "0x01", + "maximumExtraDataSize": "0x20", + "tieBreakingGas": false, + "minGasLimit": "0x1388", + "maxGasLimit": "7fffffffffffffff", + "gasLimitBoundDivisor": "0x0400", + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000" + }, + "genesis": { + "nonce": "0x0000000000000042", + "difficulty": "0x020000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x47E7C4" + }, + "skaleConfig": { + "nodeInfo": { + "nodeName": "Node1", + "nodeID": 1112, + "bindIP": "127.0.0.1", + "basePort": 1234, + "logLevel": "trace", + "logLevelProposal": "trace", + "ecdsaKeyName": "NEK:fa112" + }, + "sChain": { + "schainName": "TestChain", + "schainID": 1, + "contractStorageLimit": 32000, + "emptyBlockIntervalMs": -1, + "nodeGroups": { + "1": { + "nodes": { + "30": [ + 0, + 30, + "0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b", + "0x23bbe8db4e347b4e8c937c1c8350e4b5ed33adb3db69cbdb7a38e1f40a1b82fe" + ] + }, + "finish_ts": null, + "bls_public_key": { + "blsPublicKey0": "10860211539819517237363395256510340030868592687836950245163587507107792195621", + "blsPublicKey1": "2419969454136313127863904023626922181546178935031521540751337209075607503568", + "blsPublicKey2": "3399776985251727272800732947224655319335094876742988846345707000254666193993", + "blsPublicKey3": "16982202412630419037827505223148517434545454619191931299977913428346639096984" + } + }, + "0": { + "nodes": { + "26": [ + 3, + 26, + "0x3a581d62b12232dade30c3710215a271984841657449d1f474295a13737b778266f57e298f123ae80cbab7cc35ead1b62a387556f94b326d5c65d4a7aa2abcba", + "0x47bbe8db4e347b4e8c937c1c8350e4b7ed30adb3db69bbdb7a38c1f40a1b82fd" + ] + }, + "finish_ts": 4294967290, + "bls_public_key": { + "blsPublicKey0": "12457351342169393659284905310882617316356538373005664536506840512800919345414", + "blsPublicKey1": "11573096151310346982175966190385407867176668720531590318594794283907348596326", + "blsPublicKey2": "13929944172721019694880576097738949215943314024940461401664534665129747139387", + "blsPublicKey3": "7375214420811287025501422512322868338311819657776589198925786170409964211914" + } + } + }, + "nodes": [ + { "nodeID": 1112, "ip": "127.0.0.1", "basePort": 1234, "schainIndex" : 1, "publicKey": "0xfa", "owner": "0x21abd6db4e347b4e8c937c1c8370e4b5ed3f0dd3db69cbdb7a38e1e50b1b82fc"} + ] + } + }, + "accounts": { + "0000000000000000000000000000000000000001": { "precompiled": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } }, + "0000000000000000000000000000000000000002": { "precompiled": { "name": "sha256", "linear": { "base": 60, "word": 12 } } }, + "0000000000000000000000000000000000000003": { "precompiled": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } }, + "0000000000000000000000000000000000000004": { "precompiled": { "name": "identity", "linear": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000005": { "precompiled": { "name": "modexp", "startingBlock" : "0x2dc6c0" } }, + "0000000000000000000000000000000000000006": { "precompiled": { "name": "alt_bn128_G1_add", "startingBlock" : "0x2dc6c0", "linear": { "base": 500, "word": 0 } } }, + "0000000000000000000000000000000000000007": { "precompiled": { "name": "alt_bn128_G1_mul", "startingBlock" : "0x2dc6c0", "linear": { "base": 40000, "word": 0 } } }, + "0000000000000000000000000000000000000008": { "precompiled": { "name": "alt_bn128_pairing_product", "startingBlock" : "0x2dc6c0" } }, + "0xca4409573a5129a72edf85d6c51e26760fc9c903": { "balance": "100000000000000000000000" }, + "0xD2001300000000000000000000000000000000D2": { "balance": "0", "nonce": "0", "storage": {}, "code":"0x6080604052348015600f57600080fd5b506004361060325760003560e01c8063815b8ab41460375780638273f754146062575b600080fd5b606060048036036020811015604b57600080fd5b8101908080359060200190929190505050606a565b005b60686081565b005b60005a90505b815a82031015607d576070565b5050565b60005a9050609660028281609157fe5b04606a565b5056fea165627a7a72305820f5fb5a65e97cbda96c32b3a2e1497cd6b7989179b5dc29e9875bcbea5a96c4520029"}, + "0xD2001300000000000000000000000000000000D4": { "balance": "0", "nonce": "0", "storage": {}, "code":"0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632098776714610051578063b8bd717f1461007f578063d37165fa146100ad578063fdde8d66146100db575b600080fd5b61007d6004803603602081101561006757600080fd5b8101908080359060200190929190505050610109565b005b6100ab6004803603602081101561009557600080fd5b8101908080359060200190929190505050610136565b005b6100d9600480360360208110156100c357600080fd5b8101908080359060200190929190505050610170565b005b610107600480360360208110156100f157600080fd5b8101908080359060200190929190505050610191565b005b60005a90505b815a8203101561011e5761010f565b600080fd5b815a8203101561013257610123565b5050565b60005a90505b815a8203101561014b5761013c565b600060011461015957600080fd5b5a90505b815a8203101561016c5761015d565b5050565b60005a9050600081830390505b805a8303101561018c5761017d565b505050565b60005a90505b815a820310156101a657610197565b60016101b157600080fd5b5a90505b815a820310156101c4576101b5565b505056fea264697066735822122089b72532621e7d1849e444ee6efaad4fb8771258e6f79755083dce434e5ac94c64736f6c63430006000033"}, + "0xd40B3c51D0ECED279b1697DbdF45d4D19b872164": { "balance": "0", "nonce": "0", "storage": {}, "code":"0x6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d146037578063b05784b8146062575b600080fd5b606060048036036020811015604b57600080fd5b8101908080359060200190929190505050607e565b005b60686088565b6040518082815260200191505060405180910390f35b8060008190555050565b6000805490509056fea2646970667358221220e5ff9593bfa9540a34cad5ecbe137dcafcfe1f93e3c4832610438d6f0ece37db64736f6c63430006060033"}, + "0xD2001300000000000000000000000000000000D3": { "balance": "0", "nonce": "0", "storage": {}, "code":"0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063ee919d501461003b578063f0fdf83414610069575b600080fd5b6100676004803603602081101561005157600080fd5b81019080803590602001909291905050506100af565b005b6100956004803603602081101561007f57600080fd5b8101908080359060200190929190505050610108565b604051808215151515815260200191505060405180910390f35b600160008083815260200190815260200160002060006101000a81548160ff021916908315150217905550600080600083815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60006020528060005260406000206000915054906101000a900460ff168156fea2646970667358221220cf479cb746c4b897c88be4ad8e2612a14e27478f91928c49619c98da374a3bf864736f6c63430006000033"}, + "0xD40b89C063a23eb85d739f6fA9B14341838eeB2b": { "balance": "0", "nonce": "0", "storage": {"0x101e368776582e57ab3d116ffe2517c0a585cd5b23174b01e275c2d8329c3d83": "0x0000000000000000000000000000000000000000000000000000000000000001"}, "code":"0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80634df7e3d014610051578063d82cf7901461006f578063ee919d501461009d578063f0fdf834146100cb575b600080fd5b610059610111565b6040518082815260200191505060405180910390f35b61009b6004803603602081101561008557600080fd5b8101908080359060200190929190505050610117565b005b6100c9600480360360208110156100b357600080fd5b810190808035906020019092919050505061017d565b005b6100f7600480360360208110156100e157600080fd5b81019080803590602001909291905050506101ab565b604051808215151515815260200191505060405180910390f35b60015481565b60008082815260200190815260200160002060009054906101000a900460ff16151560011515141561017a57600080600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060018054016001819055505b50565b600160008083815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60006020528060005260406000206000915054906101000a900460ff168156fea264697066735822122000af6f9a0d5c9b8b642648557291c9eb0f9732d60094cf75e14bb192abd97bcc64736f6c63430006000033"} + } } +)E"; -std::string stringToHex( std::string inputString ) { - std::string hexString = toHex( inputString.begin(), inputString.end(), "" ); - hexString.insert( hexString.begin() + hexString.length(), 64 - hexString.length(), '0' ); - return hexString; +BOOST_AUTO_TEST_CASE( getConfigVariableUint256 ) { + ChainParams chainParams; + chainParams = chainParams.loadConfig( genesisInfoSkaleConfigTest ); + + dev::eth::g_configAccesssor.reset( new skutils::json_config_file_accessor( "/home/oleh/work/skaled/build/test/libethereum/PrecompiledConfig.h" ) ); + + std::unique_ptr client; + dev::WithExisting withExisting = dev::WithExisting::Trust; + client.reset( new eth::Client( chainParams, ( int ) chainParams.networkID, + shared_ptr< GasPricer >(), nullptr, nullptr, getDataDir(), + withExisting, dev::eth::TransactionQueue::Limits{ 1, 1, 1, 1 } ) ); + + std::shared_ptr< SkaleHost > skaleHost = std::make_shared< SkaleHost >( *client, nullptr, nullptr, "", false ); + dev::eth::g_skaleHost = skaleHost; + client->injectSkaleHost( skaleHost ); + + PrecompiledExecutor exec = PrecompiledRegistrar::executor( "getConfigVariableUint256" ); + + bytes in = fromHex( numberToHex( 32 ) + stringToHex( "skaleConfig.sChain.nodes.[0].id" ) ); + auto res = exec( bytesConstRef( in.data(), in.size() ) ); + + BOOST_REQUIRE( res.first ); + BOOST_REQUIRE( dev::fromBigEndian( res.second ) == 26 ); + + in = dev::asBytes( "0000000000000000000000000000000000000000000000000000000000000028skaleConfig.sChain.nodes.[0].schainIndex" ); + res = exec( bytesConstRef( in.data(), in.size() ) ); + + BOOST_REQUIRE( res.first ); + BOOST_REQUIRE( dev::fromBigEndian( res.second ) == 3 ); + + in = fromHex( stringToHex( "skaleConfig.sChain.nodes.[0].owner" ) ); + res = exec( bytesConstRef( in.data(), in.size() ) ); + + BOOST_REQUIRE( !res.first ); + + in = fromHex( stringToHex( "skaleConfig.sChain.nodes.[0].unknownField" ) ); + res = exec( bytesConstRef( in.data(), in.size() ) ); + + BOOST_REQUIRE( !res.first ); +} + +BOOST_AUTO_TEST_CASE( getConfigVariableAddress ) { + ChainParams chainParams; + chainParams = chainParams.loadConfig( genesisInfoSkaleConfigTest ); + + PrecompiledExecutor exec = PrecompiledRegistrar::executor( "getConfigVariableUint256" ); + + bytes in = fromHex( stringToHex( "skaleConfig.sChain.nodes.[0].owner" ) ); + auto res = exec( bytesConstRef( in.data(), in.size() ) ); + + BOOST_REQUIRE( res.first ); + BOOST_REQUIRE( res.second == fromHex("0x21abd6db4e347b4e8c937c1c8370e4b5ed3f0dd3db69cbdb7a38e1e50b1b82fc") ); + + in = fromHex( stringToHex( "skaleConfig.sChain.nodes.[0].id" ) ); + res = exec( bytesConstRef( in.data(), in.size() ) ); + + BOOST_REQUIRE( !res.first ); + + in = fromHex( stringToHex( "skaleConfig.sChain.nodes.[0].schainIndex" ) ); + res = exec( bytesConstRef( in.data(), in.size() ) ); + + BOOST_REQUIRE( !res.first ); + + in = fromHex( stringToHex( "skaleConfig.sChain.nodes.[0].unknownField" ) ); + res = exec( bytesConstRef( in.data(), in.size() ) ); + + BOOST_REQUIRE( !res.first ); } struct FilestorageFixture : public TestOutputHelperFixture { From 786882f2ab3b778a1a3859ef426943851ec7883c Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 31 Oct 2023 12:12:36 +0000 Subject: [PATCH 05/30] 1702 improve tests --- .../libethereum/PrecompiledConfig.json | 105 ++++++++++++++++++ .../unittests/libethereum/PrecompiledTest.cpp | 35 ++++-- 2 files changed, 129 insertions(+), 11 deletions(-) create mode 100644 test/unittests/libethereum/PrecompiledConfig.json diff --git a/test/unittests/libethereum/PrecompiledConfig.json b/test/unittests/libethereum/PrecompiledConfig.json new file mode 100644 index 000000000..afea6f9b0 --- /dev/null +++ b/test/unittests/libethereum/PrecompiledConfig.json @@ -0,0 +1,105 @@ +{ + "sealEngine": "Ethash", + "params": { + "accountStartNonce": "0x00", + "homesteadForkBlock": "0x00", + "EIP150ForkBlock": "0x00", + "EIP158ForkBlock": "0x00", + "byzantiumForkBlock": "0x00", + "constantinopleForkBlock": "0x00", + "constantinopleFixForkBlock": "0x00", + "networkID" : "12313219", + "chainID": "0x01", + "maximumExtraDataSize": "0x20", + "tieBreakingGas": false, + "minGasLimit": "0x1388", + "maxGasLimit": "7fffffffffffffff", + "gasLimitBoundDivisor": "0x0400", + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000" + }, + "genesis": { + "nonce": "0x0000000000000042", + "difficulty": "0x020000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x47E7C4" + }, + "skaleConfig": { + "nodeInfo": { + "nodeName": "Node1", + "nodeID": 1112, + "bindIP": "127.0.0.1", + "basePort": 1234, + "logLevel": "trace", + "logLevelProposal": "trace", + "ecdsaKeyName": "NEK:fa112" + }, + "sChain": { + "schainName": "TestChain", + "schainID": 1, + "contractStorageLimit": 32000, + "emptyBlockIntervalMs": -1, + "nodeGroups": { + "1": { + "nodes": { + "30": [ + 0, + 30, + "0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b", + "0x23bbe8db4e347b4e8c937c1c8350e4b5ed33adb3db69cbdb7a38e1f40a1b82fe" + ] + }, + "finish_ts": null, + "bls_public_key": { + "blsPublicKey0": "10860211539819517237363395256510340030868592687836950245163587507107792195621", + "blsPublicKey1": "2419969454136313127863904023626922181546178935031521540751337209075607503568", + "blsPublicKey2": "3399776985251727272800732947224655319335094876742988846345707000254666193993", + "blsPublicKey3": "16982202412630419037827505223148517434545454619191931299977913428346639096984" + } + }, + "0": { + "nodes": { + "26": [ + 3, + 26, + "0x3a581d62b12232dade30c3710215a271984841657449d1f474295a13737b778266f57e298f123ae80cbab7cc35ead1b62a387556f94b326d5c65d4a7aa2abcba", + "0x47bbe8db4e347b4e8c937c1c8350e4b7ed30adb3db69bbdb7a38c1f40a1b82fd" + ] + }, + "finish_ts": 4294967290, + "bls_public_key": { + "blsPublicKey0": "12457351342169393659284905310882617316356538373005664536506840512800919345414", + "blsPublicKey1": "11573096151310346982175966190385407867176668720531590318594794283907348596326", + "blsPublicKey2": "13929944172721019694880576097738949215943314024940461401664534665129747139387", + "blsPublicKey3": "7375214420811287025501422512322868338311819657776589198925786170409964211914" + } + } + }, + "nodes": [ + { "nodeID": 1112, "ip": "127.0.0.1", "basePort": 1234, "schainIndex" : 1, "publicKey": "0xfa", "owner": "0x21abd6db4e347b4e8c937c1c8370e4b5ed3f0dd3db69cbdb7a38e1e50b1b82fc"} + ] + } + }, + "accounts": { + "0000000000000000000000000000000000000001": { "precompiled": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } }, + "0000000000000000000000000000000000000002": { "precompiled": { "name": "sha256", "linear": { "base": 60, "word": 12 } } }, + "0000000000000000000000000000000000000003": { "precompiled": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } }, + "0000000000000000000000000000000000000004": { "precompiled": { "name": "identity", "linear": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000005": { "precompiled": { "name": "modexp", "startingBlock" : "0x2dc6c0" } }, + "0000000000000000000000000000000000000006": { "precompiled": { "name": "alt_bn128_G1_add", "startingBlock" : "0x2dc6c0", "linear": { "base": 500, "word": 0 } } }, + "0000000000000000000000000000000000000007": { "precompiled": { "name": "alt_bn128_G1_mul", "startingBlock" : "0x2dc6c0", "linear": { "base": 40000, "word": 0 } } }, + "0000000000000000000000000000000000000008": { "precompiled": { "name": "alt_bn128_pairing_product", "startingBlock" : "0x2dc6c0" } }, + "0xca4409573a5129a72edf85d6c51e26760fc9c903": { "balance": "100000000000000000000000" }, + "0xD2001300000000000000000000000000000000D2": { "balance": "0", "nonce": "0", "storage": {}, "code":"0x6080604052348015600f57600080fd5b506004361060325760003560e01c8063815b8ab41460375780638273f754146062575b600080fd5b606060048036036020811015604b57600080fd5b8101908080359060200190929190505050606a565b005b60686081565b005b60005a90505b815a82031015607d576070565b5050565b60005a9050609660028281609157fe5b04606a565b5056fea165627a7a72305820f5fb5a65e97cbda96c32b3a2e1497cd6b7989179b5dc29e9875bcbea5a96c4520029"}, + "0xD2001300000000000000000000000000000000D4": { "balance": "0", "nonce": "0", "storage": {}, "code":"0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632098776714610051578063b8bd717f1461007f578063d37165fa146100ad578063fdde8d66146100db575b600080fd5b61007d6004803603602081101561006757600080fd5b8101908080359060200190929190505050610109565b005b6100ab6004803603602081101561009557600080fd5b8101908080359060200190929190505050610136565b005b6100d9600480360360208110156100c357600080fd5b8101908080359060200190929190505050610170565b005b610107600480360360208110156100f157600080fd5b8101908080359060200190929190505050610191565b005b60005a90505b815a8203101561011e5761010f565b600080fd5b815a8203101561013257610123565b5050565b60005a90505b815a8203101561014b5761013c565b600060011461015957600080fd5b5a90505b815a8203101561016c5761015d565b5050565b60005a9050600081830390505b805a8303101561018c5761017d565b505050565b60005a90505b815a820310156101a657610197565b60016101b157600080fd5b5a90505b815a820310156101c4576101b5565b505056fea264697066735822122089b72532621e7d1849e444ee6efaad4fb8771258e6f79755083dce434e5ac94c64736f6c63430006000033"}, + "0xd40B3c51D0ECED279b1697DbdF45d4D19b872164": { "balance": "0", "nonce": "0", "storage": {}, "code":"0x6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d146037578063b05784b8146062575b600080fd5b606060048036036020811015604b57600080fd5b8101908080359060200190929190505050607e565b005b60686088565b6040518082815260200191505060405180910390f35b8060008190555050565b6000805490509056fea2646970667358221220e5ff9593bfa9540a34cad5ecbe137dcafcfe1f93e3c4832610438d6f0ece37db64736f6c63430006060033"}, + "0xD2001300000000000000000000000000000000D3": { "balance": "0", "nonce": "0", "storage": {}, "code":"0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063ee919d501461003b578063f0fdf83414610069575b600080fd5b6100676004803603602081101561005157600080fd5b81019080803590602001909291905050506100af565b005b6100956004803603602081101561007f57600080fd5b8101908080359060200190929190505050610108565b604051808215151515815260200191505060405180910390f35b600160008083815260200190815260200160002060006101000a81548160ff021916908315150217905550600080600083815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60006020528060005260406000206000915054906101000a900460ff168156fea2646970667358221220cf479cb746c4b897c88be4ad8e2612a14e27478f91928c49619c98da374a3bf864736f6c63430006000033"}, + "0xD40b89C063a23eb85d739f6fA9B14341838eeB2b": { "balance": "0", "nonce": "0", "storage": {"0x101e368776582e57ab3d116ffe2517c0a585cd5b23174b01e275c2d8329c3d83": "0x0000000000000000000000000000000000000000000000000000000000000001"}, "code":"0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80634df7e3d014610051578063d82cf7901461006f578063ee919d501461009d578063f0fdf834146100cb575b600080fd5b610059610111565b6040518082815260200191505060405180910390f35b61009b6004803603602081101561008557600080fd5b8101908080359060200190929190505050610117565b005b6100c9600480360360208110156100b357600080fd5b810190808035906020019092919050505061017d565b005b6100f7600480360360208110156100e157600080fd5b81019080803590602001909291905050506101ab565b604051808215151515815260200191505060405180910390f35b60015481565b60008082815260200190815260200160002060009054906101000a900460ff16151560011515141561017a57600080600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060018054016001819055505b50565b600160008083815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60006020528060005260406000206000915054906101000a900460ff168156fea264697066735822122000af6f9a0d5c9b8b642648557291c9eb0f9732d60094cf75e14bb192abd97bcc64736f6c63430006000033"} + } +} diff --git a/test/unittests/libethereum/PrecompiledTest.cpp b/test/unittests/libethereum/PrecompiledTest.cpp index 1bdc069ea..070e7b2c8 100644 --- a/test/unittests/libethereum/PrecompiledTest.cpp +++ b/test/unittests/libethereum/PrecompiledTest.cpp @@ -49,8 +49,9 @@ std::string numberToHex( size_t inputNumber ) { } std::string stringToHex( std::string inputString ) { + size_t strLength = ( ( inputString.size() * 2 + 63 ) / 64 ) * 64; std::string hexString = toHex( inputString.begin(), inputString.end(), "" ); - hexString.insert( hexString.begin() + hexString.length(), 64 - hexString.length(), '0' ); + hexString.insert( hexString.begin() + hexString.length(), strLength - hexString.length(), '0' ); return hexString; } @@ -1687,7 +1688,7 @@ BOOST_AUTO_TEST_CASE( getConfigVariableUint256 ) { ChainParams chainParams; chainParams = chainParams.loadConfig( genesisInfoSkaleConfigTest ); - dev::eth::g_configAccesssor.reset( new skutils::json_config_file_accessor( "/home/oleh/work/skaled/build/test/libethereum/PrecompiledConfig.h" ) ); + dev::eth::g_configAccesssor.reset( new skutils::json_config_file_accessor( "../../test/unittests/libethereum/PrecompiledConfig.json" ) ); std::unique_ptr client; dev::WithExisting withExisting = dev::WithExisting::Trust; @@ -1707,18 +1708,18 @@ BOOST_AUTO_TEST_CASE( getConfigVariableUint256 ) { BOOST_REQUIRE( res.first ); BOOST_REQUIRE( dev::fromBigEndian( res.second ) == 26 ); - in = dev::asBytes( "0000000000000000000000000000000000000000000000000000000000000028skaleConfig.sChain.nodes.[0].schainIndex" ); + in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.[0].schainIndex" ) ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( res.first ); BOOST_REQUIRE( dev::fromBigEndian( res.second ) == 3 ); - in = fromHex( stringToHex( "skaleConfig.sChain.nodes.[0].owner" ) ); + in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.[0].owner" ) ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( !res.first ); - in = fromHex( stringToHex( "skaleConfig.sChain.nodes.[0].unknownField" ) ); + in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.[0].unknownField" ) ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( !res.first ); @@ -1728,25 +1729,37 @@ BOOST_AUTO_TEST_CASE( getConfigVariableAddress ) { ChainParams chainParams; chainParams = chainParams.loadConfig( genesisInfoSkaleConfigTest ); - PrecompiledExecutor exec = PrecompiledRegistrar::executor( "getConfigVariableUint256" ); + dev::eth::g_configAccesssor.reset( new skutils::json_config_file_accessor( "../../test/unittests/libethereum/PrecompiledConfig.json" ) ); + + std::unique_ptr client; + dev::WithExisting withExisting = dev::WithExisting::Trust; + client.reset( new eth::Client( chainParams, ( int ) chainParams.networkID, + shared_ptr< GasPricer >(), nullptr, nullptr, getDataDir(), + withExisting, dev::eth::TransactionQueue::Limits{ 1, 1, 1, 1 } ) ); + + std::shared_ptr< SkaleHost > skaleHost = std::make_shared< SkaleHost >( *client, nullptr, nullptr, "", false ); + dev::eth::g_skaleHost = skaleHost; + client->injectSkaleHost( skaleHost ); + + PrecompiledExecutor exec = PrecompiledRegistrar::executor( "getConfigVariableAddress" ); - bytes in = fromHex( stringToHex( "skaleConfig.sChain.nodes.[0].owner" ) ); + bytes in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.[0].owner" ) ); auto res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( res.first ); - BOOST_REQUIRE( res.second == fromHex("0x21abd6db4e347b4e8c937c1c8370e4b5ed3f0dd3db69cbdb7a38e1e50b1b82fc") ); + BOOST_REQUIRE( res.second == fromHex("0x47bbe8db4e347b4e8c937c1c8350e4b7ed30adb3db69bbdb7a38c1f40a1b82fd") ); - in = fromHex( stringToHex( "skaleConfig.sChain.nodes.[0].id" ) ); + in = fromHex( numberToHex( 32 ) + stringToHex( "skaleConfig.sChain.nodes.[0].id" ) ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( !res.first ); - in = fromHex( stringToHex( "skaleConfig.sChain.nodes.[0].schainIndex" ) ); + in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.[0].schainIndex" ) ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( !res.first ); - in = fromHex( stringToHex( "skaleConfig.sChain.nodes.[0].unknownField" ) ); + in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.[0].unknownField" ) ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( !res.first ); From e9b63e9e47b2a541dd4395e096b5ce8fde3b38f2 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 31 Oct 2023 15:18:22 +0000 Subject: [PATCH 06/30] 1702 remove unnecessary changes --- libethcore/ChainOperationParams.h | 7 ++----- libethereum/ChainParams.cpp | 13 ++----------- libethereum/Precompiled.cpp | 4 ++++ test/unittests/libethereum/ClientTest.cpp | 2 +- .../mapreduce_consensus/ConsensusEngine.cpp | 2 +- 5 files changed, 10 insertions(+), 18 deletions(-) diff --git a/libethcore/ChainOperationParams.h b/libethcore/ChainOperationParams.h index 9bbe6dcb4..db375216d 100644 --- a/libethcore/ChainOperationParams.h +++ b/libethcore/ChainOperationParams.h @@ -78,7 +78,6 @@ struct NodeInfo { uint16_t port; std::string ip6; uint16_t port6; - std::string owner; std::string sgxServerUrl; std::string keyShareName; std::string ecdsaKeyName; @@ -90,7 +89,7 @@ struct NodeInfo { NodeInfo( std::string _name = "TestNode", u256 _id = 1, std::string _ip = "127.0.0.11", uint16_t _port = 11111, std::string _ip6 = "::1", uint16_t _port6 = 11111, - std::string _owner = "", std::string _sgxServerUrl = "", std::string _ecdsaKeyName = "", + std::string _sgxServerUrl = "", std::string _ecdsaKeyName = "", std::string _keyShareName = "", const std::array< std::string, 4 >& _BLSPublicKeys = { "1085704699902305713594457076223282948137075635957851808699051999328" @@ -111,7 +110,6 @@ struct NodeInfo { port = _port; ip6 = _ip6; port6 = _port6; - owner = _owner; sgxServerUrl = _sgxServerUrl; ecdsaKeyName = _ecdsaKeyName; keyShareName = _keyShareName; @@ -133,7 +131,6 @@ struct sChainNode { u256 port6; u256 sChainIndex; std::string publicKey; - std::string owner; std::array< std::string, 4 > blsPublicKey; }; @@ -188,7 +185,7 @@ struct SChain { // HACK This creates one node and allows to run tests - BUT when loading config we need to // delete this explicitly!! sChainNode me = { u256( 1 ), "127.0.0.11", u256( 11111 ), "::1", u256( 11111 ), u256( 1 ), - "0xfa", "", { "0", "1", "0", "1" } }; + "0xfa", { "0", "1", "0", "1" } }; nodes.push_back( me ); } }; diff --git a/libethereum/ChainParams.cpp b/libethereum/ChainParams.cpp index 0d80616ee..2d154082a 100644 --- a/libethereum/ChainParams.cpp +++ b/libethereum/ChainParams.cpp @@ -116,13 +116,9 @@ ChainParams ChainParams::loadConfig( bool syncNode = false; bool archiveMode = false; bool syncFromCatchup = false; - std::string ip, ip6, keyShareName, sgxServerUrl, owner; + std::string ip, ip6, keyShareName, sgxServerUrl; size_t t = 0; uint64_t port = 0, port6 = 0; - try { - owner = infoObj.at( "owner" ).get_str(); - } catch ( ... ) { - } try { ip = infoObj.at( "bindIP" ).get_str(); } catch ( ... ) { @@ -191,7 +187,7 @@ ChainParams ChainParams::loadConfig( } cp.nodeInfo = { nodeName, nodeID, ip, static_cast< uint16_t >( port ), ip6, - static_cast< uint16_t >( port6 ), owner, sgxServerUrl, ecdsaKeyName, keyShareName, + static_cast< uint16_t >( port6 ), sgxServerUrl, ecdsaKeyName, keyShareName, BLSPublicKeys, commonBLSPublicKeys, syncNode, archiveMode, syncFromCatchup }; auto sChainObj = skaleObj.at( "sChain" ).get_obj(); @@ -327,11 +323,6 @@ ChainParams ChainParams::loadConfig( node.id = nodeConfObj.at( "nodeID" ).get_uint64(); node.ip = nodeConfObj.at( "ip" ).get_str(); node.port = nodeConfObj.at( "basePort" ).get_uint64(); - try { - node.owner = nodeConfObj.at( "owner" ).get_str(); - } catch ( ... ) { - node.owner = ""; - } try { node.ip6 = nodeConfObj.at( "ip6" ).get_str(); } catch ( ... ) { diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index a4211a67b..b0bd2a243 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -789,6 +789,8 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableUint256 )( bytesConstRef _in ) { throw std::runtime_error( "Config accessor was not initialized" ); std::string strValue; + // call to skaleConfig.sChain.nodes means call to the historic data + // need to proccess it in a different way if ( isCallToHistoricData( rawName ) ) { if ( !g_skaleHost ) throw std::runtime_error( "SkaleHost accessor was not initialized" ); @@ -846,6 +848,8 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableAddress )( bytesConstRef _in ) { throw std::runtime_error( "Config accessor was not initialized" ); std::string strValue; + // call to skaleConfig.sChain.nodes means call to the historic data + // need to proccess it in a different way if ( isCallToHistoricData( rawName ) ) { if ( !g_skaleHost ) throw std::runtime_error( "SkaleHost accessor was not initialized" ); diff --git a/test/unittests/libethereum/ClientTest.cpp b/test/unittests/libethereum/ClientTest.cpp index 40c7872f9..69791b445 100644 --- a/test/unittests/libethereum/ClientTest.cpp +++ b/test/unittests/libethereum/ClientTest.cpp @@ -902,7 +902,7 @@ static std::string const c_genesisInfoSkaleIMABLSPublicKeyTest = std::string() + } }, "nodes": [ - { "nodeID": 1112, "ip": "127.0.0.1", "basePort": )E"+std::to_string( rand_port ) + R"E(, "schainIndex" : 1, "publicKey": "0xfa", "owner": "0x47bbe8db4e347b4e8c937c1c8350e4b7ed30adb3db69bbdb7a38c1f40a1b82fd"} + { "nodeID": 1112, "ip": "127.0.0.1", "basePort": )E"+std::to_string( rand_port ) + R"E(, "schainIndex" : 1, "publicKey": "0xfa"} ] } }, diff --git a/test/unittests/mapreduce_consensus/ConsensusEngine.cpp b/test/unittests/mapreduce_consensus/ConsensusEngine.cpp index 320415246..8b78e0bd1 100644 --- a/test/unittests/mapreduce_consensus/ConsensusEngine.cpp +++ b/test/unittests/mapreduce_consensus/ConsensusEngine.cpp @@ -214,7 +214,7 @@ class ConsensusExtFaceFixture : public ConsensusExtFace { chainParams.nodeInfo.port = chainParams.nodeInfo.port6 = rand_port; chainParams.sChain.nodes[0].port = chainParams.sChain.nodes[0].port6 = rand_port; - sChainNode node2{u256( 2 ), "127.0.0.12", u256( 11111 ), "::1", u256( 11111 ), u256( 1 ), "0xfa", "", {"0", "1", "0", "1"}}; + sChainNode node2{u256( 2 ), "127.0.0.12", u256( 11111 ), "::1", u256( 11111 ), u256( 1 ), "0xfa", {"0", "1", "0", "1"}}; chainParams.sChain.nodes.push_back( node2 ); ////////////////////////////////////////////// From a348f52d3445f694a345124e0657cab249b73d6a Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 1 Nov 2023 11:44:35 +0000 Subject: [PATCH 07/30] 1702 fix tests --- test/unittests/libethereum/PrecompiledTest.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/unittests/libethereum/PrecompiledTest.cpp b/test/unittests/libethereum/PrecompiledTest.cpp index 070e7b2c8..1e7f2da17 100644 --- a/test/unittests/libethereum/PrecompiledTest.cpp +++ b/test/unittests/libethereum/PrecompiledTest.cpp @@ -21,6 +21,7 @@ */ #include +#include #include #include #include @@ -1692,8 +1693,10 @@ BOOST_AUTO_TEST_CASE( getConfigVariableUint256 ) { std::unique_ptr client; dev::WithExisting withExisting = dev::WithExisting::Trust; + dev::TransientDirectory m_tmpDir; + setenv("DATA_DIR", m_tmpDir.path().c_str(), 1); client.reset( new eth::Client( chainParams, ( int ) chainParams.networkID, - shared_ptr< GasPricer >(), nullptr, nullptr, getDataDir(), + shared_ptr< GasPricer >(), nullptr, nullptr, m_tmpDir.path(), withExisting, dev::eth::TransactionQueue::Limits{ 1, 1, 1, 1 } ) ); std::shared_ptr< SkaleHost > skaleHost = std::make_shared< SkaleHost >( *client, nullptr, nullptr, "", false ); @@ -1733,8 +1736,10 @@ BOOST_AUTO_TEST_CASE( getConfigVariableAddress ) { std::unique_ptr client; dev::WithExisting withExisting = dev::WithExisting::Trust; + dev::TransientDirectory m_tmpDir; + setenv("DATA_DIR", m_tmpDir.path().c_str(), 1); client.reset( new eth::Client( chainParams, ( int ) chainParams.networkID, - shared_ptr< GasPricer >(), nullptr, nullptr, getDataDir(), + shared_ptr< GasPricer >(), nullptr, nullptr, m_tmpDir.path(), withExisting, dev::eth::TransactionQueue::Limits{ 1, 1, 1, 1 } ) ); std::shared_ptr< SkaleHost > skaleHost = std::make_shared< SkaleHost >( *client, nullptr, nullptr, "", false ); From 3815c22c3fa0ba60216c19c253a13b584cae1afe Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Fri, 3 Nov 2023 13:32:39 +0000 Subject: [PATCH 08/30] 1702 introduce PrecompiledConfigPatch --- libethcore/ChainOperationParams.h | 1 + libethereum/ChainParams.cpp | 5 +++++ libethereum/Client.cpp | 3 +++ libethereum/Precompiled.cpp | 5 +++-- libskale/CMakeLists.txt | 2 ++ libskale/PrecompiledConfigPatch.cpp | 11 ++++++++++ libskale/PrecompiledConfigPatch.h | 32 +++++++++++++++++++++++++++++ 7 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 libskale/PrecompiledConfigPatch.cpp create mode 100644 libskale/PrecompiledConfigPatch.h diff --git a/libethcore/ChainOperationParams.h b/libethcore/ChainOperationParams.h index 492ffc0a7..279a3948d 100644 --- a/libethcore/ChainOperationParams.h +++ b/libethcore/ChainOperationParams.h @@ -176,6 +176,7 @@ struct SChain { time_t verifyDaSigsPatchTimestamp = 0; time_t storageDestructionPatchTimestamp = 0; time_t powCheckPatchTimestamp = 0; + time_t precompiledConfigPatchTimestamp = 0; time_t pushZeroPatchTimestamp = 0; time_t skipInvalidTransactionsPatchTimestamp = 0; diff --git a/libethereum/ChainParams.cpp b/libethereum/ChainParams.cpp index 0f9478c4e..86e0d4139 100644 --- a/libethereum/ChainParams.cpp +++ b/libethereum/ChainParams.cpp @@ -266,6 +266,11 @@ ChainParams ChainParams::loadConfig( sChainObj.at( "powCheckPatchTimestamp" ).get_int64() : 0; + s.precompiledConfigPatchTimestamp = + sChainObj.count( "precompiledConfigPatchTimestamp" ) ? + sChainObj.at( "precompiledConfigPatchTimestamp" ).get_int64() : + 0; + s.pushZeroPatchTimestamp = sChainObj.count( "pushZeroPatchTimestamp" ) ? sChainObj.at( "pushZeroPatchTimestamp" ).get_int64() : 0; diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index bf77b920a..652d54552 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -167,6 +168,7 @@ Client::Client( ChainParams const& _params, int _networkID, PushZeroPatch::setTimestamp( chainParams().sChain.pushZeroPatchTimestamp ); SkipInvalidTransactionsPatch::setTimestamp( this->chainParams().sChain.skipInvalidTransactionsPatchTimestamp ); + PrecompiledConfigPatch::setTimestamp( chainParams().sChain.precompiledConfigPatchTimestamp ); } @@ -661,6 +663,7 @@ size_t Client::syncTransactions( POWCheckPatch::lastBlockTimestamp = blockChain().info().timestamp(); PushZeroPatch::lastBlockTimestamp = blockChain().info().timestamp(); SkipInvalidTransactionsPatch::lastBlockTimestamp = blockChain().info().timestamp(); + PrecompiledConfigPatch::lastBlockTimestamp = blockChain().info().timestamp(); DEV_WRITE_GUARDED( x_working ) { assert( !m_working.isSealed() ); diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index b0bd2a243..91804542f 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -791,7 +792,7 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableUint256 )( bytesConstRef _in ) { std::string strValue; // call to skaleConfig.sChain.nodes means call to the historic data // need to proccess it in a different way - if ( isCallToHistoricData( rawName ) ) { + if ( isCallToHistoricData( rawName ) && PrecompiledConfigPatch::isEnabled() ) { if ( !g_skaleHost ) throw std::runtime_error( "SkaleHost accessor was not initialized" ); @@ -850,7 +851,7 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableAddress )( bytesConstRef _in ) { std::string strValue; // call to skaleConfig.sChain.nodes means call to the historic data // need to proccess it in a different way - if ( isCallToHistoricData( rawName ) ) { + if ( isCallToHistoricData( rawName ) && PrecompiledConfigPatch::isEnabled() ) { if ( !g_skaleHost ) throw std::runtime_error( "SkaleHost accessor was not initialized" ); diff --git a/libskale/CMakeLists.txt b/libskale/CMakeLists.txt index ba774b211..aec50d6e0 100644 --- a/libskale/CMakeLists.txt +++ b/libskale/CMakeLists.txt @@ -20,6 +20,7 @@ set(sources OverlayFS.cpp StorageDestructionPatch.cpp POWCheckPatch.cpp + PrecompiledConfigPatch.cpp PushZeroPatch.cpp SkipInvalidTransactionsPatch.cpp ) @@ -40,6 +41,7 @@ set(headers AmsterdamFixPatch.h RevertableFSPatch.h POWCheckPatch.h + PrecompiledConfigPatch.h OverlayFS.h SkipInvalidTransactionsPatch.h ) diff --git a/libskale/PrecompiledConfigPatch.cpp b/libskale/PrecompiledConfigPatch.cpp new file mode 100644 index 000000000..f36557d61 --- /dev/null +++ b/libskale/PrecompiledConfigPatch.cpp @@ -0,0 +1,11 @@ +#include "PrecompiledConfigPatch.h" + +time_t PrecompiledConfigPatch::precompiledConfigPatchTimestamp; +time_t PrecompiledConfigPatch::lastBlockTimestamp; + +bool PrecompiledConfigPatch::isEnabled() { + if ( precompiledConfigPatchTimestamp == 0 ) { + return false; + } + return precompiledConfigPatchTimestamp <= lastBlockTimestamp; +} diff --git a/libskale/PrecompiledConfigPatch.h b/libskale/PrecompiledConfigPatch.h new file mode 100644 index 000000000..776dd47cc --- /dev/null +++ b/libskale/PrecompiledConfigPatch.h @@ -0,0 +1,32 @@ +#ifndef PRECOMPILEDCONFIGPATCH_H +#define PRECOMPILEDCONFIGPATCH_H + +#include +#include + +namespace dev { +namespace eth { +class Client; +} +} // namespace dev + +/* + * Context: enable precompiled contracts to read historical config data + */ +class PrecompiledConfigPatch : public SchainPatch { +public: + static bool isEnabled(); + + static void setTimestamp( time_t _timeStamp ) { + printInfo( __FILE__, _timeStamp ); + precompiledConfigPatchTimestamp = _timeStamp; + } + +private: + friend class dev::eth::Client; + static time_t precompiledConfigPatchTimestamp; + static time_t lastBlockTimestamp; +}; + + +#endif // PRECOMPILEDCONFIGPATCH_H From ee9c48a88945d1c53678b7b7001476d92bb3bdeb Mon Sep 17 00:00:00 2001 From: Stan Kladko <13399135+kladkogex@users.noreply.github.com> Date: Mon, 6 Nov 2023 13:04:15 +0000 Subject: [PATCH 09/30] #1702 renamed owner to nodeAddress --- libethcore/ChainOperationParams.h | 2 +- libethereum/ChainParams.cpp | 4 ++-- libethereum/Client.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libethcore/ChainOperationParams.h b/libethcore/ChainOperationParams.h index 279a3948d..5ac129ec6 100644 --- a/libethcore/ChainOperationParams.h +++ b/libethcore/ChainOperationParams.h @@ -140,7 +140,7 @@ struct GroupNode { u256 id; u256 schainIndex; std::string publicKey; - std::string owner; + std::string address; }; /// skale diff --git a/libethereum/ChainParams.cpp b/libethereum/ChainParams.cpp index 86e0d4139..837530bee 100644 --- a/libethereum/ChainParams.cpp +++ b/libethereum/ChainParams.cpp @@ -296,8 +296,8 @@ ChainParams ChainParams::loadConfig( u256 sChainIndex = groupNodeConfObj[0].get_uint64(); u256 id = groupNodeConfObj[1].get_uint64(); std::string publicKey = groupNodeConfObj[2].get_str(); - std::string owner = groupNodeConfObj[3].get_str(); - groupNodes.push_back( { id, sChainIndex, publicKey, owner } ); + std::string address = groupNodeConfObj[3].get_str(); + groupNodes.push_back( { id, sChainIndex, publicKey, address } ); } std::sort( groupNodes.begin(), groupNodes.end(), []( const GroupNode& lhs, const GroupNode& rhs ) { diff --git a/libethereum/Client.h b/libethereum/Client.h index 90f491282..6579818b2 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -312,7 +312,7 @@ class Client : public ClientBase, protected Worker { // get node owner for historic node in chain std::string getHistoricNodeOwner( unsigned _idx ) const { - return chainParams().sChain.nodeGroups[historicGroupIndex].nodes[_idx].owner; + return chainParams().sChain.nodeGroups[historicGroupIndex].nodes[_idx].address; } void doStateDbCompaction() const { m_state.getOriginalDb()->doCompaction(); } From aa4c0d86febc8d871b9ba03913c975999f0a6367 Mon Sep 17 00:00:00 2001 From: Stan Kladko <13399135+kladkogex@users.noreply.github.com> Date: Mon, 6 Nov 2023 13:07:55 +0000 Subject: [PATCH 10/30] #1702 changed [] to at() for safe vector access --- libethereum/ChainParams.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libethereum/ChainParams.cpp b/libethereum/ChainParams.cpp index 837530bee..930bbf1a5 100644 --- a/libethereum/ChainParams.cpp +++ b/libethereum/ChainParams.cpp @@ -293,10 +293,10 @@ ChainParams ChainParams::loadConfig( auto groupNodesObj = nodeGroupObj["nodes"].get_obj(); for ( const auto& groupNodeConf : groupNodesObj ) { auto groupNodeConfObj = groupNodeConf.second.get_array(); - u256 sChainIndex = groupNodeConfObj[0].get_uint64(); - u256 id = groupNodeConfObj[1].get_uint64(); - std::string publicKey = groupNodeConfObj[2].get_str(); - std::string address = groupNodeConfObj[3].get_str(); + u256 sChainIndex = groupNodeConfObj.at(0).get_uint64(); + u256 id = groupNodeConfObj.at(1).get_uint64(); + std::string publicKey = groupNodeConfObj.at(2).get_str(); + std::string address = groupNodeConfObj.at(3).get_str(); groupNodes.push_back( { id, sChainIndex, publicKey, address } ); } std::sort( groupNodes.begin(), groupNodes.end(), From 95215c78d3554a79b2732f2d6cc5f4c16a015119 Mon Sep 17 00:00:00 2001 From: Stan Kladko <13399135+kladkogex@users.noreply.github.com> Date: Mon, 6 Nov 2023 13:15:07 +0000 Subject: [PATCH 11/30] #1702 added param validation --- libethereum/ChainParams.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libethereum/ChainParams.cpp b/libethereum/ChainParams.cpp index 930bbf1a5..8015741d1 100644 --- a/libethereum/ChainParams.cpp +++ b/libethereum/ChainParams.cpp @@ -297,6 +297,12 @@ ChainParams ChainParams::loadConfig( u256 id = groupNodeConfObj.at(1).get_uint64(); std::string publicKey = groupNodeConfObj.at(2).get_str(); std::string address = groupNodeConfObj.at(3).get_str(); + if (publicKey.empty()) { + BOOST_THROW_EXCEPTION(std::runtime_error("Empty public key in config")); + } + if (address.empty()) { + BOOST_THROW_EXCEPTION(std::runtime_error("Empty address in config")); + } groupNodes.push_back( { id, sChainIndex, publicKey, address } ); } std::sort( groupNodes.begin(), groupNodes.end(), From 4d55443750feb25c6d425eb71643bdc370f2e675 Mon Sep 17 00:00:00 2001 From: Stan Kladko <13399135+kladkogex@users.noreply.github.com> Date: Mon, 6 Nov 2023 13:22:40 +0000 Subject: [PATCH 12/30] #1702 added a log record if node info is empty in config --- libethereum/Client.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 652d54552..0dd5831e7 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -315,8 +315,12 @@ void Client::init( WithExisting _forceAction, u256 _networkId ) { if ( m_dbPath.size() ) Defaults::setDBPath( m_dbPath ); - if ( ChainParams().sChain.nodeGroups.size() > 0 ) + if ( ChainParams().sChain.nodeGroups.size() > 0 ) { initHistoricGroupIndex(); + } else { + LOG( m_logger ) << "Empty node groups in config. " + "This is OK in tests but not OK in production"; + } // init snapshots for not newly created chains if ( number() ) { From 7f136c5c049966b1373936d281e9d4341d865318 Mon Sep 17 00:00:00 2001 From: Stan Kladko <13399135+kladkogex@users.noreply.github.com> Date: Mon, 6 Nov 2023 13:27:41 +0000 Subject: [PATCH 13/30] #1702 changed assertion to runtime error --- libethereum/Client.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 0dd5831e7..c2298f5f2 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -319,7 +319,7 @@ void Client::init( WithExisting _forceAction, u256 _networkId ) { initHistoricGroupIndex(); } else { LOG( m_logger ) << "Empty node groups in config. " - "This is OK in tests but not OK in production"; + "This is OK in tests but not OK in production"; } // init snapshots for not newly created chains @@ -1095,7 +1095,9 @@ Block Client::blockByNumber( BlockNumber _h ) const { auto readState = m_state.createStateReadOnlyCopy(); readState.mutableHistoricState().setRootByBlockNumber( _h ); - DEV_GUARDED( m_blockImportMutex ) { return Block( bc(), hash, readState ); } + DEV_GUARDED( m_blockImportMutex ) { + return Block( bc(), hash, readState ); + } assert( false ); return Block( bc() ); } catch ( Exception& ex ) { @@ -1109,7 +1111,9 @@ Block Client::blockByNumber( BlockNumber _h ) const { Block Client::latestBlock() const { // TODO Why it returns not-filled block??! (see Block ctor) try { - DEV_GUARDED( m_blockImportMutex ) { return Block( bc(), bc().currentHash(), m_state ); } + DEV_GUARDED( m_blockImportMutex ) { + return Block( bc(), bc().currentHash(), m_state ); + } assert( false ); return Block( bc() ); } catch ( Exception& ex ) { @@ -1257,7 +1261,7 @@ ExecutionResult Client::call( Address const& _from, u256 _value, Address _dest, t.checkOutExternalGas( ~u256( 0 ) ); if ( _ff == FudgeFactor::Lenient ) { historicBlock.mutableState().mutableHistoricState().addBalance( - _from, ( u256 )( t.gas() * t.gasPrice() + t.value() ) ); + _from, ( u256 ) ( t.gas() * t.gasPrice() + t.value() ) ); } ret = historicBlock.executeHistoricCall( bc().lastBlockHashes(), t ); @@ -1281,7 +1285,8 @@ ExecutionResult Client::call( Address const& _from, u256 _value, Address _dest, t.forceChainId( chainParams().chainID ); t.checkOutExternalGas( ~u256( 0 ) ); if ( _ff == FudgeFactor::Lenient ) - temp.mutableState().addBalance( _from, ( u256 )( t.gas() * t.gasPrice() + t.value() ) ); + temp.mutableState().addBalance( + _from, ( u256 ) ( t.gas() * t.gasPrice() + t.value() ) ); ret = temp.execute( bc().lastBlockHashes(), t, skale::Permanence::Reverted ); } catch ( InvalidNonce const& in ) { LOG( m_logger ) << "exception in client call(1):" @@ -1309,7 +1314,11 @@ void Client::initHistoricGroupIndex() { chainParams().sChain.nodeGroups.end(), [¤tBlockTimestamp]( const dev::eth::NodeGroup& ng ) { return currentBlockTimestamp <= ng.finishTs; } ); - assert( it != chainParams().sChain.nodeGroups.end() ); + + if ( it == chainParams().sChain.nodeGroups.end() ) { + BOOST_THROW_EXCEPTION( + std::runtime_error( "Assertion failed: it == chainParams().sChain.nodeGroups.end()" ) ); + } if ( it != chainParams().sChain.nodeGroups.begin() ) { auto prevIt = std::prev( it ); From ea28913eeee2500bb9e376ac2a4a15cc42391023 Mon Sep 17 00:00:00 2001 From: Stan Kladko <13399135+kladkogex@users.noreply.github.com> Date: Mon, 6 Nov 2023 13:30:19 +0000 Subject: [PATCH 14/30] #1702 changed assertion to runtime error --- libethereum/Client.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index c2298f5f2..b67f6b9b8 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -1335,7 +1335,10 @@ void Client::updateHistoricGroupIndex() { uint64_t currentFinishTs = chainParams().sChain.nodeGroups[historicGroupIndex].finishTs; if ( blockTimestamp >= currentFinishTs ) ++historicGroupIndex; - assert( historicGroupIndex < chainParams().sChain.nodeGroups.size() ); + if ( historicGroupIndex >= chainParams().sChain.nodeGroups.size() ) { + BOOST_THROW_EXCEPTION( std::runtime_error( + "Assertion failed: historicGroupIndex >= chainParams().sChain.nodeGroups.size())" ) ); + } } // new block watch From 3652a82cba16eaf01c901b09ade04859b58df455 Mon Sep 17 00:00:00 2001 From: Stan Kladko <13399135+kladkogex@users.noreply.github.com> Date: Mon, 6 Nov 2023 13:41:53 +0000 Subject: [PATCH 15/30] #1702 changed to standard boost library --- libethereum/Precompiled.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index 91804542f..dd0337608 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -758,7 +759,8 @@ static dev::u256 stat_parse_u256_hex_or_dec( const std::string& strValue ) { } static bool isCallToHistoricData( const std::string& callData ) { - return skutils::tools::wildcmp( "skaleConfig.sChain.nodes.*", callData.c_str() ); + // in C++ 20 there is string::starts_with, but we do not use C++ 20 yet + boost::algorithm::starts_with(callData, "skaleConfig.sChain.nodes."); } static std::pair< std::string, unsigned > parseHistoricFieldReuqest( const std::string& callData ) { From 41ddce97888ed4f4cfc5ab93b3b68df3d22e20ef Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 6 Nov 2023 15:51:42 +0000 Subject: [PATCH 16/30] 1702 fix build --- libethereum/ChainParams.cpp | 16 ++++++++-------- libethereum/Client.cpp | 13 ++++--------- libethereum/Precompiled.cpp | 2 +- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/libethereum/ChainParams.cpp b/libethereum/ChainParams.cpp index 8015741d1..72d8a2eb3 100644 --- a/libethereum/ChainParams.cpp +++ b/libethereum/ChainParams.cpp @@ -293,15 +293,15 @@ ChainParams ChainParams::loadConfig( auto groupNodesObj = nodeGroupObj["nodes"].get_obj(); for ( const auto& groupNodeConf : groupNodesObj ) { auto groupNodeConfObj = groupNodeConf.second.get_array(); - u256 sChainIndex = groupNodeConfObj.at(0).get_uint64(); - u256 id = groupNodeConfObj.at(1).get_uint64(); - std::string publicKey = groupNodeConfObj.at(2).get_str(); - std::string address = groupNodeConfObj.at(3).get_str(); - if (publicKey.empty()) { - BOOST_THROW_EXCEPTION(std::runtime_error("Empty public key in config")); + u256 sChainIndex = groupNodeConfObj.at( 0 ).get_uint64(); + u256 id = groupNodeConfObj.at( 1 ).get_uint64(); + std::string publicKey = groupNodeConfObj.at( 2 ).get_str(); + std::string address = groupNodeConfObj.at( 3 ).get_str(); + if ( publicKey.empty() ) { + BOOST_THROW_EXCEPTION( std::runtime_error( "Empty public key in config" ) ); } - if (address.empty()) { - BOOST_THROW_EXCEPTION(std::runtime_error("Empty address in config")); + if ( address.empty() ) { + BOOST_THROW_EXCEPTION( std::runtime_error( "Empty address in config" ) ); } groupNodes.push_back( { id, sChainIndex, publicKey, address } ); } diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index b67f6b9b8..2ba3f5290 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -1095,9 +1095,7 @@ Block Client::blockByNumber( BlockNumber _h ) const { auto readState = m_state.createStateReadOnlyCopy(); readState.mutableHistoricState().setRootByBlockNumber( _h ); - DEV_GUARDED( m_blockImportMutex ) { - return Block( bc(), hash, readState ); - } + DEV_GUARDED( m_blockImportMutex ) { return Block( bc(), hash, readState ); } assert( false ); return Block( bc() ); } catch ( Exception& ex ) { @@ -1111,9 +1109,7 @@ Block Client::blockByNumber( BlockNumber _h ) const { Block Client::latestBlock() const { // TODO Why it returns not-filled block??! (see Block ctor) try { - DEV_GUARDED( m_blockImportMutex ) { - return Block( bc(), bc().currentHash(), m_state ); - } + DEV_GUARDED( m_blockImportMutex ) { return Block( bc(), bc().currentHash(), m_state ); } assert( false ); return Block( bc() ); } catch ( Exception& ex ) { @@ -1261,7 +1257,7 @@ ExecutionResult Client::call( Address const& _from, u256 _value, Address _dest, t.checkOutExternalGas( ~u256( 0 ) ); if ( _ff == FudgeFactor::Lenient ) { historicBlock.mutableState().mutableHistoricState().addBalance( - _from, ( u256 ) ( t.gas() * t.gasPrice() + t.value() ) ); + _from, ( u256 )( t.gas() * t.gasPrice() + t.value() ) ); } ret = historicBlock.executeHistoricCall( bc().lastBlockHashes(), t ); @@ -1285,8 +1281,7 @@ ExecutionResult Client::call( Address const& _from, u256 _value, Address _dest, t.forceChainId( chainParams().chainID ); t.checkOutExternalGas( ~u256( 0 ) ); if ( _ff == FudgeFactor::Lenient ) - temp.mutableState().addBalance( - _from, ( u256 ) ( t.gas() * t.gasPrice() + t.value() ) ); + temp.mutableState().addBalance( _from, ( u256 )( t.gas() * t.gasPrice() + t.value() ) ); ret = temp.execute( bc().lastBlockHashes(), t, skale::Permanence::Reverted ); } catch ( InvalidNonce const& in ) { LOG( m_logger ) << "exception in client call(1):" diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index dd0337608..0c4f24570 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -760,7 +760,7 @@ static dev::u256 stat_parse_u256_hex_or_dec( const std::string& strValue ) { static bool isCallToHistoricData( const std::string& callData ) { // in C++ 20 there is string::starts_with, but we do not use C++ 20 yet - boost::algorithm::starts_with(callData, "skaleConfig.sChain.nodes."); + return boost::algorithm::starts_with( callData, "skaleConfig.sChain.nodes." ); } static std::pair< std::string, unsigned > parseHistoricFieldReuqest( const std::string& callData ) { From 399e9b1457ff4d71f511f783989bfba9204ebcd4 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 6 Nov 2023 15:55:04 +0000 Subject: [PATCH 17/30] 1702 deny access to some config fields from precompileds for security reasons --- libethereum/Precompiled.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index 0c4f24570..257f60343 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -679,19 +679,21 @@ static const std::list< std::string > g_listReadableConfigParts{ "sealEngine", //"genesis.*" //"params.*", - "skaleConfig.nodeInfo.wallets.ima.commonBLSPublicKey*", - "skaleConfig.nodeInfo.wallets.ima.BLSPublicKey*", + // skaled-1702 + // remove these config field from public access for security reasons + // "skaleConfig.nodeInfo.wallets.ima.commonBLSPublicKey*", + // "skaleConfig.nodeInfo.wallets.ima.BLSPublicKey*", - "skaleConfig.nodeInfo.nodeName", "skaleConfig.nodeInfo.nodeID", - "skaleConfig.nodeInfo.basePort*", "skaleConfig.nodeInfo.*RpcPort*", - "skaleConfig.nodeInfo.acceptors", "skaleConfig.nodeInfo.max-connections", - "skaleConfig.nodeInfo.max-http-queues", "skaleConfig.nodeInfo.ws-mode", + // "skaleConfig.nodeInfo.nodeName", "skaleConfig.nodeInfo.nodeID", + // "skaleConfig.nodeInfo.basePort*", "skaleConfig.nodeInfo.*RpcPort*", + // "skaleConfig.nodeInfo.acceptors", "skaleConfig.nodeInfo.max-connections", + // "skaleConfig.nodeInfo.max-http-queues", "skaleConfig.nodeInfo.ws-mode", - "skaleConfig.contractSettings.*", + // "skaleConfig.contractSettings.*", - "skaleConfig.sChain.emptyBlockIntervalMs", + // "skaleConfig.sChain.emptyBlockIntervalMs", - "skaleConfig.sChain.schainName", "skaleConfig.sChain.schainID", + // "skaleConfig.sChain.schainName", "skaleConfig.sChain.schainID", "skaleConfig.sChain.nodes.*" }; From cfbd4359aeeff778238fac381e2be37ff21f32c0 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 7 Nov 2023 11:32:53 +0000 Subject: [PATCH 18/30] 1702 fix tests --- libethereum/Client.cpp | 2 +- libethereum/ValidationSchemes.cpp | 2 + test/unittests/libethereum/ClientTest.cpp | 3 +- .../libethereum/PrecompiledConfig.json | 1 + .../unittests/libethereum/PrecompiledTest.cpp | 55 +++++++++++++------ 5 files changed, 43 insertions(+), 20 deletions(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 2ba3f5290..0822ba107 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -315,7 +315,7 @@ void Client::init( WithExisting _forceAction, u256 _networkId ) { if ( m_dbPath.size() ) Defaults::setDBPath( m_dbPath ); - if ( ChainParams().sChain.nodeGroups.size() > 0 ) { + if ( chainParams().sChain.nodeGroups.size() > 0 ) { initHistoricGroupIndex(); } else { LOG( m_logger ) << "Empty node groups in config. " diff --git a/libethereum/ValidationSchemes.cpp b/libethereum/ValidationSchemes.cpp index fdf83fdeb..75bd07af1 100644 --- a/libethereum/ValidationSchemes.cpp +++ b/libethereum/ValidationSchemes.cpp @@ -272,6 +272,8 @@ void validateConfigJson( js::mObject const& _obj ) { { "nodeGroups", { { js::obj_type }, JsonFieldPresence::Optional } }, { "nodeGroups", { { js::obj_type }, JsonFieldPresence::Optional } }, { "skipInvalidTransactionsPatchTimestamp", + { { js::int_type }, JsonFieldPresence::Optional } }, + { "precompiledConfigPatchTimestamp", { { js::int_type }, JsonFieldPresence::Optional } } } ); js::mArray const& nodes = sChain.at( "nodes" ).get_array(); diff --git a/test/unittests/libethereum/ClientTest.cpp b/test/unittests/libethereum/ClientTest.cpp index 69791b445..791ae56c4 100644 --- a/test/unittests/libethereum/ClientTest.cpp +++ b/test/unittests/libethereum/ClientTest.cpp @@ -865,6 +865,7 @@ static std::string const c_genesisInfoSkaleIMABLSPublicKeyTest = std::string() + "schainName": "TestChain", "schainID": 1, "emptyBlockIntervalMs": -1, + "precompiledConfigPatchTimestamp": 1, "nodeGroups": { "1": { "nodes": { @@ -919,7 +920,7 @@ static std::string const c_genesisInfoSkaleIMABLSPublicKeyTest = std::string() + } )E"; -BOOST_AUTO_TEST_CASE( initAndUpdateIMABLSPUblicKey ) { +BOOST_AUTO_TEST_CASE( initAndUpdateHistoricConfigFields ) { TestClientFixture fixture( c_genesisInfoSkaleIMABLSPublicKeyTest ); ClientTest* testClient = asClientTest( fixture.ethereum() ); diff --git a/test/unittests/libethereum/PrecompiledConfig.json b/test/unittests/libethereum/PrecompiledConfig.json index afea6f9b0..d5889d2b5 100644 --- a/test/unittests/libethereum/PrecompiledConfig.json +++ b/test/unittests/libethereum/PrecompiledConfig.json @@ -44,6 +44,7 @@ "schainName": "TestChain", "schainID": 1, "contractStorageLimit": 32000, + "precompiledConfigPatchTimestamp": 1, "emptyBlockIntervalMs": -1, "nodeGroups": { "1": { diff --git a/test/unittests/libethereum/PrecompiledTest.cpp b/test/unittests/libethereum/PrecompiledTest.cpp index 1e7f2da17..8de629387 100644 --- a/test/unittests/libethereum/PrecompiledTest.cpp +++ b/test/unittests/libethereum/PrecompiledTest.cpp @@ -26,12 +26,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include @@ -1624,12 +1626,13 @@ static std::string const genesisInfoSkaleConfigTest = std::string() + "schainName": "TestChain", "schainID": 1, "contractStorageLimit": 32000, + "precompiledConfigPatchTimestamp": 1, "emptyBlockIntervalMs": -1, "nodeGroups": { "1": { "nodes": { "30": [ - 0, + 13, 30, "0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b", "0x23bbe8db4e347b4e8c937c1c8350e4b5ed33adb3db69cbdb7a38e1f40a1b82fe" @@ -1688,20 +1691,28 @@ static std::string const genesisInfoSkaleConfigTest = std::string() + BOOST_AUTO_TEST_CASE( getConfigVariableUint256 ) { ChainParams chainParams; chainParams = chainParams.loadConfig( genesisInfoSkaleConfigTest ); + chainParams.sealEngineName = NoProof::name(); + chainParams.allowFutureBlocks = true; dev::eth::g_configAccesssor.reset( new skutils::json_config_file_accessor( "../../test/unittests/libethereum/PrecompiledConfig.json" ) ); std::unique_ptr client; - dev::WithExisting withExisting = dev::WithExisting::Trust; dev::TransientDirectory m_tmpDir; + auto monitor = make_shared< InstanceMonitor >("test"); setenv("DATA_DIR", m_tmpDir.path().c_str(), 1); - client.reset( new eth::Client( chainParams, ( int ) chainParams.networkID, - shared_ptr< GasPricer >(), nullptr, nullptr, m_tmpDir.path(), - withExisting, dev::eth::TransactionQueue::Limits{ 1, 1, 1, 1 } ) ); + client.reset( new eth::ClientTest( chainParams, ( int ) chainParams.networkID, + shared_ptr< GasPricer >(), nullptr, monitor, m_tmpDir.path(), dev::WithExisting::Kill ) ); - std::shared_ptr< SkaleHost > skaleHost = std::make_shared< SkaleHost >( *client, nullptr, nullptr, "", false ); - dev::eth::g_skaleHost = skaleHost; - client->injectSkaleHost( skaleHost ); + client->injectSkaleHost(); + client->startWorking(); + + client->setAuthor( Address("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") ); + + ClientTest* testClient = asClientTest( client.get() ); + + testClient->mineBlocks( 1 ); + testClient->importTransactionsAsBlock( dev::eth::Transactions(), 1000, 4294967294 ); + dev::eth::g_skaleHost = testClient->skaleHost(); PrecompiledExecutor exec = PrecompiledRegistrar::executor( "getConfigVariableUint256" ); @@ -1709,13 +1720,13 @@ BOOST_AUTO_TEST_CASE( getConfigVariableUint256 ) { auto res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( res.first ); - BOOST_REQUIRE( dev::fromBigEndian( res.second ) == 26 ); + BOOST_REQUIRE( dev::fromBigEndian( res.second ) == 30 ); in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.[0].schainIndex" ) ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( res.first ); - BOOST_REQUIRE( dev::fromBigEndian( res.second ) == 3 ); + BOOST_REQUIRE( dev::fromBigEndian( res.second ) == 13 ); in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.[0].owner" ) ); res = exec( bytesConstRef( in.data(), in.size() ) ); @@ -1731,20 +1742,28 @@ BOOST_AUTO_TEST_CASE( getConfigVariableUint256 ) { BOOST_AUTO_TEST_CASE( getConfigVariableAddress ) { ChainParams chainParams; chainParams = chainParams.loadConfig( genesisInfoSkaleConfigTest ); + chainParams.sealEngineName = NoProof::name(); + chainParams.allowFutureBlocks = true; dev::eth::g_configAccesssor.reset( new skutils::json_config_file_accessor( "../../test/unittests/libethereum/PrecompiledConfig.json" ) ); std::unique_ptr client; - dev::WithExisting withExisting = dev::WithExisting::Trust; dev::TransientDirectory m_tmpDir; + auto monitor = make_shared< InstanceMonitor >("test"); setenv("DATA_DIR", m_tmpDir.path().c_str(), 1); - client.reset( new eth::Client( chainParams, ( int ) chainParams.networkID, - shared_ptr< GasPricer >(), nullptr, nullptr, m_tmpDir.path(), - withExisting, dev::eth::TransactionQueue::Limits{ 1, 1, 1, 1 } ) ); + client.reset( new eth::ClientTest( chainParams, ( int ) chainParams.networkID, + shared_ptr< GasPricer >(), nullptr, monitor, m_tmpDir.path(), dev::WithExisting::Kill ) ); + + client->injectSkaleHost(); + client->startWorking(); + + client->setAuthor( Address("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") ); + + ClientTest* testClient = asClientTest( client.get() ); - std::shared_ptr< SkaleHost > skaleHost = std::make_shared< SkaleHost >( *client, nullptr, nullptr, "", false ); - dev::eth::g_skaleHost = skaleHost; - client->injectSkaleHost( skaleHost ); + testClient->mineBlocks( 1 ); + testClient->importTransactionsAsBlock( dev::eth::Transactions(), 1000, 4294967294 ); + dev::eth::g_skaleHost = testClient->skaleHost(); PrecompiledExecutor exec = PrecompiledRegistrar::executor( "getConfigVariableAddress" ); @@ -1752,7 +1771,7 @@ BOOST_AUTO_TEST_CASE( getConfigVariableAddress ) { auto res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( res.first ); - BOOST_REQUIRE( res.second == fromHex("0x47bbe8db4e347b4e8c937c1c8350e4b7ed30adb3db69bbdb7a38c1f40a1b82fd") ); + BOOST_REQUIRE( res.second == fromHex("0x23bbe8db4e347b4e8c937c1c8350e4b5ed33adb3db69cbdb7a38e1f40a1b82fe") ); in = fromHex( numberToHex( 32 ) + stringToHex( "skaleConfig.sChain.nodes.[0].id" ) ); res = exec( bytesConstRef( in.data(), in.size() ) ); From 80618dd3dbb07f6b73eb202635824eafe42a2805 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 7 Nov 2023 18:53:56 +0000 Subject: [PATCH 19/30] #1702 improve code quality --- libethereum/Precompiled.cpp | 89 +++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 34 deletions(-) diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index 257f60343..8dc4ed7d1 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -675,27 +676,7 @@ ETH_REGISTER_PRECOMPILED( logTextMessage )( bytesConstRef _in ) { return { false, response }; // 1st false - means bad error occur } -static const std::list< std::string > g_listReadableConfigParts{ "sealEngine", - //"genesis.*" - //"params.*", - - // skaled-1702 - // remove these config field from public access for security reasons - // "skaleConfig.nodeInfo.wallets.ima.commonBLSPublicKey*", - // "skaleConfig.nodeInfo.wallets.ima.BLSPublicKey*", - - // "skaleConfig.nodeInfo.nodeName", "skaleConfig.nodeInfo.nodeID", - // "skaleConfig.nodeInfo.basePort*", "skaleConfig.nodeInfo.*RpcPort*", - // "skaleConfig.nodeInfo.acceptors", "skaleConfig.nodeInfo.max-connections", - // "skaleConfig.nodeInfo.max-http-queues", "skaleConfig.nodeInfo.ws-mode", - - // "skaleConfig.contractSettings.*", - - // "skaleConfig.sChain.emptyBlockIntervalMs", - - // "skaleConfig.sChain.schainName", "skaleConfig.sChain.schainID", - - "skaleConfig.sChain.nodes.*" }; +static const std::list< std::string > g_listReadableConfigParts{ "skaleConfig.sChain.nodes." }; static bool stat_is_accessible_json_path( const std::string& strPath ) { if ( strPath.empty() ) @@ -704,7 +685,7 @@ static bool stat_is_accessible_json_path( const std::string& strPath ) { itEnd = g_listReadableConfigParts.cend(); for ( ; itWalk != itEnd; ++itWalk ) { const std::string strWildCard = ( *itWalk ); - if ( skutils::tools::wildcmp( strWildCard.c_str(), strPath.c_str() ) ) + if ( boost::algorithm::starts_with( strPath, strWildCard ) ) return true; } return false; @@ -766,14 +747,31 @@ static bool isCallToHistoricData( const std::string& callData ) { } static std::pair< std::string, unsigned > parseHistoricFieldReuqest( const std::string& callData ) { - size_t numberLength = callData.find( ']' ) - callData.find( '[' ) - 1; - unsigned id = std::stoul( callData.substr( callData.find( '[' ) + 1, numberLength ) ); + auto idPosBegin = callData.find( '[' ); + auto idPosEnd = callData.find( ']' ); + if ( idPosBegin == std::string::npos || idPosEnd == std::string::npos || + idPosBegin > idPosEnd ) { + // means the input is incorrect + return { "unknown field", 0 }; + } + if ( callData.substr( 0, idPosBegin ) != "skaleConfig.sChain.nodes." ) { + // invalid input + return { "unknown field", 0 }; + } + for ( size_t pos = idPosBegin + 1; pos != idPosEnd; ++pos ) { + if ( !std::isdigit( callData[pos] ) ) { + // invalid input + return { "unknown field", 0 }; + } + } + size_t numberLength = idPosEnd - idPosBegin - 1; + unsigned id = std::stoul( callData.substr( idPosBegin + 1, numberLength ) ); std::string fieldName; - if ( callData.find( "id" ) != std::string::npos ) { + if ( boost::algorithm::ends_with( callData.c_str(), "id" ) ) { fieldName = "id"; - } else if ( callData.find( "schainIndex" ) != std::string::npos ) { + } else if ( boost::algorithm::ends_with( callData.c_str(), "schainIndex" ) ) { fieldName = "schainIndex"; - } else if ( callData.find( "owner" ) != std::string::npos ) { + } else if ( boost::algorithm::ends_with( callData.c_str(), "owner" ) ) { fieldName = "owner"; } else { fieldName = "unknown field"; @@ -781,6 +779,21 @@ static std::pair< std::string, unsigned > parseHistoricFieldReuqest( const std:: return { fieldName, id }; } +/* + * this precompiled contract is designed to get access to specific integer config values + * and works as key / values map + * input: bytes - length + path to config variable + * output: bytes - config variable value + * + * example: + * to request value for input=skaleConfig.sChain.nodes.[0].id + * one should pass the following + * toBytes( ( ( input.length + 1 ) / 32 ) * 32) + toBytes(input) + * + * variables available through this precompiled contract: + * 1. id - node id for INDEX node in schain group for current block number + * 2. schainIndex - schain index for INDEX node in schain group for current block number + */ ETH_REGISTER_PRECOMPILED( getConfigVariableUint256 )( bytesConstRef _in ) { try { size_t lengthName; @@ -818,11 +831,7 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableUint256 )( bytesConstRef _in ) { joValue.is_string() ? joValue.get< std::string >() : joValue.dump() ); } - // dev::u256 uValue( strValue.c_str() ); - dev::u256 uValue = stat_parse_u256_hex_or_dec( strValue ); - // std::cout << "------------ Loaded config var \"" - // << rawName << "\" value is " << uValue - // << "\n"; + dev::u256 uValue = jsToInt( strValue ); bytes response = toBigEndian( uValue ); return { true, response }; } catch ( std::exception& ex ) { @@ -840,6 +849,19 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableUint256 )( bytesConstRef _in ) { return { false, response }; // 1st false - means bad error occur } +/* + * this precompiled contract is designed to get access to specific config values that are ETH + * addresses and works as key / values map input: bytes - length + path to config variable output: + * bytes - config variable value + * + * example: + * to request value for input=skaleConfig.sChain.nodes.[1].owner + * one should pass the following + * toBytes( ( ( input.length + 1 ) / 32 ) * 32) + toBytes(input) + * + * variables available through this precompiled contract: + * 1. owner - address for INDEX node in schain group for current block number + */ ETH_REGISTER_PRECOMPILED( getConfigVariableAddress )( bytesConstRef _in ) { try { size_t lengthName; @@ -875,8 +897,7 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableAddress )( bytesConstRef _in ) { joValue.is_string() ? joValue.get< std::string >() : joValue.dump() ); } - dev::u256 uValue( strValue.c_str() ); - + dev::u256 uValue( strValue ); bytes response = toBigEndian( uValue ); return { true, response }; } catch ( std::exception& ex ) { From 582b526d033a9bbc21d1823a38b4714c2f91f8aa Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 8 Nov 2023 13:33:08 +0000 Subject: [PATCH 20/30] #1702 use common approach to access config variables --- libethereum/Precompiled.cpp | 62 +++++++++---------- .../unittests/libethereum/PrecompiledTest.cpp | 16 ++--- 2 files changed, 38 insertions(+), 40 deletions(-) diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index 8dc4ed7d1..64c4a724b 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -746,32 +747,18 @@ static bool isCallToHistoricData( const std::string& callData ) { return boost::algorithm::starts_with( callData, "skaleConfig.sChain.nodes." ); } -static std::pair< std::string, unsigned > parseHistoricFieldReuqest( const std::string& callData ) { - auto idPosBegin = callData.find( '[' ); - auto idPosEnd = callData.find( ']' ); - if ( idPosBegin == std::string::npos || idPosEnd == std::string::npos || - idPosBegin > idPosEnd ) { - // means the input is incorrect - return { "unknown field", 0 }; - } - if ( callData.substr( 0, idPosBegin ) != "skaleConfig.sChain.nodes." ) { - // invalid input - return { "unknown field", 0 }; - } - for ( size_t pos = idPosBegin + 1; pos != idPosEnd; ++pos ) { - if ( !std::isdigit( callData[pos] ) ) { - // invalid input - return { "unknown field", 0 }; - } - } - size_t numberLength = idPosEnd - idPosBegin - 1; - unsigned id = std::stoul( callData.substr( idPosBegin + 1, numberLength ) ); +static std::pair< std::string, unsigned > parseHistoricFieldReuqest( std::string callData ) { + std::vector< std::string > splitted; + boost::split( splitted, callData, boost::is_any_of( "." ) ); + // first 3 elements are skaleConfig, sChain, nodes - it was checked before + unsigned id = std::stoul( splitted[3] ); std::string fieldName; - if ( boost::algorithm::ends_with( callData.c_str(), "id" ) ) { + boost::trim_if( splitted[4], []( char c ) { return c == '\0'; } ); + if ( splitted[4] == "id" ) { fieldName = "id"; - } else if ( boost::algorithm::ends_with( callData.c_str(), "schainIndex" ) ) { + } else if ( splitted[4] == "schainIndex" ) { fieldName = "schainIndex"; - } else if ( boost::algorithm::ends_with( callData.c_str(), "owner" ) ) { + } else if ( splitted[4] == "owner" ) { fieldName = "owner"; } else { fieldName = "unknown field"; @@ -785,14 +772,19 @@ static std::pair< std::string, unsigned > parseHistoricFieldReuqest( const std:: * input: bytes - length + path to config variable * output: bytes - config variable value * - * example: - * to request value for input=skaleConfig.sChain.nodes.[0].id - * one should pass the following - * toBytes( ( ( input.length + 1 ) / 32 ) * 32) + toBytes(input) - * * variables available through this precompiled contract: * 1. id - node id for INDEX node in schain group for current block number * 2. schainIndex - schain index for INDEX node in schain group for current block number + * to access those variables one should use the following scheme: + * prefix=skaleConfig.sChain.nodes - to access corresponding structure inside skaled + * index - node index user wants to get access to + * field - the field user wants to request + * + * example: + * to request the value for 1-st node (1 based) for the node id field the input should be + * input=skaleConfig.sChain.nodes.0.id (inside skaled node indexes are 0 based) + * so one should pass the following as calldata: + * toBytes( ( ( input.length + 1 ) / 32 ) * 32) + toBytes(input) */ ETH_REGISTER_PRECOMPILED( getConfigVariableUint256 )( bytesConstRef _in ) { try { @@ -854,13 +846,19 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableUint256 )( bytesConstRef _in ) { * addresses and works as key / values map input: bytes - length + path to config variable output: * bytes - config variable value * + * variables available through this precompiled contract: + * 1. owner - address for INDEX node in schain group for current block number + * to access those variables one should use the following scheme: + * prefix=skaleConfig.sChain.nodes - to access corresponding structure inside skaled + * index - node index user wants to get access to + * field - the field user wants to request + * * example: - * to request value for input=skaleConfig.sChain.nodes.[1].owner - * one should pass the following + * to request the value for 2-nd node (1 based) for the owner field the input should be + * input=skaleConfig.sChain.nodes.1.owner (inside skaled node indexes are 0 based) + * so one should pass the following as calldata * toBytes( ( ( input.length + 1 ) / 32 ) * 32) + toBytes(input) * - * variables available through this precompiled contract: - * 1. owner - address for INDEX node in schain group for current block number */ ETH_REGISTER_PRECOMPILED( getConfigVariableAddress )( bytesConstRef _in ) { try { diff --git a/test/unittests/libethereum/PrecompiledTest.cpp b/test/unittests/libethereum/PrecompiledTest.cpp index 8de629387..f380d6745 100644 --- a/test/unittests/libethereum/PrecompiledTest.cpp +++ b/test/unittests/libethereum/PrecompiledTest.cpp @@ -1716,24 +1716,24 @@ BOOST_AUTO_TEST_CASE( getConfigVariableUint256 ) { PrecompiledExecutor exec = PrecompiledRegistrar::executor( "getConfigVariableUint256" ); - bytes in = fromHex( numberToHex( 32 ) + stringToHex( "skaleConfig.sChain.nodes.[0].id" ) ); + bytes in = fromHex( numberToHex( 32 ) + stringToHex( "skaleConfig.sChain.nodes.0.id" ) ); auto res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( res.first ); BOOST_REQUIRE( dev::fromBigEndian( res.second ) == 30 ); - in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.[0].schainIndex" ) ); + in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.0.schainIndex" ) ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( res.first ); BOOST_REQUIRE( dev::fromBigEndian( res.second ) == 13 ); - in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.[0].owner" ) ); + in = fromHex( numberToHex( 32 ) + stringToHex( "skaleConfig.sChain.nodes.0.owner" ) ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( !res.first ); - in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.[0].unknownField" ) ); + in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.0.unknownField" ) ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( !res.first ); @@ -1767,23 +1767,23 @@ BOOST_AUTO_TEST_CASE( getConfigVariableAddress ) { PrecompiledExecutor exec = PrecompiledRegistrar::executor( "getConfigVariableAddress" ); - bytes in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.[0].owner" ) ); + bytes in = fromHex( numberToHex( 32 ) + stringToHex( "skaleConfig.sChain.nodes.0.owner" ) ); auto res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( res.first ); BOOST_REQUIRE( res.second == fromHex("0x23bbe8db4e347b4e8c937c1c8350e4b5ed33adb3db69cbdb7a38e1f40a1b82fe") ); - in = fromHex( numberToHex( 32 ) + stringToHex( "skaleConfig.sChain.nodes.[0].id" ) ); + in = fromHex( numberToHex( 32 ) + stringToHex( "skaleConfig.sChain.nodes.0.id" ) ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( !res.first ); - in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.[0].schainIndex" ) ); + in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.0.schainIndex" ) ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( !res.first ); - in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.[0].unknownField" ) ); + in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.0.unknownField" ) ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( !res.first ); From ea694fc79379e4144f7c297cfdba71ded0d786c8 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 8 Nov 2023 15:35:08 +0000 Subject: [PATCH 21/30] #1702 improve code quality --- libethereum/Precompiled.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index 64c4a724b..339829186 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -747,21 +747,19 @@ static bool isCallToHistoricData( const std::string& callData ) { return boost::algorithm::starts_with( callData, "skaleConfig.sChain.nodes." ); } -static std::pair< std::string, unsigned > parseHistoricFieldReuqest( std::string callData ) { +static std::pair< std::string, unsigned > parseHistoricFieldRequest( std::string callData ) { std::vector< std::string > splitted; boost::split( splitted, callData, boost::is_any_of( "." ) ); // first 3 elements are skaleConfig, sChain, nodes - it was checked before - unsigned id = std::stoul( splitted[3] ); + unsigned id = std::stoul( splitted.at( 3 ) ); std::string fieldName; - boost::trim_if( splitted[4], []( char c ) { return c == '\0'; } ); - if ( splitted[4] == "id" ) { - fieldName = "id"; - } else if ( splitted[4] == "schainIndex" ) { - fieldName = "schainIndex"; - } else if ( splitted[4] == "owner" ) { - fieldName = "owner"; + boost::trim_if( splitted.at( 4 ), []( char c ) { return c == '\0'; } ); + std::set< std::string > allowedValues{ "id", "schainIndex", "owner" }; + fieldName = splitted.at( 4 ); + if ( allowedValues.count( fieldName ) ) { + return { fieldName, id }; } else { - fieldName = "unknown field"; + BOOST_THROW_EXCEPTION( std::runtime_error( "Unknown field:" + fieldName ) ); } return { fieldName, id }; } @@ -807,7 +805,7 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableUint256 )( bytesConstRef _in ) { std::string field; unsigned id; - std::tie( field, id ) = parseHistoricFieldReuqest( rawName ); + std::tie( field, id ) = parseHistoricFieldRequest( rawName ); if ( field == "id" ) { strValue = g_skaleHost->getHistoricNodeId( id ); } else if ( field == "schainIndex" ) { @@ -881,7 +879,7 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableAddress )( bytesConstRef _in ) { std::string field; unsigned id; - std::tie( field, id ) = parseHistoricFieldReuqest( rawName ); + std::tie( field, id ) = parseHistoricFieldRequest( rawName ); if ( field == "owner" ) { strValue = g_skaleHost->getHistoricNodeOwner( id ); } else { From ca16ebf0a361abad1c20c94431dcc1cc16ddb344 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 13 Nov 2023 13:35:21 +0000 Subject: [PATCH 22/30] #1702 improve input proccessing for precompileds --- libethereum/Precompiled.cpp | 14 ++++++--- .../unittests/libethereum/PrecompiledTest.cpp | 31 ++++++++++++++----- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index 339829186..fbc2be280 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -251,10 +251,16 @@ static Logger& getLogger( int a_severity = VerbosityTrace ) { static void convertBytesToString( bytesConstRef _in, size_t _startPosition, std::string& _out, size_t& _stringLength ) { + if ( _in.size() < UINT256_SIZE ) { + throw std::runtime_error( "Input is too short - invalid input in convertBytesToString()" ); + } bigint const sstringLength( parseBigEndianRightPadded( _in, _startPosition, UINT256_SIZE ) ); _stringLength = sstringLength.convert_to< size_t >(); + if ( _startPosition + UINT256_SIZE + _stringLength > _in.size() ) { + throw std::runtime_error( "Invalid input in convertBytesToString()" ); + } vector_ref< const unsigned char > byteFilename = - _in.cropped( _startPosition + 32, _stringLength ); + _in.cropped( _startPosition + UINT256_SIZE, _stringLength ); _out = std::string( ( char* ) byteFilename.data(), _stringLength ); } @@ -753,7 +759,6 @@ static std::pair< std::string, unsigned > parseHistoricFieldRequest( std::string // first 3 elements are skaleConfig, sChain, nodes - it was checked before unsigned id = std::stoul( splitted.at( 3 ) ); std::string fieldName; - boost::trim_if( splitted.at( 4 ), []( char c ) { return c == '\0'; } ); std::set< std::string > allowedValues{ "id", "schainIndex", "owner" }; fieldName = splitted.at( 4 ); if ( allowedValues.count( fieldName ) ) { @@ -782,7 +787,7 @@ static std::pair< std::string, unsigned > parseHistoricFieldRequest( std::string * to request the value for 1-st node (1 based) for the node id field the input should be * input=skaleConfig.sChain.nodes.0.id (inside skaled node indexes are 0 based) * so one should pass the following as calldata: - * toBytes( ( ( input.length + 1 ) / 32 ) * 32) + toBytes(input) + * toBytes( input.length + toBytes(input) ) */ ETH_REGISTER_PRECOMPILED( getConfigVariableUint256 )( bytesConstRef _in ) { try { @@ -855,8 +860,7 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableUint256 )( bytesConstRef _in ) { * to request the value for 2-nd node (1 based) for the owner field the input should be * input=skaleConfig.sChain.nodes.1.owner (inside skaled node indexes are 0 based) * so one should pass the following as calldata - * toBytes( ( ( input.length + 1 ) / 32 ) * 32) + toBytes(input) - * + * toBytes( input.length + toBytes(input) ) */ ETH_REGISTER_PRECOMPILED( getConfigVariableAddress )( bytesConstRef _in ) { try { diff --git a/test/unittests/libethereum/PrecompiledTest.cpp b/test/unittests/libethereum/PrecompiledTest.cpp index f380d6745..4ede56bb3 100644 --- a/test/unittests/libethereum/PrecompiledTest.cpp +++ b/test/unittests/libethereum/PrecompiledTest.cpp @@ -1715,25 +1715,32 @@ BOOST_AUTO_TEST_CASE( getConfigVariableUint256 ) { dev::eth::g_skaleHost = testClient->skaleHost(); PrecompiledExecutor exec = PrecompiledRegistrar::executor( "getConfigVariableUint256" ); + std::string input = stringToHex( "skaleConfig.sChain.nodes.0.id" ); + input = input.substr(0, 58); // remove 0s in the end - bytes in = fromHex( numberToHex( 32 ) + stringToHex( "skaleConfig.sChain.nodes.0.id" ) ); + bytes in = fromHex( numberToHex( 29 ) + input ); auto res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( res.first ); BOOST_REQUIRE( dev::fromBigEndian( res.second ) == 30 ); - in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.0.schainIndex" ) ); + input = stringToHex( "skaleConfig.sChain.nodes.0.schainIndex" ); + input = input.substr(0, 76); // remove 0s in the end + in = fromHex( numberToHex( 38 ) + input ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( res.first ); BOOST_REQUIRE( dev::fromBigEndian( res.second ) == 13 ); - in = fromHex( numberToHex( 32 ) + stringToHex( "skaleConfig.sChain.nodes.0.owner" ) ); + input = stringToHex( "skaleConfig.sChain.nodes.0.owner" ); + in = fromHex( numberToHex( 32 ) + input ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( !res.first ); - in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.0.unknownField" ) ); + input = stringToHex( "skaleConfig.sChain.nodes.0.unknownField" ); + input = input.substr(0, 78); // remove 0s in the end + in = fromHex( numberToHex( 39 ) + input ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( !res.first ); @@ -1767,23 +1774,31 @@ BOOST_AUTO_TEST_CASE( getConfigVariableAddress ) { PrecompiledExecutor exec = PrecompiledRegistrar::executor( "getConfigVariableAddress" ); - bytes in = fromHex( numberToHex( 32 ) + stringToHex( "skaleConfig.sChain.nodes.0.owner" ) ); + std::string input = stringToHex( "skaleConfig.sChain.nodes.0.owner" ); + bytes in = fromHex( numberToHex( 32 ) + input ); auto res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( res.first ); BOOST_REQUIRE( res.second == fromHex("0x23bbe8db4e347b4e8c937c1c8350e4b5ed33adb3db69cbdb7a38e1f40a1b82fe") ); - in = fromHex( numberToHex( 32 ) + stringToHex( "skaleConfig.sChain.nodes.0.id" ) ); + input = stringToHex( "skaleConfig.sChain.nodes.0.id" ); + input = input.substr(0, 58); // remove 0s in the end + + in = fromHex( numberToHex( 29 ) + input ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( !res.first ); - in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.0.schainIndex" ) ); + input = stringToHex( "skaleConfig.sChain.nodes.0.schainIndex" ); + input = input.substr(0, 76); // remove 0s in the end + in = fromHex( numberToHex( 38 ) + input ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( !res.first ); - in = fromHex( numberToHex( 64 ) + stringToHex( "skaleConfig.sChain.nodes.0.unknownField" ) ); + input = stringToHex( "skaleConfig.sChain.nodes.0.unknownField" ); + input = input.substr(0, 78); // remove 0s in the end + in = fromHex( numberToHex( 39 ) + input ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( !res.first ); From 49956134bfea1c270c9a83c40a8181946d432f0d Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 13 Nov 2023 13:45:58 +0000 Subject: [PATCH 23/30] #1702 add more checks --- libethereum/Precompiled.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index fbc2be280..a4b7123f5 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -255,6 +255,10 @@ static void convertBytesToString( throw std::runtime_error( "Input is too short - invalid input in convertBytesToString()" ); } bigint const sstringLength( parseBigEndianRightPadded( _in, _startPosition, UINT256_SIZE ) ); + if ( sstringLength < 0 ) { + throw std::runtime_error( + "Negative string length - invalid input in convertBytesToString()" ); + } _stringLength = sstringLength.convert_to< size_t >(); if ( _startPosition + UINT256_SIZE + _stringLength > _in.size() ) { throw std::runtime_error( "Invalid input in convertBytesToString()" ); From edd62d4671c07a748776dd9688d12de8dbb84c39 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 13 Nov 2023 17:44:45 +0000 Subject: [PATCH 24/30] #1702 improve tests --- .../unittests/libethereum/PrecompiledTest.cpp | 97 +++++++++++++------ 1 file changed, 65 insertions(+), 32 deletions(-) diff --git a/test/unittests/libethereum/PrecompiledTest.cpp b/test/unittests/libethereum/PrecompiledTest.cpp index 4ede56bb3..06ecba280 100644 --- a/test/unittests/libethereum/PrecompiledTest.cpp +++ b/test/unittests/libethereum/PrecompiledTest.cpp @@ -1688,7 +1688,7 @@ static std::string const genesisInfoSkaleConfigTest = std::string() + } )E"; -BOOST_AUTO_TEST_CASE( getConfigVariableUint256 ) { +BOOST_AUTO_TEST_CASE( getConfigVariable ) { ChainParams chainParams; chainParams = chainParams.loadConfig( genesisInfoSkaleConfigTest ); chainParams.sealEngineName = NoProof::name(); @@ -1744,39 +1744,12 @@ BOOST_AUTO_TEST_CASE( getConfigVariableUint256 ) { res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( !res.first ); -} - -BOOST_AUTO_TEST_CASE( getConfigVariableAddress ) { - ChainParams chainParams; - chainParams = chainParams.loadConfig( genesisInfoSkaleConfigTest ); - chainParams.sealEngineName = NoProof::name(); - chainParams.allowFutureBlocks = true; - - dev::eth::g_configAccesssor.reset( new skutils::json_config_file_accessor( "../../test/unittests/libethereum/PrecompiledConfig.json" ) ); - - std::unique_ptr client; - dev::TransientDirectory m_tmpDir; - auto monitor = make_shared< InstanceMonitor >("test"); - setenv("DATA_DIR", m_tmpDir.path().c_str(), 1); - client.reset( new eth::ClientTest( chainParams, ( int ) chainParams.networkID, - shared_ptr< GasPricer >(), nullptr, monitor, m_tmpDir.path(), dev::WithExisting::Kill ) ); - - client->injectSkaleHost(); - client->startWorking(); - client->setAuthor( Address("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") ); - - ClientTest* testClient = asClientTest( client.get() ); + exec = PrecompiledRegistrar::executor( "getConfigVariableAddress" ); - testClient->mineBlocks( 1 ); - testClient->importTransactionsAsBlock( dev::eth::Transactions(), 1000, 4294967294 ); - dev::eth::g_skaleHost = testClient->skaleHost(); - - PrecompiledExecutor exec = PrecompiledRegistrar::executor( "getConfigVariableAddress" ); - - std::string input = stringToHex( "skaleConfig.sChain.nodes.0.owner" ); - bytes in = fromHex( numberToHex( 32 ) + input ); - auto res = exec( bytesConstRef( in.data(), in.size() ) ); + input = stringToHex( "skaleConfig.sChain.nodes.0.owner" ); + in = fromHex( numberToHex( 32 ) + input ); + res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( res.first ); BOOST_REQUIRE( res.second == fromHex("0x23bbe8db4e347b4e8c937c1c8350e4b5ed33adb3db69cbdb7a38e1f40a1b82fe") ); @@ -1804,6 +1777,66 @@ BOOST_AUTO_TEST_CASE( getConfigVariableAddress ) { BOOST_REQUIRE( !res.first ); } +// temporary merge tests for getConfigVariable +// because of the specifics in test design +//BOOST_AUTO_TEST_CASE( getConfigVariableAddress ) { +// ChainParams chainParams; +// chainParams = chainParams.loadConfig( genesisInfoSkaleConfigTest ); +// chainParams.sealEngineName = NoProof::name(); +// chainParams.allowFutureBlocks = true; + +// dev::eth::g_configAccesssor.reset( new skutils::json_config_file_accessor( "../../test/unittests/libethereum/PrecompiledConfig.json" ) ); + +// std::unique_ptr client; +// dev::TransientDirectory m_tmpDir; +// auto monitor = make_shared< InstanceMonitor >("test"); +// setenv("DATA_DIR", m_tmpDir.path().c_str(), 1); +// client.reset( new eth::ClientTest( chainParams, ( int ) chainParams.networkID, +// shared_ptr< GasPricer >(), nullptr, monitor, m_tmpDir.path(), dev::WithExisting::Kill ) ); + +// client->injectSkaleHost(); +// client->startWorking(); + +// client->setAuthor( Address("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") ); + +// ClientTest* testClient = asClientTest( client.get() ); + +// testClient->mineBlocks( 1 ); +// testClient->importTransactionsAsBlock( dev::eth::Transactions(), 1000, 4294967294 ); +// dev::eth::g_skaleHost = testClient->skaleHost(); + +// PrecompiledExecutor exec = PrecompiledRegistrar::executor( "getConfigVariableAddress" ); + +// std::string input = stringToHex( "skaleConfig.sChain.nodes.0.owner" ); +// bytes in = fromHex( numberToHex( 32 ) + input ); +// auto res = exec( bytesConstRef( in.data(), in.size() ) ); + +// BOOST_REQUIRE( res.first ); +// BOOST_REQUIRE( res.second == fromHex("0x23bbe8db4e347b4e8c937c1c8350e4b5ed33adb3db69cbdb7a38e1f40a1b82fe") ); + +// input = stringToHex( "skaleConfig.sChain.nodes.0.id" ); +// input = input.substr(0, 58); // remove 0s in the end + +// in = fromHex( numberToHex( 29 ) + input ); +// res = exec( bytesConstRef( in.data(), in.size() ) ); + +// BOOST_REQUIRE( !res.first ); + +// input = stringToHex( "skaleConfig.sChain.nodes.0.schainIndex" ); +// input = input.substr(0, 76); // remove 0s in the end +// in = fromHex( numberToHex( 38 ) + input ); +// res = exec( bytesConstRef( in.data(), in.size() ) ); + +// BOOST_REQUIRE( !res.first ); + +// input = stringToHex( "skaleConfig.sChain.nodes.0.unknownField" ); +// input = input.substr(0, 78); // remove 0s in the end +// in = fromHex( numberToHex( 39 ) + input ); +// res = exec( bytesConstRef( in.data(), in.size() ) ); + +// BOOST_REQUIRE( !res.first ); +//} + struct FilestorageFixture : public TestOutputHelperFixture { FilestorageFixture() { ownerAddress = Address( "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" ); From 4b510812f6d6ccd9a5577786db5c08b9bcffffc1 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 22 Nov 2023 11:47:18 +0000 Subject: [PATCH 25/30] #1702 pass historic publicKey instead of address --- libethcore/ChainOperationParams.h | 1 - libethereum/ChainParams.cpp | 6 +- libethereum/Client.h | 4 +- libethereum/Precompiled.cpp | 91 ++++++++++--------- libethereum/SkaleHost.cpp | 4 +- libethereum/SkaleHost.h | 4 +- test/unittests/libethereum/ClientTest.cpp | 12 +-- .../libethereum/PrecompiledConfig.json | 6 +- .../unittests/libethereum/PrecompiledTest.cpp | 10 +- 9 files changed, 64 insertions(+), 74 deletions(-) diff --git a/libethcore/ChainOperationParams.h b/libethcore/ChainOperationParams.h index 5ac129ec6..3e442229d 100644 --- a/libethcore/ChainOperationParams.h +++ b/libethcore/ChainOperationParams.h @@ -140,7 +140,6 @@ struct GroupNode { u256 id; u256 schainIndex; std::string publicKey; - std::string address; }; /// skale diff --git a/libethereum/ChainParams.cpp b/libethereum/ChainParams.cpp index 72d8a2eb3..fec3da5a5 100644 --- a/libethereum/ChainParams.cpp +++ b/libethereum/ChainParams.cpp @@ -296,14 +296,10 @@ ChainParams ChainParams::loadConfig( u256 sChainIndex = groupNodeConfObj.at( 0 ).get_uint64(); u256 id = groupNodeConfObj.at( 1 ).get_uint64(); std::string publicKey = groupNodeConfObj.at( 2 ).get_str(); - std::string address = groupNodeConfObj.at( 3 ).get_str(); if ( publicKey.empty() ) { BOOST_THROW_EXCEPTION( std::runtime_error( "Empty public key in config" ) ); } - if ( address.empty() ) { - BOOST_THROW_EXCEPTION( std::runtime_error( "Empty address in config" ) ); - } - groupNodes.push_back( { id, sChainIndex, publicKey, address } ); + groupNodes.push_back( { id, sChainIndex, publicKey } ); } std::sort( groupNodes.begin(), groupNodes.end(), []( const GroupNode& lhs, const GroupNode& rhs ) { diff --git a/libethereum/Client.h b/libethereum/Client.h index 6579818b2..6ad196a0d 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -311,8 +311,8 @@ class Client : public ClientBase, protected Worker { } // get node owner for historic node in chain - std::string getHistoricNodeOwner( unsigned _idx ) const { - return chainParams().sChain.nodeGroups[historicGroupIndex].nodes[_idx].address; + std::string getHistoricNodePublicKey( unsigned _idx ) const { + return chainParams().sChain.nodeGroups[historicGroupIndex].nodes[_idx].publicKey; } void doStateDbCompaction() const { m_state.getOriginalDb()->doCompaction(); } diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index a4b7123f5..9bc432a45 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -763,7 +763,7 @@ static std::pair< std::string, unsigned > parseHistoricFieldRequest( std::string // first 3 elements are skaleConfig, sChain, nodes - it was checked before unsigned id = std::stoul( splitted.at( 3 ) ); std::string fieldName; - std::set< std::string > allowedValues{ "id", "schainIndex", "owner" }; + std::set< std::string > allowedValues{ "id", "schainIndex", "publicKey" }; fieldName = splitted.at( 4 ); if ( allowedValues.count( fieldName ) ) { return { fieldName, id }; @@ -848,25 +848,61 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableUint256 )( bytesConstRef _in ) { return { false, response }; // 1st false - means bad error occur } +ETH_REGISTER_PRECOMPILED( getConfigVariableAddress )( bytesConstRef _in ) { + try { + size_t lengthName; + std::string rawName; + convertBytesToString( _in, 0, rawName, lengthName ); + if ( !stat_is_accessible_json_path( rawName ) ) + throw std::runtime_error( + "Security poicy violation, inaccessible configuration JSON path: " + rawName ); + + if ( !g_configAccesssor ) + throw std::runtime_error( "Config accessor was not initialized" ); + + nlohmann::json joConfig = g_configAccesssor->getConfigJSON(); + nlohmann::json joValue = + skutils::json_config_file_accessor::stat_extract_at_path( joConfig, rawName ); + std::string strValue = skutils::tools::trim_copy( + joValue.is_string() ? joValue.get< std::string >() : joValue.dump() ); + + dev::u256 uValue( strValue ); + bytes response = toBigEndian( uValue ); + return { true, response }; + } catch ( std::exception& ex ) { + std::string strError = ex.what(); + if ( strError.empty() ) + strError = "exception without description"; + LOG( getLogger( VerbosityError ) ) + << "Exception in precompiled/getConfigVariableAddress(): " << strError << "\n"; + } catch ( ... ) { + LOG( getLogger( VerbosityError ) ) + << "Unknown exception in precompiled/getConfigVariableAddress()\n"; + } + u256 code = 0; + bytes response = toBigEndian( code ); + return { false, response }; // 1st false - means bad error occur +} + /* - * this precompiled contract is designed to get access to specific config values that are ETH - * addresses and works as key / values map input: bytes - length + path to config variable output: + * this precompiled contract is designed to get access to specific config values that are + * strings and works as key / values map input: bytes - length + path to config variable output: * bytes - config variable value * * variables available through this precompiled contract: - * 1. owner - address for INDEX node in schain group for current block number + * 1. publicKey - ETH public key for INDEX node in schain group for current block number * to access those variables one should use the following scheme: * prefix=skaleConfig.sChain.nodes - to access corresponding structure inside skaled * index - node index user wants to get access to * field - the field user wants to request * * example: - * to request the value for 2-nd node (1 based) for the owner field the input should be - * input=skaleConfig.sChain.nodes.1.owner (inside skaled node indexes are 0 based) + * to request the value for 2-nd node (1 based) for the publicKey field the input should be + * input=skaleConfig.sChain.nodes.1.publicKey (inside skaled node indexes are 0 based) * so one should pass the following as calldata * toBytes( input.length + toBytes(input) ) */ -ETH_REGISTER_PRECOMPILED( getConfigVariableAddress )( bytesConstRef _in ) { +ETH_REGISTER_PRECOMPILED( getConfigVariableString )( bytesConstRef _in ) { try { size_t lengthName; std::string rawName; @@ -877,7 +913,6 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableAddress )( bytesConstRef _in ) { if ( !g_configAccesssor ) throw std::runtime_error( "Config accessor was not initialized" ); - std::string strValue; // call to skaleConfig.sChain.nodes means call to the historic data // need to proccess it in a different way @@ -888,8 +923,8 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableAddress )( bytesConstRef _in ) { std::string field; unsigned id; std::tie( field, id ) = parseHistoricFieldRequest( rawName ); - if ( field == "owner" ) { - strValue = g_skaleHost->getHistoricNodeOwner( id ); + if ( field == "publicKey" ) { + strValue = g_skaleHost->getHistoricNodePublicKey( id ); } else { throw std::runtime_error( "Incorrect config field" ); } @@ -900,41 +935,7 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableAddress )( bytesConstRef _in ) { strValue = skutils::tools::trim_copy( joValue.is_string() ? joValue.get< std::string >() : joValue.dump() ); } - - dev::u256 uValue( strValue ); - bytes response = toBigEndian( uValue ); - return { true, response }; - } catch ( std::exception& ex ) { - std::string strError = ex.what(); - if ( strError.empty() ) - strError = "exception without description"; - LOG( getLogger( VerbosityError ) ) - << "Exception in precompiled/getConfigVariableAddress(): " << strError << "\n"; - } catch ( ... ) { - LOG( getLogger( VerbosityError ) ) - << "Unknown exception in precompiled/getConfigVariableAddress()\n"; - } - u256 code = 0; - bytes response = toBigEndian( code ); - return { false, response }; // 1st false - means bad error occur -} - -ETH_REGISTER_PRECOMPILED( getConfigVariableString )( bytesConstRef _in ) { - try { - size_t lengthName; - std::string rawName; - convertBytesToString( _in, 0, rawName, lengthName ); - if ( !stat_is_accessible_json_path( rawName ) ) - throw std::runtime_error( - "Security poicy violation, inaccessible configuration JSON path: " + rawName ); - - if ( !g_configAccesssor ) - throw std::runtime_error( "Config accessor was not initialized" ); - nlohmann::json joConfig = g_configAccesssor->getConfigJSON(); - nlohmann::json joValue = - skutils::json_config_file_accessor::stat_extract_at_path( joConfig, rawName ); - std::string strValue = joValue.is_string() ? joValue.get< std::string >() : joValue.dump(); - bytes response = stat_string_to_bytes_with_length( strValue ); + bytes response = dev::asBytes( strValue ); return { true, response }; } catch ( std::exception& ex ) { std::string strError = ex.what(); diff --git a/libethereum/SkaleHost.cpp b/libethereum/SkaleHost.cpp index 53a318180..3db110bd3 100644 --- a/libethereum/SkaleHost.cpp +++ b/libethereum/SkaleHost.cpp @@ -958,8 +958,8 @@ std::string SkaleHost::getHistoricNodeIndex( unsigned _index ) const { return m_client.getHistoricNodeIndex( _index ); } -std::string SkaleHost::getHistoricNodeOwner( unsigned _idx ) const { - return m_client.getHistoricNodeOwner( _idx ); +std::string SkaleHost::getHistoricNodePublicKey( unsigned _idx ) const { + return m_client.getHistoricNodePublicKey( _idx ); } uint64_t SkaleHost::submitOracleRequest( diff --git a/libethereum/SkaleHost.h b/libethereum/SkaleHost.h index b5ae631c9..82a4c6357 100644 --- a/libethereum/SkaleHost.h +++ b/libethereum/SkaleHost.h @@ -132,8 +132,8 @@ class SkaleHost { // get schain index for historic node in chain std::string getHistoricNodeIndex( unsigned _idx ) const; - // get node owner for historic node in chain - std::string getHistoricNodeOwner( unsigned _idx ) const; + // get public key for historic node in chain + std::string getHistoricNodePublicKey( unsigned _idx ) const; uint64_t submitOracleRequest( const string& _spec, string& _receipt, string& _errorMessage ); uint64_t checkOracleResult( const string& _receipt, string& _result ); diff --git a/test/unittests/libethereum/ClientTest.cpp b/test/unittests/libethereum/ClientTest.cpp index 791ae56c4..1ba92556c 100644 --- a/test/unittests/libethereum/ClientTest.cpp +++ b/test/unittests/libethereum/ClientTest.cpp @@ -815,7 +815,7 @@ BOOST_AUTO_TEST_CASE( consumptionWithReverts ) { BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE( IMABLSPublicKey ) +BOOST_AUTO_TEST_SUITE( getHistoricNodesData ) static std::string const c_genesisInfoSkaleIMABLSPublicKeyTest = std::string() + R"E( @@ -872,8 +872,7 @@ static std::string const c_genesisInfoSkaleIMABLSPublicKeyTest = std::string() + "30": [ 0, 30, - "0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b", - "0x23bbe8db4e347b4e8c937c1c8350e4b5ed33adb3db69cbdb7a38e1f40a1b82fe" + "0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b" ] }, "finish_ts": null, @@ -889,8 +888,7 @@ static std::string const c_genesisInfoSkaleIMABLSPublicKeyTest = std::string() + "26": [ 3, 26, - "0x3a581d62b12232dade30c3710215a271984841657449d1f474295a13737b778266f57e298f123ae80cbab7cc35ead1b62a387556f94b326d5c65d4a7aa2abcba", - "0x47bbe8db4e347b4e8c937c1c8350e4b7ed30adb3db69bbdb7a38c1f40a1b82fd" + "0x3a581d62b12232dade30c3710215a271984841657449d1f474295a13737b778266f57e298f123ae80cbab7cc35ead1b62a387556f94b326d5c65d4a7aa2abcba" ] }, "finish_ts": 4294967290, @@ -927,7 +925,7 @@ BOOST_AUTO_TEST_CASE( initAndUpdateHistoricConfigFields ) { std::array< std::string, 4 > imaBLSPublicKeyOnStartUp = { "12457351342169393659284905310882617316356538373005664536506840512800919345414", "11573096151310346982175966190385407867176668720531590318594794283907348596326", "13929944172721019694880576097738949215943314024940461401664534665129747139387", "7375214420811287025501422512322868338311819657776589198925786170409964211914" }; BOOST_REQUIRE( testClient->getIMABLSPublicKey() == imaBLSPublicKeyOnStartUp ); - BOOST_REQUIRE( testClient->getHistoricNodeOwner( 0 ) == "0x47bbe8db4e347b4e8c937c1c8350e4b7ed30adb3db69bbdb7a38c1f40a1b82fd" ); + BOOST_REQUIRE( testClient->getHistoricNodePublicKey( 0 ) == "0x3a581d62b12232dade30c3710215a271984841657449d1f474295a13737b778266f57e298f123ae80cbab7cc35ead1b62a387556f94b326d5c65d4a7aa2abcba" ); BOOST_REQUIRE( testClient->getHistoricNodeId( 0 ) == "26" ); BOOST_REQUIRE( testClient->getHistoricNodeIndex( 0 ) == "3" ); @@ -938,7 +936,7 @@ BOOST_AUTO_TEST_CASE( initAndUpdateHistoricConfigFields ) { std::array< std::string, 4 > imaBLSPublicKeyAfterBlock = { "10860211539819517237363395256510340030868592687836950245163587507107792195621", "2419969454136313127863904023626922181546178935031521540751337209075607503568", "3399776985251727272800732947224655319335094876742988846345707000254666193993", "16982202412630419037827505223148517434545454619191931299977913428346639096984" }; BOOST_REQUIRE( testClient->getIMABLSPublicKey() == imaBLSPublicKeyAfterBlock ); - BOOST_REQUIRE( testClient->getHistoricNodeOwner( 0 ) == "0x23bbe8db4e347b4e8c937c1c8350e4b5ed33adb3db69cbdb7a38e1f40a1b82fe" ); + BOOST_REQUIRE( testClient->getHistoricNodePublicKey( 0 ) == "0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b" ); BOOST_REQUIRE( testClient->getHistoricNodeId( 0 ) == "30" ); BOOST_REQUIRE( testClient->getHistoricNodeIndex( 0 ) == "0" ); } diff --git a/test/unittests/libethereum/PrecompiledConfig.json b/test/unittests/libethereum/PrecompiledConfig.json index d5889d2b5..356aeced1 100644 --- a/test/unittests/libethereum/PrecompiledConfig.json +++ b/test/unittests/libethereum/PrecompiledConfig.json @@ -52,8 +52,7 @@ "30": [ 0, 30, - "0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b", - "0x23bbe8db4e347b4e8c937c1c8350e4b5ed33adb3db69cbdb7a38e1f40a1b82fe" + "0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b" ] }, "finish_ts": null, @@ -69,8 +68,7 @@ "26": [ 3, 26, - "0x3a581d62b12232dade30c3710215a271984841657449d1f474295a13737b778266f57e298f123ae80cbab7cc35ead1b62a387556f94b326d5c65d4a7aa2abcba", - "0x47bbe8db4e347b4e8c937c1c8350e4b7ed30adb3db69bbdb7a38c1f40a1b82fd" + "0x3a581d62b12232dade30c3710215a271984841657449d1f474295a13737b778266f57e298f123ae80cbab7cc35ead1b62a387556f94b326d5c65d4a7aa2abcba" ] }, "finish_ts": 4294967290, diff --git a/test/unittests/libethereum/PrecompiledTest.cpp b/test/unittests/libethereum/PrecompiledTest.cpp index 06ecba280..cc1638d26 100644 --- a/test/unittests/libethereum/PrecompiledTest.cpp +++ b/test/unittests/libethereum/PrecompiledTest.cpp @@ -1635,7 +1635,6 @@ static std::string const genesisInfoSkaleConfigTest = std::string() + 13, 30, "0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b", - "0x23bbe8db4e347b4e8c937c1c8350e4b5ed33adb3db69cbdb7a38e1f40a1b82fe" ] }, "finish_ts": null, @@ -1652,7 +1651,6 @@ static std::string const genesisInfoSkaleConfigTest = std::string() + 3, 26, "0x3a581d62b12232dade30c3710215a271984841657449d1f474295a13737b778266f57e298f123ae80cbab7cc35ead1b62a387556f94b326d5c65d4a7aa2abcba", - "0x47bbe8db4e347b4e8c937c1c8350e4b7ed30adb3db69bbdb7a38c1f40a1b82fd" ] }, "finish_ts": 4294967290, @@ -1732,7 +1730,7 @@ BOOST_AUTO_TEST_CASE( getConfigVariable ) { BOOST_REQUIRE( res.first ); BOOST_REQUIRE( dev::fromBigEndian( res.second ) == 13 ); - input = stringToHex( "skaleConfig.sChain.nodes.0.owner" ); + input = stringToHex( "skaleConfig.sChain.nodes.0.publicKey" ); in = fromHex( numberToHex( 32 ) + input ); res = exec( bytesConstRef( in.data(), in.size() ) ); @@ -1745,14 +1743,14 @@ BOOST_AUTO_TEST_CASE( getConfigVariable ) { BOOST_REQUIRE( !res.first ); - exec = PrecompiledRegistrar::executor( "getConfigVariableAddress" ); + exec = PrecompiledRegistrar::executor( "getConfigVariableString" ); - input = stringToHex( "skaleConfig.sChain.nodes.0.owner" ); + input = stringToHex( "skaleConfig.sChain.nodes.0.publicKey" ); in = fromHex( numberToHex( 32 ) + input ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( res.first ); - BOOST_REQUIRE( res.second == fromHex("0x23bbe8db4e347b4e8c937c1c8350e4b5ed33adb3db69cbdb7a38e1f40a1b82fe") ); + BOOST_REQUIRE( res.second == fromHex("0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b") ); input = stringToHex( "skaleConfig.sChain.nodes.0.id" ); input = input.substr(0, 58); // remove 0s in the end From a5040906ce34b54105eb2d498ab477890d86e45a Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 22 Nov 2023 13:58:30 +0000 Subject: [PATCH 26/30] #1702 fix tests --- libethereum/Precompiled.cpp | 5 +++-- test/unittests/libethereum/PrecompiledTest.cpp | 10 ++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index 9bc432a45..aecc33209 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -687,7 +687,8 @@ ETH_REGISTER_PRECOMPILED( logTextMessage )( bytesConstRef _in ) { return { false, response }; // 1st false - means bad error occur } -static const std::list< std::string > g_listReadableConfigParts{ "skaleConfig.sChain.nodes." }; +static const std::list< std::string > g_listReadableConfigParts{ "skaleConfig.sChain.nodes.", + "skaleConfig.nodeInfo.wallets.ima.n" }; static bool stat_is_accessible_json_path( const std::string& strPath ) { if ( strPath.empty() ) @@ -935,7 +936,7 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableString )( bytesConstRef _in ) { strValue = skutils::tools::trim_copy( joValue.is_string() ? joValue.get< std::string >() : joValue.dump() ); } - bytes response = dev::asBytes( strValue ); + bytes response = dev::fromHex( strValue ); return { true, response }; } catch ( std::exception& ex ) { std::string strError = ex.what(); diff --git a/test/unittests/libethereum/PrecompiledTest.cpp b/test/unittests/libethereum/PrecompiledTest.cpp index cc1638d26..2ccea50d1 100644 --- a/test/unittests/libethereum/PrecompiledTest.cpp +++ b/test/unittests/libethereum/PrecompiledTest.cpp @@ -1634,7 +1634,7 @@ static std::string const genesisInfoSkaleConfigTest = std::string() + "30": [ 13, 30, - "0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b", + "0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b" ] }, "finish_ts": null, @@ -1650,7 +1650,7 @@ static std::string const genesisInfoSkaleConfigTest = std::string() + "26": [ 3, 26, - "0x3a581d62b12232dade30c3710215a271984841657449d1f474295a13737b778266f57e298f123ae80cbab7cc35ead1b62a387556f94b326d5c65d4a7aa2abcba", + "0x3a581d62b12232dade30c3710215a271984841657449d1f474295a13737b778266f57e298f123ae80cbab7cc35ead1b62a387556f94b326d5c65d4a7aa2abcba" ] }, "finish_ts": 4294967290, @@ -1731,7 +1731,8 @@ BOOST_AUTO_TEST_CASE( getConfigVariable ) { BOOST_REQUIRE( dev::fromBigEndian( res.second ) == 13 ); input = stringToHex( "skaleConfig.sChain.nodes.0.publicKey" ); - in = fromHex( numberToHex( 32 ) + input ); + input = input.substr(0, 72); // remove 0s in the end + in = fromHex( numberToHex( 36 ) + input ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( !res.first ); @@ -1746,7 +1747,8 @@ BOOST_AUTO_TEST_CASE( getConfigVariable ) { exec = PrecompiledRegistrar::executor( "getConfigVariableString" ); input = stringToHex( "skaleConfig.sChain.nodes.0.publicKey" ); - in = fromHex( numberToHex( 32 ) + input ); + input = input.substr(0, 72); // remove 0s in the end + in = fromHex( numberToHex( 36 ) + input ); res = exec( bytesConstRef( in.data(), in.size() ) ); BOOST_REQUIRE( res.first ); From 1a673802d1ed58567e2df27b294cf479036e13a2 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 22 Nov 2023 16:27:43 +0000 Subject: [PATCH 27/30] #1702 add more tests --- .../libethereum/PrecompiledConfig.json | 7 +++++- .../unittests/libethereum/PrecompiledTest.cpp | 22 ++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/test/unittests/libethereum/PrecompiledConfig.json b/test/unittests/libethereum/PrecompiledConfig.json index 356aeced1..b7b4901f0 100644 --- a/test/unittests/libethereum/PrecompiledConfig.json +++ b/test/unittests/libethereum/PrecompiledConfig.json @@ -38,7 +38,12 @@ "basePort": 1234, "logLevel": "trace", "logLevelProposal": "trace", - "ecdsaKeyName": "NEK:fa112" + "ecdsaKeyName": "NEK:fa112", + "wallets": { + "ima": { + "n": 1 + } + } }, "sChain": { "schainName": "TestChain", diff --git a/test/unittests/libethereum/PrecompiledTest.cpp b/test/unittests/libethereum/PrecompiledTest.cpp index 2ccea50d1..20498f3d9 100644 --- a/test/unittests/libethereum/PrecompiledTest.cpp +++ b/test/unittests/libethereum/PrecompiledTest.cpp @@ -1620,7 +1620,12 @@ static std::string const genesisInfoSkaleConfigTest = std::string() + "basePort": 1234, "logLevel": "trace", "logLevelProposal": "trace", - "ecdsaKeyName": "NEK:fa112" + "ecdsaKeyName": "NEK:fa112", + "wallets": { + "ima": { + "n": 1 + } + } }, "sChain": { "schainName": "TestChain", @@ -1744,6 +1749,21 @@ BOOST_AUTO_TEST_CASE( getConfigVariable ) { BOOST_REQUIRE( !res.first ); + input = stringToHex( "skaleConfig.nodeInfo.wallets.ima.n" ); + input = input.substr(0, 68); // remove 0s in the end + in = fromHex( numberToHex( 34 ) + input ); + res = exec( bytesConstRef( in.data(), in.size() ) ); + + BOOST_REQUIRE( res.first ); + BOOST_REQUIRE( dev::fromBigEndian( res.second ) == 1 ); + + input = stringToHex( "skaleConfig.nodeInfo.wallets.ima.t" ); + input = input.substr(0, 68); // remove 0s in the end + in = fromHex( numberToHex( 34 ) + input ); + res = exec( bytesConstRef( in.data(), in.size() ) ); + + BOOST_REQUIRE( !res.first ); + exec = PrecompiledRegistrar::executor( "getConfigVariableString" ); input = stringToHex( "skaleConfig.sChain.nodes.0.publicKey" ); From 7700738e8c331c1d077d6ba63657cf4504a55438 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 22 Nov 2023 16:50:56 +0000 Subject: [PATCH 28/30] #1702 change [] to at() --- libethereum/Client.cpp | 2 +- libethereum/Client.h | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 0822ba107..00c90351c 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -1327,7 +1327,7 @@ void Client::initHistoricGroupIndex() { void Client::updateHistoricGroupIndex() { uint64_t blockTimestamp = blockInfo( hashFromNumber( number() ) ).timestamp(); - uint64_t currentFinishTs = chainParams().sChain.nodeGroups[historicGroupIndex].finishTs; + uint64_t currentFinishTs = chainParams().sChain.nodeGroups.at( historicGroupIndex ).finishTs; if ( blockTimestamp >= currentFinishTs ) ++historicGroupIndex; if ( historicGroupIndex >= chainParams().sChain.nodeGroups.size() ) { diff --git a/libethereum/Client.h b/libethereum/Client.h index 6ad196a0d..4a1b3fb8d 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -297,22 +297,25 @@ class Client : public ClientBase, protected Worker { } std::array< std::string, 4 > getIMABLSPublicKey() const { - return chainParams().sChain.nodeGroups[historicGroupIndex].blsPublicKey; + return chainParams().sChain.nodeGroups.at( historicGroupIndex ).blsPublicKey; } // get node id for historic node in chain std::string getHistoricNodeId( unsigned _id ) const { - return chainParams().sChain.nodeGroups[historicGroupIndex].nodes[_id].id.str(); + return chainParams().sChain.nodeGroups.at( historicGroupIndex ).nodes[_id].id.str(); } // get schain index for historic node in chain std::string getHistoricNodeIndex( unsigned _idx ) const { - return chainParams().sChain.nodeGroups[historicGroupIndex].nodes[_idx].schainIndex.str(); + return chainParams() + .sChain.nodeGroups.at( historicGroupIndex ) + .nodes[_idx] + .schainIndex.str(); } // get node owner for historic node in chain std::string getHistoricNodePublicKey( unsigned _idx ) const { - return chainParams().sChain.nodeGroups[historicGroupIndex].nodes[_idx].publicKey; + return chainParams().sChain.nodeGroups.at( historicGroupIndex ).nodes[_idx].publicKey; } void doStateDbCompaction() const { m_state.getOriginalDb()->doCompaction(); } From c8921f68be1ccedd2b44f54d6619ab6d201f0277 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 22 Nov 2023 17:56:11 +0000 Subject: [PATCH 29/30] #1702 change [] to at() --- libethereum/Client.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libethereum/Client.h b/libethereum/Client.h index 4a1b3fb8d..415e4d126 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -302,7 +302,7 @@ class Client : public ClientBase, protected Worker { // get node id for historic node in chain std::string getHistoricNodeId( unsigned _id ) const { - return chainParams().sChain.nodeGroups.at( historicGroupIndex ).nodes[_id].id.str(); + return chainParams().sChain.nodeGroups.at( historicGroupIndex ).nodes.at( _id ).id.str(); } // get schain index for historic node in chain @@ -315,7 +315,7 @@ class Client : public ClientBase, protected Worker { // get node owner for historic node in chain std::string getHistoricNodePublicKey( unsigned _idx ) const { - return chainParams().sChain.nodeGroups.at( historicGroupIndex ).nodes[_idx].publicKey; + return chainParams().sChain.nodeGroups.at( historicGroupIndex ).nodes.at( _idx ).publicKey; } void doStateDbCompaction() const { m_state.getOriginalDb()->doCompaction(); } From 23a54370afb437f9fdd19fc084acb5de26fc587d Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 22 Nov 2023 17:56:45 +0000 Subject: [PATCH 30/30] #1702 change [] to at() --- libethereum/Client.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/Client.h b/libethereum/Client.h index 415e4d126..3bf2015c4 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -309,7 +309,7 @@ class Client : public ClientBase, protected Worker { std::string getHistoricNodeIndex( unsigned _idx ) const { return chainParams() .sChain.nodeGroups.at( historicGroupIndex ) - .nodes[_idx] + .nodes.at( _idx ) .schainIndex.str(); }