diff --git a/libethcore/ChainOperationParams.h b/libethcore/ChainOperationParams.h index db6e52683..3e442229d 100644 --- a/libethcore/ChainOperationParams.h +++ b/libethcore/ChainOperationParams.h @@ -175,6 +175,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 8ed23de33..fec3da5a5 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; @@ -288,9 +293,12 @@ 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(); + u256 sChainIndex = groupNodeConfObj.at( 0 ).get_uint64(); + u256 id = groupNodeConfObj.at( 1 ).get_uint64(); + std::string publicKey = groupNodeConfObj.at( 2 ).get_str(); + if ( publicKey.empty() ) { + BOOST_THROW_EXCEPTION( std::runtime_error( "Empty public key in config" ) ); + } groupNodes.push_back( { id, sChainIndex, publicKey } ); } std::sort( groupNodes.begin(), groupNodes.end(), diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index d20bdc950..00c90351c 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 ); } @@ -313,8 +315,12 @@ void Client::init( WithExisting _forceAction, u256 _networkId ) { if ( m_dbPath.size() ) Defaults::setDBPath( m_dbPath ); - if ( ChainParams().sChain.nodeGroups.size() > 0 ) - initIMABLSPublicKey(); + 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() ) { @@ -621,7 +627,7 @@ size_t Client::importTransactionsAsBlock( } if ( chainParams().sChain.nodeGroups.size() > 0 ) - updateIMABLSPublicKey(); + updateHistoricGroupIndex(); m_snapshotAgent->doSnapshotIfNeeded( number(), _timestamp ); @@ -661,6 +667,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() ); @@ -1288,9 +1295,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; } @@ -1302,7 +1309,11 @@ void Client::initIMABLSPublicKey() { 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 ); @@ -1311,15 +1322,18 @@ 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.at( historicGroupIndex ).finishTs; if ( blockTimestamp >= currentFinishTs ) - ++imaBLSPublicKeyGroupIndex; - assert( imaBLSPublicKeyGroupIndex < chainParams().sChain.nodeGroups.size() ); + ++historicGroupIndex; + if ( historicGroupIndex >= chainParams().sChain.nodeGroups.size() ) { + BOOST_THROW_EXCEPTION( std::runtime_error( + "Assertion failed: historicGroupIndex >= chainParams().sChain.nodeGroups.size())" ) ); + } } // new block watch diff --git a/libethereum/Client.h b/libethereum/Client.h index 2e3155612..3bf2015c4 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -297,7 +297,25 @@ class Client : public ClientBase, protected Worker { } std::array< std::string, 4 > getIMABLSPublicKey() const { - return chainParams().sChain.nodeGroups[imaBLSPublicKeyGroupIndex].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.at( historicGroupIndex ).nodes.at( _id ).id.str(); + } + + // get schain index for historic node in chain + std::string getHistoricNodeIndex( unsigned _idx ) const { + return chainParams() + .sChain.nodeGroups.at( historicGroupIndex ) + .nodes.at( _idx ) + .schainIndex.str(); + } + + // get node owner for historic node in chain + std::string getHistoricNodePublicKey( unsigned _idx ) const { + return chainParams().sChain.nodeGroups.at( historicGroupIndex ).nodes.at( _idx ).publicKey; } void doStateDbCompaction() const { m_state.getOriginalDb()->doCompaction(); } @@ -532,10 +550,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..aecc33209 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -36,8 +37,11 @@ #include #include #include +#include #include #include +#include +#include #include @@ -247,10 +251,20 @@ 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 ) ); + 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()" ); + } vector_ref< const unsigned char > byteFilename = - _in.cropped( _startPosition + 32, _stringLength ); + _in.cropped( _startPosition + UINT256_SIZE, _stringLength ); _out = std::string( ( char* ) byteFilename.data(), _stringLength ); } @@ -673,25 +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{ "sealEngine", - //"genesis.*" - //"params.*", - - "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.", + "skaleConfig.nodeInfo.wallets.ima.n" }; static bool stat_is_accessible_json_path( const std::string& strPath ) { if ( strPath.empty() ) @@ -700,7 +697,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; @@ -756,6 +753,47 @@ static dev::u256 stat_parse_u256_hex_or_dec( const std::string& strValue ) { return uValue; } +static bool isCallToHistoricData( const std::string& callData ) { + // in C++ 20 there is string::starts_with, but we do not use C++ 20 yet + return boost::algorithm::starts_with( callData, "skaleConfig.sChain.nodes." ); +} + +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.at( 3 ) ); + std::string fieldName; + std::set< std::string > allowedValues{ "id", "schainIndex", "publicKey" }; + fieldName = splitted.at( 4 ); + if ( allowedValues.count( fieldName ) ) { + return { fieldName, id }; + } else { + BOOST_THROW_EXCEPTION( std::runtime_error( "Unknown field:" + fieldName ) ); + } + 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 + * + * 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 + toBytes(input) ) + */ ETH_REGISTER_PRECOMPILED( getConfigVariableUint256 )( bytesConstRef _in ) { try { size_t lengthName; @@ -767,18 +805,33 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableUint256 )( 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() ); - // 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"; + 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 ) && PrecompiledConfigPatch::isEnabled() ) { + if ( !g_skaleHost ) + throw std::runtime_error( "SkaleHost accessor was not initialized" ); + + std::string field; + unsigned id; + std::tie( field, id ) = parseHistoricFieldRequest( 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 = jsToInt( strValue ); bytes response = toBigEndian( uValue ); return { true, response }; } catch ( std::exception& ex ) { @@ -807,13 +860,14 @@ 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() ); - dev::u256 uValue( strValue.c_str() ); + dev::u256 uValue( strValue ); bytes response = toBigEndian( uValue ); return { true, response }; } catch ( std::exception& ex ) { @@ -831,6 +885,24 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableAddress )( 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 + * 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. 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 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( getConfigVariableString )( bytesConstRef _in ) { try { size_t lengthName; @@ -842,11 +914,29 @@ ETH_REGISTER_PRECOMPILED( getConfigVariableString )( 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 = joValue.is_string() ? joValue.get< std::string >() : joValue.dump(); - bytes response = stat_string_to_bytes_with_length( strValue ); + 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 ) && PrecompiledConfigPatch::isEnabled() ) { + if ( !g_skaleHost ) + throw std::runtime_error( "SkaleHost accessor was not initialized" ); + + std::string field; + unsigned id; + std::tie( field, id ) = parseHistoricFieldRequest( rawName ); + if ( field == "publicKey" ) { + strValue = g_skaleHost->getHistoricNodePublicKey( 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() ); + } + bytes response = dev::fromHex( strValue ); return { true, response }; } catch ( std::exception& ex ) { std::string strError = ex.what(); diff --git a/libethereum/SkaleHost.cpp b/libethereum/SkaleHost.cpp index 1f15035fe..0cbb4241f 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::getHistoricNodePublicKey( unsigned _idx ) const { + return m_client.getHistoricNodePublicKey( _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..82a4c6357 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 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/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/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 diff --git a/test/unittests/libethereum/ClientTest.cpp b/test/unittests/libethereum/ClientTest.cpp index c49302cad..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( @@ -865,6 +865,7 @@ static std::string const c_genesisInfoSkaleIMABLSPublicKeyTest = std::string() + "schainName": "TestChain", "schainID": 1, "emptyBlockIntervalMs": -1, + "precompiledConfigPatchTimestamp": 1, "nodeGroups": { "1": { "nodes": { @@ -917,15 +918,16 @@ 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() ); std::array< std::string, 4 > imaBLSPublicKeyOnStartUp = { "12457351342169393659284905310882617316356538373005664536506840512800919345414", "11573096151310346982175966190385407867176668720531590318594794283907348596326", "13929944172721019694880576097738949215943314024940461401664534665129747139387", "7375214420811287025501422512322868338311819657776589198925786170409964211914" }; - BOOST_REQUIRE( testClient->getIMABLSPublicKey() == imaBLSPublicKeyOnStartUp ); - + BOOST_REQUIRE( testClient->getHistoricNodePublicKey( 0 ) == "0x3a581d62b12232dade30c3710215a271984841657449d1f474295a13737b778266f57e298f123ae80cbab7cc35ead1b62a387556f94b326d5c65d4a7aa2abcba" ); + BOOST_REQUIRE( testClient->getHistoricNodeId( 0 ) == "26" ); + BOOST_REQUIRE( testClient->getHistoricNodeIndex( 0 ) == "3" ); BOOST_REQUIRE( testClient->mineBlocks( 1 ) ); @@ -934,6 +936,9 @@ BOOST_AUTO_TEST_CASE( initAndUpdateIMABLSPUblicKey ) { std::array< std::string, 4 > imaBLSPublicKeyAfterBlock = { "10860211539819517237363395256510340030868592687836950245163587507107792195621", "2419969454136313127863904023626922181546178935031521540751337209075607503568", "3399776985251727272800732947224655319335094876742988846345707000254666193993", "16982202412630419037827505223148517434545454619191931299977913428346639096984" }; BOOST_REQUIRE( testClient->getIMABLSPublicKey() == imaBLSPublicKeyAfterBlock ); + BOOST_REQUIRE( testClient->getHistoricNodePublicKey( 0 ) == "0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b" ); + BOOST_REQUIRE( testClient->getHistoricNodeId( 0 ) == "30" ); + BOOST_REQUIRE( testClient->getHistoricNodeIndex( 0 ) == "0" ); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/unittests/libethereum/PrecompiledConfig.json b/test/unittests/libethereum/PrecompiledConfig.json new file mode 100644 index 000000000..b7b4901f0 --- /dev/null +++ b/test/unittests/libethereum/PrecompiledConfig.json @@ -0,0 +1,109 @@ +{ + "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", + "wallets": { + "ima": { + "n": 1 + } + } + }, + "sChain": { + "schainName": "TestChain", + "schainID": 1, + "contractStorageLimit": 32000, + "precompiledConfigPatchTimestamp": 1, + "emptyBlockIntervalMs": -1, + "nodeGroups": { + "1": { + "nodes": { + "30": [ + 0, + 30, + "0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b" + ] + }, + "finish_ts": null, + "bls_public_key": { + "blsPublicKey0": "10860211539819517237363395256510340030868592687836950245163587507107792195621", + "blsPublicKey1": "2419969454136313127863904023626922181546178935031521540751337209075607503568", + "blsPublicKey2": "3399776985251727272800732947224655319335094876742988846345707000254666193993", + "blsPublicKey3": "16982202412630419037827505223148517434545454619191931299977913428346639096984" + } + }, + "0": { + "nodes": { + "26": [ + 3, + 26, + "0x3a581d62b12232dade30c3710215a271984841657449d1f474295a13737b778266f57e298f123ae80cbab7cc35ead1b62a387556f94b326d5c65d4a7aa2abcba" + ] + }, + "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 861cbb595..20498f3d9 100644 --- a/test/unittests/libethereum/PrecompiledTest.cpp +++ b/test/unittests/libethereum/PrecompiledTest.cpp @@ -21,13 +21,19 @@ */ #include +#include #include #include #include +#include +#include +#include +#include #include #include #include #include +#include #include @@ -37,6 +43,21 @@ 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 ) { + size_t strLength = ( ( inputString.size() * 2 + 63 ) / 64 ) * 64; + std::string hexString = toHex( inputString.begin(), inputString.end(), "" ); + hexString.insert( hexString.begin() + hexString.length(), strLength - hexString.length(), '0' ); + return hexString; +} + BOOST_FIXTURE_TEST_SUITE( PrecompiledTests, TestOutputHelperFixture ) BOOST_AUTO_TEST_CASE( modexpFermatTheorem, @@ -1557,20 +1578,285 @@ 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", + "wallets": { + "ima": { + "n": 1 + } + } + }, + "sChain": { + "schainName": "TestChain", + "schainID": 1, + "contractStorageLimit": 32000, + "precompiledConfigPatchTimestamp": 1, + "emptyBlockIntervalMs": -1, + "nodeGroups": { + "1": { + "nodes": { + "30": [ + 13, + 30, + "0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b" + ] + }, + "finish_ts": null, + "bls_public_key": { + "blsPublicKey0": "10860211539819517237363395256510340030868592687836950245163587507107792195621", + "blsPublicKey1": "2419969454136313127863904023626922181546178935031521540751337209075607503568", + "blsPublicKey2": "3399776985251727272800732947224655319335094876742988846345707000254666193993", + "blsPublicKey3": "16982202412630419037827505223148517434545454619191931299977913428346639096984" + } + }, + "0": { + "nodes": { + "26": [ + 3, + 26, + "0x3a581d62b12232dade30c3710215a271984841657449d1f474295a13737b778266f57e298f123ae80cbab7cc35ead1b62a387556f94b326d5c65d4a7aa2abcba" + ] + }, + "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( getConfigVariable ) { + 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( "getConfigVariableUint256" ); + std::string input = stringToHex( "skaleConfig.sChain.nodes.0.id" ); + input = input.substr(0, 58); // remove 0s in the end + + 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 ); + + 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 ); + + input = stringToHex( "skaleConfig.sChain.nodes.0.publicKey" ); + 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 ); + + 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 ); + + 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" ); + 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 ); + BOOST_REQUIRE( res.second == fromHex("0x6180cde2cbbcc6b6a17efec4503a7d4316f8612f411ee171587089f770335f484003ad236c534b9afa82befc1f69533723abdb6ec2601e582b72dcfd7919338b") ); + + 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 ); } +// 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" );