From f85a75cac5e72fa33a7e8df817daf233e8875aeb Mon Sep 17 00:00:00 2001 From: kladkogex <13399135+kladkogex@users.noreply.github.com> Date: Thu, 21 Sep 2023 19:58:27 +0100 Subject: [PATCH 001/414] 1664 Switching on transaction tracing --- deps/build.sh | 7 +--- libweb3jsonrpc/Debug.cpp | 77 +++++++++++++++++++++++++++------------- libweb3jsonrpc/Debug.h | 6 ++-- 3 files changed, 58 insertions(+), 32 deletions(-) diff --git a/deps/build.sh b/deps/build.sh index f8a184049..16f35d527 100755 --- a/deps/build.sh +++ b/deps/build.sh @@ -932,13 +932,8 @@ then cd "$SOURCES_ROOT" if [ ! -d "libiconv-1.15" ]; then - if [ ! -f "libiconv-1.15.tar.gz" ]; - then - echo -e "${COLOR_INFO}downloading it${COLOR_DOTS}...${COLOR_RESET}" - eval "$WGET" --no-check-certificate https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.15.tar.gz - fi echo -e "${COLOR_INFO}unpacking it${COLOR_DOTS}...${COLOR_RESET}" - eval tar -xzf libiconv-1.15.tar.gz + eval tar -xzf "$PREDOWNLOADED_ROOT/libiconv-1.15.tar.gz" echo -e "${COLOR_INFO}configuring it${COLOR_DOTS}...${COLOR_RESET}" cd libiconv-1.15 eval ./configure "${CONF_CROSSCOMPILING_OPTS_GENERIC}" --enable-static --disable-shared --prefix="$INSTALL_ROOT" "${CONF_DEBUG_OPTIONS}" diff --git a/libweb3jsonrpc/Debug.cpp b/libweb3jsonrpc/Debug.cpp index 0ef884262..acaf00845 100644 --- a/libweb3jsonrpc/Debug.cpp +++ b/libweb3jsonrpc/Debug.cpp @@ -1,3 +1,4 @@ +#define HISTORIC_STATE #include "Debug.h" #include "JsonHelper.h" @@ -11,6 +12,11 @@ #include #include +#ifdef HISTORIC_STATE +#include +#include +#endif + using namespace std; using namespace dev; using namespace dev::rpc; @@ -20,8 +26,8 @@ using namespace skale; Debug::Debug( eth::Client const& _eth, SkaleDebugInterface* _debugInterface, const string& argv ) : m_eth( _eth ), m_debugInterface( _debugInterface ), argv_options( argv ) {} -StandardTrace::DebugOptions dev::eth::debugOptions( Json::Value const& _json ) { - StandardTrace::DebugOptions op; +AlethStandardTrace::DebugOptions dev::eth::debugOptions( Json::Value const& _json ) { + AlethStandardTrace::DebugOptions op; if ( !_json.isObject() || _json.empty() ) return op; if ( !_json["disableStorage"].empty() ) @@ -35,6 +41,7 @@ StandardTrace::DebugOptions dev::eth::debugOptions( Json::Value const& _json ) { return op; } + h256 Debug::blockHash( string const& _blockNumberOrHash ) const { if ( isHash< h256 >( _blockNumberOrHash ) ) return h256( _blockNumberOrHash.substr( _blockNumberOrHash.size() - 64, 64 ) ); @@ -67,20 +74,27 @@ State Debug::stateAt( std::string const& /*_blockHashOrNumber*/, int _txIndex ) // return state; } -Json::Value Debug::traceTransaction( - Executive& _e, Transaction const& _t, Json::Value const& _json ) { - Json::Value trace; - StandardTrace st; + + +Json::Value Debug::traceTransaction(Executive& _e, Transaction const& _t, Json::Value const& _json) +{ + +#ifdef HISTORIC_STATE + Json::Value traceJson{Json::arrayValue}; + AlethStandardTrace st{traceJson}; st.setShowMnemonics(); - st.setOptions( debugOptions( _json ) ); - _e.initialize( _t ); - if ( !_e.execute() ) - _e.go( st.onOp() ); + st.setOptions(debugOptions(_json)); + _e.initialize(_t); + if (!_e.execute()) + _e.go(st.onOp()); _e.finalize(); - Json::Reader().parse( st.json(), trace ); - return trace; + return traceJson; +#else + throw logic_error( "This function is only supported on SKALE archive nodes"); +#endif } + Json::Value Debug::traceBlock( Block const& _block, Json::Value const& _json ) { State s( _block.state() ); // s.setRoot(_block.stateRootBeforeTx(0)); @@ -103,19 +117,34 @@ Json::Value Debug::traceBlock( Block const& _block, Json::Value const& _json ) { return traces; } -Json::Value Debug::debug_traceTransaction( - string const& /*_txHash*/, Json::Value const& /*_json*/ ) { + +Json::Value Debug::debug_traceTransaction(string const& +#ifdef HISTORIC_STATE + _txHash +#endif + , Json::Value const& +#ifdef HISTORIC_STATE + _json +#endif + ) +{ Json::Value ret; - try { - throw std::logic_error( "Historical state is not supported in Skale" ); - // Executive e(s, block, t.transactionIndex(), m_eth.blockChain()); - // e.setResultRecipient(er); - // Json::Value trace = traceTransaction(e, t, _json); - // ret["gas"] = toJS(t.gas()); - // ret["return"] = toHexPrefixed(er.output); - // ret["structLogs"] = trace; - } catch ( Exception const& _e ) { - cwarn << diagnostic_information( _e ); + try + { + LocalisedTransaction t = m_eth.localisedTransaction(h256(_txHash)); + Block block = m_eth.block(t.blockHash()); + HistoricState s(HistoricState::Null); + eth::ExecutionResult er; + AlethExecutive e(s, block, t.transactionIndex(), m_eth.blockChain()); + e.setResultRecipient(er); + Json::Value trace = traceTransaction(e, t, _json); + ret["gas"] = toJS(t.gas()); + ret["return"] = toHexPrefixed(er.output); + ret["structLogs"] = trace; + } + catch(Exception const& _e) + { + cwarn << diagnostic_information(_e); } return ret; } diff --git a/libweb3jsonrpc/Debug.h b/libweb3jsonrpc/Debug.h index f5337001d..c4347f1f2 100644 --- a/libweb3jsonrpc/Debug.h +++ b/libweb3jsonrpc/Debug.h @@ -13,9 +13,11 @@ namespace dev { namespace eth { class Client; -StandardTrace::DebugOptions debugOptions( Json::Value const& _json ); -} // namespace eth +#ifdef HISTORIC_STATE +AlethStandardTrace::DebugOptions debugOptions( Json::Value const& _json ); +#endif +} // namespace eth namespace rpc { class SessionManager; From 7e48759eaa40df4317ee1db3b2a45b75e57df6b1 Mon Sep 17 00:00:00 2001 From: Stan Kladko <13399135+kladkogex@users.noreply.github.com> Date: Fri, 29 Sep 2023 18:06:23 +0100 Subject: [PATCH 002/414] 1664 adding trace --- libweb3jsonrpc/Debug.cpp | 418 ++++++++++++++++++++------------------- libweb3jsonrpc/Debug.h | 8 +- 2 files changed, 218 insertions(+), 208 deletions(-) diff --git a/libweb3jsonrpc/Debug.cpp b/libweb3jsonrpc/Debug.cpp index acaf00845..0cdb883b2 100644 --- a/libweb3jsonrpc/Debug.cpp +++ b/libweb3jsonrpc/Debug.cpp @@ -1,4 +1,7 @@ +#ifndef HISTORIC_STATE #define HISTORIC_STATE +#endif + #include "Debug.h" #include "JsonHelper.h" @@ -23,24 +26,9 @@ using namespace dev::rpc; using namespace dev::eth; using namespace skale; -Debug::Debug( eth::Client const& _eth, SkaleDebugInterface* _debugInterface, const string& argv ) +Debug::Debug( eth::Client & _eth, SkaleDebugInterface* _debugInterface, const string& argv ) : m_eth( _eth ), m_debugInterface( _debugInterface ), argv_options( argv ) {} -AlethStandardTrace::DebugOptions dev::eth::debugOptions( Json::Value const& _json ) { - AlethStandardTrace::DebugOptions op; - if ( !_json.isObject() || _json.empty() ) - return op; - if ( !_json["disableStorage"].empty() ) - op.disableStorage = _json["disableStorage"].asBool(); - if ( !_json["disableMemory"].empty() ) - op.disableMemory = _json["disableMemory"].asBool(); - if ( !_json["disableStack"].empty() ) - op.disableStack = _json["disableStack"].asBool(); - if ( !_json["fullStorage"].empty() ) - op.fullStorage = _json["fullStorage"].asBool(); - return op; -} - h256 Debug::blockHash( string const& _blockNumberOrHash ) const { if ( isHash< h256 >( _blockNumberOrHash ) ) @@ -74,24 +62,34 @@ State Debug::stateAt( std::string const& /*_blockHashOrNumber*/, int _txIndex ) // return state; } +StandardTrace::DebugOptions dev::eth::debugOptions( Json::Value const& _json ) { + StandardTrace::DebugOptions op; + if ( !_json.isObject() || _json.empty() ) + return op; + if ( !_json["disableStorage"].empty() ) + op.disableStorage = _json["disableStorage"].asBool(); + if ( !_json["disableMemory"].empty() ) + op.disableMemory = _json["disableMemory"].asBool(); + if ( !_json["disableStack"].empty() ) + op.disableStack = _json["disableStack"].asBool(); + if ( !_json["fullStorage"].empty() ) + op.fullStorage = _json["fullStorage"].asBool(); + return op; +} -Json::Value Debug::traceTransaction(Executive& _e, Transaction const& _t, Json::Value const& _json) -{ - -#ifdef HISTORIC_STATE - Json::Value traceJson{Json::arrayValue}; - AlethStandardTrace st{traceJson}; +Json::Value Debug::traceTransaction( + Executive& _e, Transaction const& _t, Json::Value const& _json ) { + Json::Value trace; + StandardTrace st; st.setShowMnemonics(); - st.setOptions(debugOptions(_json)); - _e.initialize(_t); - if (!_e.execute()) - _e.go(st.onOp()); + st.setOptions( debugOptions( _json ) ); + _e.initialize( _t ); + if ( !_e.execute() ) + _e.go( st.onOp() ); _e.finalize(); - return traceJson; -#else - throw logic_error( "This function is only supported on SKALE archive nodes"); -#endif + Json::Reader().parse( st.json(), trace ); + return trace; } @@ -118,37 +116,51 @@ Json::Value Debug::traceBlock( Block const& _block, Json::Value const& _json ) { } -Json::Value Debug::debug_traceTransaction(string const& +Json::Value Debug::debug_traceTransaction( string const& #ifdef HISTORIC_STATE - _txHash + _txHash #endif - , Json::Value const& + , + Json::Value const& #ifdef HISTORIC_STATE _json #endif - ) -{ +) { Json::Value ret; - try - { - LocalisedTransaction t = m_eth.localisedTransaction(h256(_txHash)); - Block block = m_eth.block(t.blockHash()); - HistoricState s(HistoricState::Null); - eth::ExecutionResult er; - AlethExecutive e(s, block, t.transactionIndex(), m_eth.blockChain()); - e.setResultRecipient(er); - Json::Value trace = traceTransaction(e, t, _json); - ret["gas"] = toJS(t.gas()); - ret["return"] = toHexPrefixed(er.output); - ret["structLogs"] = trace; + + +#ifndef HISTORIC_STATE + throw jsonrpc::JsonRpcException( + "debug_traceTransaction API is only supported " + "on archive nodes, not or core or sync nodes" ); +#else + LocalisedTransaction t = m_eth.localisedTransaction( h256( _txHash ) ); + + + if ( t.blockHash() == h256( 0 ) ) { + throw jsonrpc::JsonRpcException( "no committed transaction with this hash" ); + } + + auto blockNumber = t.blockNumber(); + + if ( !m_eth.isKnown( blockNumber ) ) { + throw jsonrpc::JsonRpcException( "Unknown block number" ); + ; } - catch(Exception const& _e) - { - cwarn << diagnostic_information(_e); + try { + ExecutionResult er = m_eth.call( t.from(), t.value(), t.to(), t.data(), t.gas(), + t.gasPrice(), blockNumber, FudgeFactor::Lenient ); + ret["gas"] = toJS( t.gas() ); + ret["return"] = toHexPrefixed( er.output ); + ret["structLogs"] = ""; + } catch ( Exception const& _e ) { + cwarn << diagnostic_information( _e ); } return ret; +#endif } + Json::Value Debug::debug_traceBlock( string const& _blockRLP, Json::Value const& _json ) { bytes bytes = fromHex( _blockRLP ); BlockHeader blockHeader( bytes ); @@ -158,188 +170,188 @@ Json::Value Debug::debug_traceBlock( string const& _blockRLP, Json::Value const& // TODO Make function without "block" parameter Json::Value Debug::debug_traceBlockByHash( string const& /*_blockHash*/, Json::Value const& _json ) { - Json::Value ret; - Block block = m_eth.latestBlock(); - ret["structLogs"] = traceBlock( block, _json ); - return ret; -} + Json::Value ret; + Block block = m_eth.latestBlock(); + ret["structLogs"] = traceBlock( block, _json ); + return ret; + } -// TODO Make function without "block" parameter -Json::Value Debug::debug_traceBlockByNumber( int /*_blockNumber*/, Json::Value const& _json ) { - Json::Value ret; - Block block = m_eth.latestBlock(); - ret["structLogs"] = traceBlock( block, _json ); - return ret; -} + // TODO Make function without "block" parameter + Json::Value Debug::debug_traceBlockByNumber( int /*_blockNumber*/, Json::Value const& _json ) { + Json::Value ret; + Block block = m_eth.latestBlock(); + ret["structLogs"] = traceBlock( block, _json ); + return ret; + } -Json::Value Debug::debug_accountRangeAt( string const& _blockHashOrNumber, int _txIndex, - string const& /*_addressHash*/, int _maxResults ) { - Json::Value ret( Json::objectValue ); + Json::Value Debug::debug_accountRangeAt( string const& _blockHashOrNumber, int _txIndex, + string const& /*_addressHash*/, int _maxResults ) { + Json::Value ret( Json::objectValue ); - if ( _maxResults <= 0 ) - throw jsonrpc::JsonRpcException( "Nonpositive maxResults" ); + if ( _maxResults <= 0 ) + throw jsonrpc::JsonRpcException( "Nonpositive maxResults" ); - try { - State const state = stateAt( _blockHashOrNumber, _txIndex ); + try { + State const state = stateAt( _blockHashOrNumber, _txIndex ); - throw std::logic_error( "Addresses list is not suppoted in Skale state" ); - // auto const addressMap = state.addresses(h256(_addressHash), _maxResults); + throw std::logic_error( "Addresses list is not suppoted in Skale state" ); + // auto const addressMap = state.addresses(h256(_addressHash), _maxResults); - // Json::Value addressList(Json::objectValue); - // for (auto const& record : addressMap.first) - // addressList[toString(record.first)] = toString(record.second); + // Json::Value addressList(Json::objectValue); + // for (auto const& record : addressMap.first) + // addressList[toString(record.first)] = toString(record.second); - // ret["addressMap"] = addressList; - // ret["nextKey"] = toString(addressMap.second); - } catch ( Exception const& _e ) { - cwarn << diagnostic_information( _e ); - throw jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ); - } - - return ret; -} + // ret["addressMap"] = addressList; + // ret["nextKey"] = toString(addressMap.second); + } catch ( Exception const& _e ) { + cwarn << diagnostic_information( _e ); + throw jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ); + } -Json::Value Debug::debug_storageRangeAt( string const& _blockHashOrNumber, int _txIndex, - string const& /*_address*/, string const& /*_begin*/, int _maxResults ) { - Json::Value ret( Json::objectValue ); - ret["complete"] = true; - ret["storage"] = Json::Value( Json::objectValue ); + return ret; + } - if ( _maxResults <= 0 ) - throw jsonrpc::JsonRpcException( "Nonpositive maxResults" ); + Json::Value Debug::debug_storageRangeAt( string const& _blockHashOrNumber, int _txIndex, + string const& /*_address*/, string const& /*_begin*/, int _maxResults ) { + Json::Value ret( Json::objectValue ); + ret["complete"] = true; + ret["storage"] = Json::Value( Json::objectValue ); + + if ( _maxResults <= 0 ) + throw jsonrpc::JsonRpcException( "Nonpositive maxResults" ); + + try { + State const state = stateAt( _blockHashOrNumber, _txIndex ); + + throw std::logic_error( "Obtaining of full storage is not suppoted in Skale state" ); + // map> const storage(state.storage(Address(_address))); + + // // begin is inclusive + // auto itBegin = storage.lower_bound(h256fromHex(_begin)); + // for (auto it = itBegin; it != storage.end(); ++it) + // { + // if (ret["storage"].size() == static_cast(_maxResults)) + // { + // ret["nextKey"] = toCompactHexPrefixed(it->first, 1); + // break; + // } + + // Json::Value keyValue(Json::objectValue); + // std::string hashedKey = toCompactHexPrefixed(it->first, 1); + // keyValue["key"] = toCompactHexPrefixed(it->second.first, 1); + // keyValue["value"] = toCompactHexPrefixed(it->second.second, 1); + + // ret["storage"][hashedKey] = keyValue; + // } + } catch ( Exception const& _e ) { + cwarn << diagnostic_information( _e ); + throw jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ); + } - try { - State const state = stateAt( _blockHashOrNumber, _txIndex ); - - throw std::logic_error( "Obtaining of full storage is not suppoted in Skale state" ); - // map> const storage(state.storage(Address(_address))); - - // // begin is inclusive - // auto itBegin = storage.lower_bound(h256fromHex(_begin)); - // for (auto it = itBegin; it != storage.end(); ++it) - // { - // if (ret["storage"].size() == static_cast(_maxResults)) - // { - // ret["nextKey"] = toCompactHexPrefixed(it->first, 1); - // break; - // } - - // Json::Value keyValue(Json::objectValue); - // std::string hashedKey = toCompactHexPrefixed(it->first, 1); - // keyValue["key"] = toCompactHexPrefixed(it->second.first, 1); - // keyValue["value"] = toCompactHexPrefixed(it->second.second, 1); - - // ret["storage"][hashedKey] = keyValue; - // } - } catch ( Exception const& _e ) { - cwarn << diagnostic_information( _e ); - throw jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ); + return ret; } - return ret; -} - -std::string Debug::debug_preimage( std::string const& /*_hashedKey*/ ) { - throw std::logic_error( "Preimages do not exist in Skale state" ); - // h256 const hashedKey(h256fromHex(_hashedKey)); - // bytes const key = m_eth.state().lookupAux(hashedKey); + std::string Debug::debug_preimage( std::string const& /*_hashedKey*/ ) { + throw std::logic_error( "Preimages do not exist in Skale state" ); + // h256 const hashedKey(h256fromHex(_hashedKey)); + // bytes const key = m_eth.state().lookupAux(hashedKey); - // return key.empty() ? std::string() : toHexPrefixed(key); -} + // return key.empty() ? std::string() : toHexPrefixed(key); + } -Json::Value Debug::debug_traceCall( Json::Value const& _call, Json::Value const& _options ) { - Json::Value ret; - try { - Block temp = m_eth.latestBlock(); - TransactionSkeleton ts = toTransactionSkeleton( _call ); - if ( !ts.from ) { - ts.from = Address(); + Json::Value Debug::debug_traceCall( Json::Value const& _call, Json::Value const& _options ) { + Json::Value ret; + try { + Block temp = m_eth.latestBlock(); + TransactionSkeleton ts = toTransactionSkeleton( _call ); + if ( !ts.from ) { + ts.from = Address(); + } + u256 nonce = temp.transactionsFrom( ts.from ); + u256 gas = ts.gas == Invalid256 ? m_eth.gasLimitRemaining() : ts.gas; + u256 gasPrice = ts.gasPrice == Invalid256 ? m_eth.gasBidPrice() : ts.gasPrice; + temp.mutableState().addBalance( ts.from, gas * gasPrice + ts.value ); + Transaction transaction( ts.value, gasPrice, gas, ts.to, ts.data, nonce ); + transaction.forceSender( ts.from ); + eth::ExecutionResult er; + // HACK 0 here is for gasPrice + Executive e( temp, m_eth.blockChain().lastBlockHashes(), 0 ); + e.setResultRecipient( er ); + Json::Value trace = traceTransaction( e, transaction, _options ); + ret["gas"] = toJS( transaction.gas() ); + ret["return"] = toHexPrefixed( er.output ); + ret["structLogs"] = trace; + } catch ( Exception const& _e ) { + cwarn << diagnostic_information( _e ); } - u256 nonce = temp.transactionsFrom( ts.from ); - u256 gas = ts.gas == Invalid256 ? m_eth.gasLimitRemaining() : ts.gas; - u256 gasPrice = ts.gasPrice == Invalid256 ? m_eth.gasBidPrice() : ts.gasPrice; - temp.mutableState().addBalance( ts.from, gas * gasPrice + ts.value ); - Transaction transaction( ts.value, gasPrice, gas, ts.to, ts.data, nonce ); - transaction.forceSender( ts.from ); - eth::ExecutionResult er; - // HACK 0 here is for gasPrice - Executive e( temp, m_eth.blockChain().lastBlockHashes(), 0 ); - e.setResultRecipient( er ); - Json::Value trace = traceTransaction( e, transaction, _options ); - ret["gas"] = toJS( transaction.gas() ); - ret["return"] = toHexPrefixed( er.output ); - ret["structLogs"] = trace; - } catch ( Exception const& _e ) { - cwarn << diagnostic_information( _e ); + return ret; } - return ret; -} -void Debug::debug_pauseBroadcast( bool _pause ) { - m_eth.skaleHost()->pauseBroadcast( _pause ); -} -void Debug::debug_pauseConsensus( bool _pause ) { - m_eth.skaleHost()->pauseConsensus( _pause ); -} -void Debug::debug_forceBlock() { - m_eth.skaleHost()->forceEmptyBlock(); -} + void Debug::debug_pauseBroadcast( bool _pause ) { + m_eth.skaleHost()->pauseBroadcast( _pause ); + } + void Debug::debug_pauseConsensus( bool _pause ) { + m_eth.skaleHost()->pauseConsensus( _pause ); + } + void Debug::debug_forceBlock() { + m_eth.skaleHost()->forceEmptyBlock(); + } -void Debug::debug_forceBroadcast( const std::string& _transactionHash ) { - try { - h256 h = jsToFixed< 32 >( _transactionHash ); - if ( !m_eth.isKnownTransaction( h ) ) + void Debug::debug_forceBroadcast( const std::string& _transactionHash ) { + try { + h256 h = jsToFixed< 32 >( _transactionHash ); + if ( !m_eth.isKnownTransaction( h ) ) + BOOST_THROW_EXCEPTION( + jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ) ); + + const Transaction tx = m_eth.transaction( h ); + m_eth.skaleHost()->forcedBroadcast( tx ); + } catch ( ... ) { BOOST_THROW_EXCEPTION( jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ) ); - - const Transaction tx = m_eth.transaction( h ); - m_eth.skaleHost()->forcedBroadcast( tx ); - } catch ( ... ) { - BOOST_THROW_EXCEPTION( - jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ) ); + } } -} -std::string Debug::debug_interfaceCall( const std::string& _arg ) { - return m_debugInterface->call( _arg ); -} + std::string Debug::debug_interfaceCall( const std::string& _arg ) { + return m_debugInterface->call( _arg ); + } -std::string Debug::debug_getVersion() { - return Version; -} + std::string Debug::debug_getVersion() { + return Version; + } -std::string Debug::debug_getArguments() { - return argv_options; -} + std::string Debug::debug_getArguments() { + return argv_options; + } -std::string Debug::debug_getConfig() { - return m_eth.chainParams().getOriginalJson(); -} + std::string Debug::debug_getConfig() { + return m_eth.chainParams().getOriginalJson(); + } -std::string Debug::debug_getSchainName() { - return m_eth.chainParams().sChain.name; -} + std::string Debug::debug_getSchainName() { + return m_eth.chainParams().sChain.name; + } -uint64_t Debug::debug_getSnapshotCalculationTime() { - return m_eth.getSnapshotCalculationTime(); -} + uint64_t Debug::debug_getSnapshotCalculationTime() { + return m_eth.getSnapshotCalculationTime(); + } -uint64_t Debug::debug_getSnapshotHashCalculationTime() { - return m_eth.getSnapshotHashCalculationTime(); -} + uint64_t Debug::debug_getSnapshotHashCalculationTime() { + return m_eth.getSnapshotHashCalculationTime(); + } -uint64_t Debug::debug_doStateDbCompaction() { - auto t1 = boost::chrono::high_resolution_clock::now(); - m_eth.doStateDbCompaction(); - auto t2 = boost::chrono::high_resolution_clock::now(); + uint64_t Debug::debug_doStateDbCompaction() { + auto t1 = boost::chrono::high_resolution_clock::now(); + m_eth.doStateDbCompaction(); + auto t2 = boost::chrono::high_resolution_clock::now(); - return boost::chrono::duration_cast< boost::chrono::milliseconds >( t2 - t1 ).count(); -} + return boost::chrono::duration_cast< boost::chrono::milliseconds >( t2 - t1 ).count(); + } -uint64_t Debug::debug_doBlocksDbCompaction() { - auto t1 = boost::chrono::high_resolution_clock::now(); - m_eth.doBlocksDbCompaction(); - auto t2 = boost::chrono::high_resolution_clock::now(); + uint64_t Debug::debug_doBlocksDbCompaction() { + auto t1 = boost::chrono::high_resolution_clock::now(); + m_eth.doBlocksDbCompaction(); + auto t2 = boost::chrono::high_resolution_clock::now(); - return boost::chrono::duration_cast< boost::chrono::milliseconds >( t2 - t1 ).count(); -} + return boost::chrono::duration_cast< boost::chrono::milliseconds >( t2 - t1 ).count(); + } diff --git a/libweb3jsonrpc/Debug.h b/libweb3jsonrpc/Debug.h index c4347f1f2..ef589a562 100644 --- a/libweb3jsonrpc/Debug.h +++ b/libweb3jsonrpc/Debug.h @@ -13,9 +13,7 @@ namespace dev { namespace eth { class Client; -#ifdef HISTORIC_STATE -AlethStandardTrace::DebugOptions debugOptions( Json::Value const& _json ); -#endif +StandardTrace::DebugOptions debugOptions( Json::Value const& _json ); } // namespace eth namespace rpc { @@ -23,7 +21,7 @@ class SessionManager; class Debug : public DebugFace { public: - explicit Debug( eth::Client const& _eth, SkaleDebugInterface* _debugInterface = nullptr, + explicit Debug( eth::Client& _eth, SkaleDebugInterface* _debugInterface = nullptr, const std::string& argv = std::string() ); virtual RPCModules implementedModules() const override { @@ -63,7 +61,7 @@ class Debug : public DebugFace { virtual uint64_t debug_doBlocksDbCompaction() override; private: - eth::Client const& m_eth; + eth::Client& m_eth; SkaleDebugInterface* m_debugInterface = nullptr; std::string argv_options; From ce72ec82344b937aa90e8848d928bb053ec90286 Mon Sep 17 00:00:00 2001 From: Stan Kladko <13399135+kladkogex@users.noreply.github.com> Date: Fri, 29 Sep 2023 18:39:27 +0100 Subject: [PATCH 003/414] 1664 fixing function signatures --- libethereum/Client.cpp | 1 + libethereum/Client.h | 6 +++++- libethereum/Interface.h | 2 ++ libskale/httpserveroverride.cpp | 1 + libweb3jsonrpc/Debug.cpp | 2 +- libweb3jsonrpc/Eth.cpp | 1 + test/tools/libtestutils/FixedClient.h | 2 ++ 7 files changed, 13 insertions(+), 2 deletions(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index dcd422880..be04c4283 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -1224,6 +1224,7 @@ ExecutionResult Client::call( Address const& _from, u256 _value, Address _dest, u256 _gas, u256 _gasPrice, #ifdef HISTORIC_STATE BlockNumber _blockNumber, + bool _generateExecutionTrace, #endif FudgeFactor _ff ) { ExecutionResult ret; diff --git a/libethereum/Client.h b/libethereum/Client.h index 2e3155612..1d925aed8 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -4,7 +4,7 @@ This file is part of cpp-ethereum. cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by + it unde #include @@ -118,6 +121,7 @@ class Client : public ClientBase, protected Worker { u256 _gas, u256 _gasPrice, #ifdef HISTORIC_STATE BlockNumber _blockNumber, + bool _generateExecutionTrace, #endif FudgeFactor _ff = FudgeFactor::Strict ) override; diff --git a/libethereum/Interface.h b/libethereum/Interface.h index a6c1c874f..4a1974b1c 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -90,6 +90,7 @@ class Interface { bytes const& _data, u256 _gas, u256 _gasPrice, #ifdef HISTORIC_STATE BlockNumber _blockNumber, + bool _generateExecutionTrace, #endif FudgeFactor _ff = FudgeFactor::Strict ) = 0; ExecutionResult call( Secret const& _secret, u256 _value, Address _dest, bytes const& _data, @@ -101,6 +102,7 @@ class Interface { return call( toAddress( _secret ), _value, _dest, _data, _gas, _gasPrice, #ifdef HISTORIC_STATE _blockNumber, + false, #endif _ff ); } diff --git a/libskale/httpserveroverride.cpp b/libskale/httpserveroverride.cpp index 70175a404..f954e2451 100644 --- a/libskale/httpserveroverride.cpp +++ b/libskale/httpserveroverride.cpp @@ -3610,6 +3610,7 @@ void SkaleServerOverride::informational_eth_getBalance( pClient->call( t.from, t.value, t.to, t.data, t.gas, t.gasPrice, #ifdef HISTORIC_STATE bNumber, + false, #endif dev::eth::FudgeFactor::Lenient ); diff --git a/libweb3jsonrpc/Debug.cpp b/libweb3jsonrpc/Debug.cpp index 0cdb883b2..02ea1e0f7 100644 --- a/libweb3jsonrpc/Debug.cpp +++ b/libweb3jsonrpc/Debug.cpp @@ -149,7 +149,7 @@ Json::Value Debug::debug_traceTransaction( string const& } try { ExecutionResult er = m_eth.call( t.from(), t.value(), t.to(), t.data(), t.gas(), - t.gasPrice(), blockNumber, FudgeFactor::Lenient ); + t.gasPrice(), blockNumber, true, FudgeFactor::Lenient ); ret["gas"] = toJS( t.gas() ); ret["return"] = toHexPrefixed( er.output ); ret["structLogs"] = ""; diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index 42f89a002..85864576c 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -415,6 +415,7 @@ string Eth::eth_call( TransactionSkeleton& t, string const& ExecutionResult er = client()->call( t.from, t.value, t.to, t.data, t.gas, t.gasPrice, #ifdef HISTORIC_STATE bN, + false, #endif FudgeFactor::Lenient ); diff --git a/test/tools/libtestutils/FixedClient.h b/test/tools/libtestutils/FixedClient.h index d4b00016a..1346570eb 100644 --- a/test/tools/libtestutils/FixedClient.h +++ b/test/tools/libtestutils/FixedClient.h @@ -74,6 +74,8 @@ class FixedClient : public dev::eth::ClientBase { Address const&, u256, Address, bytes const&, u256, u256, #ifdef HISTORIC_STATE BlockNumber, + bool, + #endif eth::FudgeFactor ) override { return {}; From cb06e645a0dd2d79cb56a7e1b88277a60b6c3e3c Mon Sep 17 00:00:00 2001 From: Stan Kladko <13399135+kladkogex@users.noreply.github.com> Date: Fri, 29 Sep 2023 19:29:53 +0100 Subject: [PATCH 004/414] Fixing function signatures --- libethereum/Block.cpp | 7 ++++++- libethereum/Block.h | 6 +++++- libethereum/Client.cpp | 19 ++++++++++++------- libethereum/Client.h | 2 +- libethereum/Interface.h | 5 +++-- libskale/httpserveroverride.cpp | 2 +- libweb3jsonrpc/Debug.cpp | 2 +- libweb3jsonrpc/Eth.cpp | 2 +- test/tools/libtestutils/FixedClient.h | 8 +++++++- 9 files changed, 37 insertions(+), 16 deletions(-) diff --git a/libethereum/Block.cpp b/libethereum/Block.cpp index 559cceee3..8d5eb76b4 100644 --- a/libethereum/Block.cpp +++ b/libethereum/Block.cpp @@ -786,11 +786,16 @@ u256 Block::enact( VerifiedBlockRef const& _block, BlockChain const& _bc ) { #ifdef HISTORIC_STATE ExecutionResult Block::executeHistoricCall( - LastBlockHashesFace const& _lh, Transaction const& _t ) { + LastBlockHashesFace const& _lh, Transaction const& _t, std::shared_ptr _tracer ) { auto p = Permanence::Reverted; auto onOp = OnOpFunc(); + if (_tracer) { + onOp = _tracer->onOp(); + } + + if ( isSealed() ) BOOST_THROW_EXCEPTION( InvalidOperationOnSealedBlock() ); diff --git a/libethereum/Block.h b/libethereum/Block.h index 3dff5b034..ee615e87a 100644 --- a/libethereum/Block.h +++ b/libethereum/Block.h @@ -214,9 +214,13 @@ class Block { ExecutionResult execute( LastBlockHashesFace const& _lh, Transaction const& _t, skale::Permanence _p = skale::Permanence::Committed, OnOpFunc const& _onOp = OnOpFunc() ); +#ifndef HISTORIC_STATE +#define HISTORIC_STATE +#endif #ifdef HISTORIC_STATE - ExecutionResult executeHistoricCall( LastBlockHashesFace const& _lh, Transaction const& _t ); + ExecutionResult executeHistoricCall( + LastBlockHashesFace const& _lh, Transaction const& _t, std::shared_ptr _tracer ); #endif diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index be04c4283..34fe1ef10 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -1080,7 +1080,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 ) { @@ -1094,7 +1096,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 ) { @@ -1223,8 +1227,7 @@ h256 Client::importTransaction( Transaction const& _t ) { ExecutionResult Client::call( Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, #ifdef HISTORIC_STATE - BlockNumber _blockNumber, - bool _generateExecutionTrace, + BlockNumber _blockNumber, std::shared_ptr _tracer, #endif FudgeFactor _ff ) { ExecutionResult ret; @@ -1243,10 +1246,11 @@ 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 ); + ret = historicBlock.executeHistoricCall( + bc().lastBlockHashes(), t, _tracer ); } catch ( ... ) { cwarn << boost::current_exception_diagnostic_information(); throw; @@ -1267,7 +1271,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):" diff --git a/libethereum/Client.h b/libethereum/Client.h index 1d925aed8..b47bad062 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -121,7 +121,7 @@ class Client : public ClientBase, protected Worker { u256 _gas, u256 _gasPrice, #ifdef HISTORIC_STATE BlockNumber _blockNumber, - bool _generateExecutionTrace, + std::shared_ptr _tracer, #endif FudgeFactor _ff = FudgeFactor::Strict ) override; diff --git a/libethereum/Interface.h b/libethereum/Interface.h index 4a1974b1c..253367063 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -38,6 +38,7 @@ namespace dev { namespace eth { struct SyncStatus; +class StandardTrace; using TransactionHashes = h256s; using UncleHashes = h256s; @@ -90,7 +91,7 @@ class Interface { bytes const& _data, u256 _gas, u256 _gasPrice, #ifdef HISTORIC_STATE BlockNumber _blockNumber, - bool _generateExecutionTrace, + std::shared_ptr _tracer, #endif FudgeFactor _ff = FudgeFactor::Strict ) = 0; ExecutionResult call( Secret const& _secret, u256 _value, Address _dest, bytes const& _data, @@ -102,7 +103,7 @@ class Interface { return call( toAddress( _secret ), _value, _dest, _data, _gas, _gasPrice, #ifdef HISTORIC_STATE _blockNumber, - false, + nullptr, #endif _ff ); } diff --git a/libskale/httpserveroverride.cpp b/libskale/httpserveroverride.cpp index f954e2451..e1f417787 100644 --- a/libskale/httpserveroverride.cpp +++ b/libskale/httpserveroverride.cpp @@ -3610,7 +3610,7 @@ void SkaleServerOverride::informational_eth_getBalance( pClient->call( t.from, t.value, t.to, t.data, t.gas, t.gasPrice, #ifdef HISTORIC_STATE bNumber, - false, + nullptr, #endif dev::eth::FudgeFactor::Lenient ); diff --git a/libweb3jsonrpc/Debug.cpp b/libweb3jsonrpc/Debug.cpp index 02ea1e0f7..b80bc8a01 100644 --- a/libweb3jsonrpc/Debug.cpp +++ b/libweb3jsonrpc/Debug.cpp @@ -149,7 +149,7 @@ Json::Value Debug::debug_traceTransaction( string const& } try { ExecutionResult er = m_eth.call( t.from(), t.value(), t.to(), t.data(), t.gas(), - t.gasPrice(), blockNumber, true, FudgeFactor::Lenient ); + t.gasPrice(), blockNumber, nullptr, FudgeFactor::Lenient ); ret["gas"] = toJS( t.gas() ); ret["return"] = toHexPrefixed( er.output ); ret["structLogs"] = ""; diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index 85864576c..4784acdca 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -415,7 +415,7 @@ string Eth::eth_call( TransactionSkeleton& t, string const& ExecutionResult er = client()->call( t.from, t.value, t.to, t.data, t.gas, t.gasPrice, #ifdef HISTORIC_STATE bN, - false, + nullptr, #endif FudgeFactor::Lenient ); diff --git a/test/tools/libtestutils/FixedClient.h b/test/tools/libtestutils/FixedClient.h index 1346570eb..5ff4d2bfa 100644 --- a/test/tools/libtestutils/FixedClient.h +++ b/test/tools/libtestutils/FixedClient.h @@ -30,6 +30,12 @@ using BlockNumber = unsigned; namespace dev { + +namespace eth { + class StandardTrace; +} + + namespace test { /** @@ -74,7 +80,7 @@ class FixedClient : public dev::eth::ClientBase { Address const&, u256, Address, bytes const&, u256, u256, #ifdef HISTORIC_STATE BlockNumber, - bool, + std::shared_ptr, #endif eth::FudgeFactor ) override { From 097239c11132c2eaf2efc27ebe6801b5fafb0f92 Mon Sep 17 00:00:00 2001 From: Stan Kladko <13399135+kladkogex@users.noreply.github.com> Date: Fri, 29 Sep 2023 19:35:45 +0100 Subject: [PATCH 005/414] 1664 Fix fudge factor --- libweb3jsonrpc/Debug.cpp | 319 ++++++++++++++++++++------------------- 1 file changed, 163 insertions(+), 156 deletions(-) diff --git a/libweb3jsonrpc/Debug.cpp b/libweb3jsonrpc/Debug.cpp index b80bc8a01..0bfd8417e 100644 --- a/libweb3jsonrpc/Debug.cpp +++ b/libweb3jsonrpc/Debug.cpp @@ -26,7 +26,7 @@ using namespace dev::rpc; using namespace dev::eth; using namespace skale; -Debug::Debug( eth::Client & _eth, SkaleDebugInterface* _debugInterface, const string& argv ) +Debug::Debug( eth::Client& _eth, SkaleDebugInterface* _debugInterface, const string& argv ) : m_eth( _eth ), m_debugInterface( _debugInterface ), argv_options( argv ) {} @@ -147,9 +147,16 @@ Json::Value Debug::debug_traceTransaction( string const& throw jsonrpc::JsonRpcException( "Unknown block number" ); ; } + + auto tracer = std::make_shared< StandardTrace >(); + tracer->setShowMnemonics(); + tracer->setOptions( debugOptions( _json ) ); + + try { - ExecutionResult er = m_eth.call( t.from(), t.value(), t.to(), t.data(), t.gas(), - t.gasPrice(), blockNumber, nullptr, FudgeFactor::Lenient ); + ExecutionResult er = m_eth.call( t.from(), t.value(), t.to(), + t.data(), t.gas(), + t.gasPrice(), blockNumber, tracer, FudgeFactor::Strict ); ret["gas"] = toJS( t.gas() ); ret["return"] = toHexPrefixed( er.output ); ret["structLogs"] = ""; @@ -170,188 +177,188 @@ Json::Value Debug::debug_traceBlock( string const& _blockRLP, Json::Value const& // TODO Make function without "block" parameter Json::Value Debug::debug_traceBlockByHash( string const& /*_blockHash*/, Json::Value const& _json ) { - Json::Value ret; - Block block = m_eth.latestBlock(); - ret["structLogs"] = traceBlock( block, _json ); - return ret; - } - - // TODO Make function without "block" parameter - Json::Value Debug::debug_traceBlockByNumber( int /*_blockNumber*/, Json::Value const& _json ) { - Json::Value ret; - Block block = m_eth.latestBlock(); - ret["structLogs"] = traceBlock( block, _json ); - return ret; - } + Json::Value ret; + Block block = m_eth.latestBlock(); + ret["structLogs"] = traceBlock( block, _json ); + return ret; +} - Json::Value Debug::debug_accountRangeAt( string const& _blockHashOrNumber, int _txIndex, - string const& /*_addressHash*/, int _maxResults ) { - Json::Value ret( Json::objectValue ); +// TODO Make function without "block" parameter +Json::Value Debug::debug_traceBlockByNumber( int /*_blockNumber*/, Json::Value const& _json ) { + Json::Value ret; + Block block = m_eth.latestBlock(); + ret["structLogs"] = traceBlock( block, _json ); + return ret; +} - if ( _maxResults <= 0 ) - throw jsonrpc::JsonRpcException( "Nonpositive maxResults" ); +Json::Value Debug::debug_accountRangeAt( string const& _blockHashOrNumber, int _txIndex, + string const& /*_addressHash*/, int _maxResults ) { + Json::Value ret( Json::objectValue ); - try { - State const state = stateAt( _blockHashOrNumber, _txIndex ); + if ( _maxResults <= 0 ) + throw jsonrpc::JsonRpcException( "Nonpositive maxResults" ); - throw std::logic_error( "Addresses list is not suppoted in Skale state" ); - // auto const addressMap = state.addresses(h256(_addressHash), _maxResults); + try { + State const state = stateAt( _blockHashOrNumber, _txIndex ); - // Json::Value addressList(Json::objectValue); - // for (auto const& record : addressMap.first) - // addressList[toString(record.first)] = toString(record.second); + throw std::logic_error( "Addresses list is not suppoted in Skale state" ); + // auto const addressMap = state.addresses(h256(_addressHash), _maxResults); - // ret["addressMap"] = addressList; - // ret["nextKey"] = toString(addressMap.second); - } catch ( Exception const& _e ) { - cwarn << diagnostic_information( _e ); - throw jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ); - } + // Json::Value addressList(Json::objectValue); + // for (auto const& record : addressMap.first) + // addressList[toString(record.first)] = toString(record.second); - return ret; + // ret["addressMap"] = addressList; + // ret["nextKey"] = toString(addressMap.second); + } catch ( Exception const& _e ) { + cwarn << diagnostic_information( _e ); + throw jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ); } - Json::Value Debug::debug_storageRangeAt( string const& _blockHashOrNumber, int _txIndex, - string const& /*_address*/, string const& /*_begin*/, int _maxResults ) { - Json::Value ret( Json::objectValue ); - ret["complete"] = true; - ret["storage"] = Json::Value( Json::objectValue ); - - if ( _maxResults <= 0 ) - throw jsonrpc::JsonRpcException( "Nonpositive maxResults" ); - - try { - State const state = stateAt( _blockHashOrNumber, _txIndex ); - - throw std::logic_error( "Obtaining of full storage is not suppoted in Skale state" ); - // map> const storage(state.storage(Address(_address))); - - // // begin is inclusive - // auto itBegin = storage.lower_bound(h256fromHex(_begin)); - // for (auto it = itBegin; it != storage.end(); ++it) - // { - // if (ret["storage"].size() == static_cast(_maxResults)) - // { - // ret["nextKey"] = toCompactHexPrefixed(it->first, 1); - // break; - // } - - // Json::Value keyValue(Json::objectValue); - // std::string hashedKey = toCompactHexPrefixed(it->first, 1); - // keyValue["key"] = toCompactHexPrefixed(it->second.first, 1); - // keyValue["value"] = toCompactHexPrefixed(it->second.second, 1); - - // ret["storage"][hashedKey] = keyValue; - // } - } catch ( Exception const& _e ) { - cwarn << diagnostic_information( _e ); - throw jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ); - } + return ret; +} - return ret; - } +Json::Value Debug::debug_storageRangeAt( string const& _blockHashOrNumber, int _txIndex, + string const& /*_address*/, string const& /*_begin*/, int _maxResults ) { + Json::Value ret( Json::objectValue ); + ret["complete"] = true; + ret["storage"] = Json::Value( Json::objectValue ); - std::string Debug::debug_preimage( std::string const& /*_hashedKey*/ ) { - throw std::logic_error( "Preimages do not exist in Skale state" ); - // h256 const hashedKey(h256fromHex(_hashedKey)); - // bytes const key = m_eth.state().lookupAux(hashedKey); + if ( _maxResults <= 0 ) + throw jsonrpc::JsonRpcException( "Nonpositive maxResults" ); - // return key.empty() ? std::string() : toHexPrefixed(key); + try { + State const state = stateAt( _blockHashOrNumber, _txIndex ); + + throw std::logic_error( "Obtaining of full storage is not suppoted in Skale state" ); + // map> const storage(state.storage(Address(_address))); + + // // begin is inclusive + // auto itBegin = storage.lower_bound(h256fromHex(_begin)); + // for (auto it = itBegin; it != storage.end(); ++it) + // { + // if (ret["storage"].size() == static_cast(_maxResults)) + // { + // ret["nextKey"] = toCompactHexPrefixed(it->first, 1); + // break; + // } + + // Json::Value keyValue(Json::objectValue); + // std::string hashedKey = toCompactHexPrefixed(it->first, 1); + // keyValue["key"] = toCompactHexPrefixed(it->second.first, 1); + // keyValue["value"] = toCompactHexPrefixed(it->second.second, 1); + + // ret["storage"][hashedKey] = keyValue; + // } + } catch ( Exception const& _e ) { + cwarn << diagnostic_information( _e ); + throw jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ); } - Json::Value Debug::debug_traceCall( Json::Value const& _call, Json::Value const& _options ) { - Json::Value ret; - try { - Block temp = m_eth.latestBlock(); - TransactionSkeleton ts = toTransactionSkeleton( _call ); - if ( !ts.from ) { - ts.from = Address(); - } - u256 nonce = temp.transactionsFrom( ts.from ); - u256 gas = ts.gas == Invalid256 ? m_eth.gasLimitRemaining() : ts.gas; - u256 gasPrice = ts.gasPrice == Invalid256 ? m_eth.gasBidPrice() : ts.gasPrice; - temp.mutableState().addBalance( ts.from, gas * gasPrice + ts.value ); - Transaction transaction( ts.value, gasPrice, gas, ts.to, ts.data, nonce ); - transaction.forceSender( ts.from ); - eth::ExecutionResult er; - // HACK 0 here is for gasPrice - Executive e( temp, m_eth.blockChain().lastBlockHashes(), 0 ); - e.setResultRecipient( er ); - Json::Value trace = traceTransaction( e, transaction, _options ); - ret["gas"] = toJS( transaction.gas() ); - ret["return"] = toHexPrefixed( er.output ); - ret["structLogs"] = trace; - } catch ( Exception const& _e ) { - cwarn << diagnostic_information( _e ); - } - return ret; - } + return ret; +} - void Debug::debug_pauseBroadcast( bool _pause ) { - m_eth.skaleHost()->pauseBroadcast( _pause ); - } - void Debug::debug_pauseConsensus( bool _pause ) { - m_eth.skaleHost()->pauseConsensus( _pause ); - } - void Debug::debug_forceBlock() { - m_eth.skaleHost()->forceEmptyBlock(); +std::string Debug::debug_preimage( std::string const& /*_hashedKey*/ ) { + throw std::logic_error( "Preimages do not exist in Skale state" ); + // h256 const hashedKey(h256fromHex(_hashedKey)); + // bytes const key = m_eth.state().lookupAux(hashedKey); + + // return key.empty() ? std::string() : toHexPrefixed(key); +} + +Json::Value Debug::debug_traceCall( Json::Value const& _call, Json::Value const& _options ) { + Json::Value ret; + try { + Block temp = m_eth.latestBlock(); + TransactionSkeleton ts = toTransactionSkeleton( _call ); + if ( !ts.from ) { + ts.from = Address(); + } + u256 nonce = temp.transactionsFrom( ts.from ); + u256 gas = ts.gas == Invalid256 ? m_eth.gasLimitRemaining() : ts.gas; + u256 gasPrice = ts.gasPrice == Invalid256 ? m_eth.gasBidPrice() : ts.gasPrice; + temp.mutableState().addBalance( ts.from, gas * gasPrice + ts.value ); + Transaction transaction( ts.value, gasPrice, gas, ts.to, ts.data, nonce ); + transaction.forceSender( ts.from ); + eth::ExecutionResult er; + // HACK 0 here is for gasPrice + Executive e( temp, m_eth.blockChain().lastBlockHashes(), 0 ); + e.setResultRecipient( er ); + Json::Value trace = traceTransaction( e, transaction, _options ); + ret["gas"] = toJS( transaction.gas() ); + ret["return"] = toHexPrefixed( er.output ); + ret["structLogs"] = trace; + } catch ( Exception const& _e ) { + cwarn << diagnostic_information( _e ); } + return ret; +} - void Debug::debug_forceBroadcast( const std::string& _transactionHash ) { - try { - h256 h = jsToFixed< 32 >( _transactionHash ); - if ( !m_eth.isKnownTransaction( h ) ) - BOOST_THROW_EXCEPTION( - jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ) ); +void Debug::debug_pauseBroadcast( bool _pause ) { + m_eth.skaleHost()->pauseBroadcast( _pause ); +} +void Debug::debug_pauseConsensus( bool _pause ) { + m_eth.skaleHost()->pauseConsensus( _pause ); +} +void Debug::debug_forceBlock() { + m_eth.skaleHost()->forceEmptyBlock(); +} - const Transaction tx = m_eth.transaction( h ); - m_eth.skaleHost()->forcedBroadcast( tx ); - } catch ( ... ) { +void Debug::debug_forceBroadcast( const std::string& _transactionHash ) { + try { + h256 h = jsToFixed< 32 >( _transactionHash ); + if ( !m_eth.isKnownTransaction( h ) ) BOOST_THROW_EXCEPTION( jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ) ); - } - } - std::string Debug::debug_interfaceCall( const std::string& _arg ) { - return m_debugInterface->call( _arg ); + const Transaction tx = m_eth.transaction( h ); + m_eth.skaleHost()->forcedBroadcast( tx ); + } catch ( ... ) { + BOOST_THROW_EXCEPTION( + jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ) ); } +} - std::string Debug::debug_getVersion() { - return Version; - } +std::string Debug::debug_interfaceCall( const std::string& _arg ) { + return m_debugInterface->call( _arg ); +} - std::string Debug::debug_getArguments() { - return argv_options; - } +std::string Debug::debug_getVersion() { + return Version; +} - std::string Debug::debug_getConfig() { - return m_eth.chainParams().getOriginalJson(); - } +std::string Debug::debug_getArguments() { + return argv_options; +} - std::string Debug::debug_getSchainName() { - return m_eth.chainParams().sChain.name; - } +std::string Debug::debug_getConfig() { + return m_eth.chainParams().getOriginalJson(); +} - uint64_t Debug::debug_getSnapshotCalculationTime() { - return m_eth.getSnapshotCalculationTime(); - } +std::string Debug::debug_getSchainName() { + return m_eth.chainParams().sChain.name; +} - uint64_t Debug::debug_getSnapshotHashCalculationTime() { - return m_eth.getSnapshotHashCalculationTime(); - } +uint64_t Debug::debug_getSnapshotCalculationTime() { + return m_eth.getSnapshotCalculationTime(); +} - uint64_t Debug::debug_doStateDbCompaction() { - auto t1 = boost::chrono::high_resolution_clock::now(); - m_eth.doStateDbCompaction(); - auto t2 = boost::chrono::high_resolution_clock::now(); +uint64_t Debug::debug_getSnapshotHashCalculationTime() { + return m_eth.getSnapshotHashCalculationTime(); +} - return boost::chrono::duration_cast< boost::chrono::milliseconds >( t2 - t1 ).count(); - } +uint64_t Debug::debug_doStateDbCompaction() { + auto t1 = boost::chrono::high_resolution_clock::now(); + m_eth.doStateDbCompaction(); + auto t2 = boost::chrono::high_resolution_clock::now(); - uint64_t Debug::debug_doBlocksDbCompaction() { - auto t1 = boost::chrono::high_resolution_clock::now(); - m_eth.doBlocksDbCompaction(); - auto t2 = boost::chrono::high_resolution_clock::now(); + return boost::chrono::duration_cast< boost::chrono::milliseconds >( t2 - t1 ).count(); +} - return boost::chrono::duration_cast< boost::chrono::milliseconds >( t2 - t1 ).count(); - } +uint64_t Debug::debug_doBlocksDbCompaction() { + auto t1 = boost::chrono::high_resolution_clock::now(); + m_eth.doBlocksDbCompaction(); + auto t2 = boost::chrono::high_resolution_clock::now(); + + return boost::chrono::duration_cast< boost::chrono::milliseconds >( t2 - t1 ).count(); +} From f271e3708a4954ffc4ef67d33bddb39a8097b434 Mon Sep 17 00:00:00 2001 From: Stan Kladko <13399135+kladkogex@users.noreply.github.com> Date: Fri, 29 Sep 2023 19:47:16 +0100 Subject: [PATCH 006/414] 1664 Process tracer result --- libweb3jsonrpc/Debug.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libweb3jsonrpc/Debug.cpp b/libweb3jsonrpc/Debug.cpp index 0bfd8417e..e21bdcd77 100644 --- a/libweb3jsonrpc/Debug.cpp +++ b/libweb3jsonrpc/Debug.cpp @@ -159,7 +159,9 @@ Json::Value Debug::debug_traceTransaction( string const& t.gasPrice(), blockNumber, tracer, FudgeFactor::Strict ); ret["gas"] = toJS( t.gas() ); ret["return"] = toHexPrefixed( er.output ); - ret["structLogs"] = ""; + Json::Value trace; + Json::Reader().parse( tracer->json(), trace ); + ret["structLogs"] = trace; } catch ( Exception const& _e ) { cwarn << diagnostic_information( _e ); } From f4b2bd7fa242f02e3ce4891c64be75adf9136ea9 Mon Sep 17 00:00:00 2001 From: Stan Kladko <13399135+kladkogex@users.noreply.github.com> Date: Fri, 29 Sep 2023 20:09:49 +0100 Subject: [PATCH 007/414] 1664 enable debug interface --- libweb3jsonrpc/Debug.cpp | 11 +++++++---- libweb3jsonrpc/Debug.h | 5 ++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/libweb3jsonrpc/Debug.cpp b/libweb3jsonrpc/Debug.cpp index e21bdcd77..f2ec972a8 100644 --- a/libweb3jsonrpc/Debug.cpp +++ b/libweb3jsonrpc/Debug.cpp @@ -26,8 +26,12 @@ using namespace dev::rpc; using namespace dev::eth; using namespace skale; -Debug::Debug( eth::Client& _eth, SkaleDebugInterface* _debugInterface, const string& argv ) - : m_eth( _eth ), m_debugInterface( _debugInterface ), argv_options( argv ) {} +Debug::Debug( eth::Client& _eth, SkaleDebugInterface* _debugInterface, const string& argv, + bool _enablePrivilegedApis ) + : m_eth( _eth ), + m_debugInterface( _debugInterface ), + argv_options( argv ), + enablePrivilegedApis( _enablePrivilegedApis ) {} h256 Debug::blockHash( string const& _blockNumberOrHash ) const { @@ -154,8 +158,7 @@ Json::Value Debug::debug_traceTransaction( string const& try { - ExecutionResult er = m_eth.call( t.from(), t.value(), t.to(), - t.data(), t.gas(), + ExecutionResult er = m_eth.call( t.from(), t.value(), t.to(), t.data(), t.gas(), t.gasPrice(), blockNumber, tracer, FudgeFactor::Strict ); ret["gas"] = toJS( t.gas() ); ret["return"] = toHexPrefixed( er.output ); diff --git a/libweb3jsonrpc/Debug.h b/libweb3jsonrpc/Debug.h index ef589a562..240af6ee5 100644 --- a/libweb3jsonrpc/Debug.h +++ b/libweb3jsonrpc/Debug.h @@ -22,7 +22,7 @@ class SessionManager; class Debug : public DebugFace { public: explicit Debug( eth::Client& _eth, SkaleDebugInterface* _debugInterface = nullptr, - const std::string& argv = std::string() ); + const std::string& argv = std::string(), bool _enablePrivilegedApis = false); virtual RPCModules implementedModules() const override { return RPCModules{ RPCModule{ "debug", "1.0" } }; @@ -70,6 +70,9 @@ class Debug : public DebugFace { Json::Value traceTransaction( dev::eth::Executive& _e, dev::eth::Transaction const& _t, Json::Value const& _json ); Json::Value traceBlock( dev::eth::Block const& _block, Json::Value const& _json ); + + bool enablePrivilegedApis; + }; } // namespace rpc From a96b3767138a6abaaf77625ac5f4b43fe83ff3a1 Mon Sep 17 00:00:00 2001 From: Stan Kladko <13399135+kladkogex@users.noreply.github.com> Date: Fri, 29 Sep 2023 20:51:43 +0100 Subject: [PATCH 008/414] 1664 completed implementation of eth_TraceTransaction --- libweb3jsonrpc/Debug.cpp | 36 +++++++++++++++++++++++++++++++----- libweb3jsonrpc/Debug.h | 5 ++++- skaled/main.cpp | 8 ++++---- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/libweb3jsonrpc/Debug.cpp b/libweb3jsonrpc/Debug.cpp index f2ec972a8..840f34126 100644 --- a/libweb3jsonrpc/Debug.cpp +++ b/libweb3jsonrpc/Debug.cpp @@ -26,6 +26,18 @@ using namespace dev::rpc; using namespace dev::eth; using namespace skale; +void Debug::checkPrivilegedAccess() const { + if ( enablePrivilegedApis ) { + throw jsonrpc::JsonRpcException( "This API call is not enabled" ); + } +} + +void Debug::checkHistoricStateEnabled() const { +#ifndef HISTORIC_STATE + throw jsonrpc::JsonRpcException( "This API call is available on archive nodes only" ); +#endif +} + Debug::Debug( eth::Client& _eth, SkaleDebugInterface* _debugInterface, const string& argv, bool _enablePrivilegedApis ) : m_eth( _eth ), @@ -35,6 +47,7 @@ Debug::Debug( eth::Client& _eth, SkaleDebugInterface* _debugInterface, const str h256 Debug::blockHash( string const& _blockNumberOrHash ) const { + checkPrivilegedAccess(); if ( isHash< h256 >( _blockNumberOrHash ) ) return h256( _blockNumberOrHash.substr( _blockNumberOrHash.size() - 64, 64 ) ); try { @@ -45,6 +58,7 @@ h256 Debug::blockHash( string const& _blockNumberOrHash ) const { } State Debug::stateAt( std::string const& /*_blockHashOrNumber*/, int _txIndex ) const { + checkPrivilegedAccess(); if ( _txIndex < 0 ) throw jsonrpc::JsonRpcException( "Negative index" ); @@ -132,12 +146,9 @@ Json::Value Debug::debug_traceTransaction( string const& ) { Json::Value ret; + checkHistoricStateEnabled(); -#ifndef HISTORIC_STATE - throw jsonrpc::JsonRpcException( - "debug_traceTransaction API is only supported " - "on archive nodes, not or core or sync nodes" ); -#else +#ifdef HISTORIC_STATE LocalisedTransaction t = m_eth.localisedTransaction( h256( _txHash ) ); @@ -174,6 +185,7 @@ Json::Value Debug::debug_traceTransaction( string const& Json::Value Debug::debug_traceBlock( string const& _blockRLP, Json::Value const& _json ) { + checkHistoricStateEnabled(); bytes bytes = fromHex( _blockRLP ); BlockHeader blockHeader( bytes ); return debug_traceBlockByHash( blockHeader.hash().hex(), _json ); @@ -182,6 +194,7 @@ Json::Value Debug::debug_traceBlock( string const& _blockRLP, Json::Value const& // TODO Make function without "block" parameter Json::Value Debug::debug_traceBlockByHash( string const& /*_blockHash*/, Json::Value const& _json ) { + checkHistoricStateEnabled(); Json::Value ret; Block block = m_eth.latestBlock(); ret["structLogs"] = traceBlock( block, _json ); @@ -191,6 +204,7 @@ Json::Value Debug::debug_traceBlockByHash( // TODO Make function without "block" parameter Json::Value Debug::debug_traceBlockByNumber( int /*_blockNumber*/, Json::Value const& _json ) { Json::Value ret; + checkHistoricStateEnabled(); Block block = m_eth.latestBlock(); ret["structLogs"] = traceBlock( block, _json ); return ret; @@ -198,6 +212,7 @@ Json::Value Debug::debug_traceBlockByNumber( int /*_blockNumber*/, Json::Value c Json::Value Debug::debug_accountRangeAt( string const& _blockHashOrNumber, int _txIndex, string const& /*_addressHash*/, int _maxResults ) { + checkPrivilegedAccess(); Json::Value ret( Json::objectValue ); if ( _maxResults <= 0 ) @@ -225,6 +240,7 @@ Json::Value Debug::debug_accountRangeAt( string const& _blockHashOrNumber, int _ Json::Value Debug::debug_storageRangeAt( string const& _blockHashOrNumber, int _txIndex, string const& /*_address*/, string const& /*_begin*/, int _maxResults ) { + checkPrivilegedAccess(); Json::Value ret( Json::objectValue ); ret["complete"] = true; ret["storage"] = Json::Value( Json::objectValue ); @@ -264,6 +280,7 @@ Json::Value Debug::debug_storageRangeAt( string const& _blockHashOrNumber, int _ } std::string Debug::debug_preimage( std::string const& /*_hashedKey*/ ) { + checkPrivilegedAccess(); throw std::logic_error( "Preimages do not exist in Skale state" ); // h256 const hashedKey(h256fromHex(_hashedKey)); // bytes const key = m_eth.state().lookupAux(hashedKey); @@ -300,16 +317,20 @@ Json::Value Debug::debug_traceCall( Json::Value const& _call, Json::Value const& } void Debug::debug_pauseBroadcast( bool _pause ) { + checkPrivilegedAccess(); m_eth.skaleHost()->pauseBroadcast( _pause ); } void Debug::debug_pauseConsensus( bool _pause ) { + checkPrivilegedAccess(); m_eth.skaleHost()->pauseConsensus( _pause ); } void Debug::debug_forceBlock() { + checkPrivilegedAccess(); m_eth.skaleHost()->forceEmptyBlock(); } void Debug::debug_forceBroadcast( const std::string& _transactionHash ) { + checkPrivilegedAccess(); try { h256 h = jsToFixed< 32 >( _transactionHash ); if ( !m_eth.isKnownTransaction( h ) ) @@ -325,6 +346,7 @@ void Debug::debug_forceBroadcast( const std::string& _transactionHash ) { } std::string Debug::debug_interfaceCall( const std::string& _arg ) { + checkPrivilegedAccess(); return m_debugInterface->call( _arg ); } @@ -333,10 +355,12 @@ std::string Debug::debug_getVersion() { } std::string Debug::debug_getArguments() { + checkPrivilegedAccess(); return argv_options; } std::string Debug::debug_getConfig() { + checkPrivilegedAccess(); return m_eth.chainParams().getOriginalJson(); } @@ -353,6 +377,7 @@ uint64_t Debug::debug_getSnapshotHashCalculationTime() { } uint64_t Debug::debug_doStateDbCompaction() { + checkPrivilegedAccess(); auto t1 = boost::chrono::high_resolution_clock::now(); m_eth.doStateDbCompaction(); auto t2 = boost::chrono::high_resolution_clock::now(); @@ -361,6 +386,7 @@ uint64_t Debug::debug_doStateDbCompaction() { } uint64_t Debug::debug_doBlocksDbCompaction() { + checkPrivilegedAccess(); auto t1 = boost::chrono::high_resolution_clock::now(); m_eth.doBlocksDbCompaction(); auto t2 = boost::chrono::high_resolution_clock::now(); diff --git a/libweb3jsonrpc/Debug.h b/libweb3jsonrpc/Debug.h index 240af6ee5..7b50f8345 100644 --- a/libweb3jsonrpc/Debug.h +++ b/libweb3jsonrpc/Debug.h @@ -22,7 +22,7 @@ class SessionManager; class Debug : public DebugFace { public: explicit Debug( eth::Client& _eth, SkaleDebugInterface* _debugInterface = nullptr, - const std::string& argv = std::string(), bool _enablePrivilegedApis = false); + const std::string& argv = std::string(), bool _enablePrivilegedApis = false ); virtual RPCModules implementedModules() const override { return RPCModules{ RPCModule{ "debug", "1.0" } }; @@ -73,6 +73,9 @@ class Debug : public DebugFace { bool enablePrivilegedApis; + void checkPrivilegedAccess() const; + + void checkHistoricStateEnabled() const; }; } // namespace rpc diff --git a/skaled/main.cpp b/skaled/main.cpp index 8118b017e..da7752419 100644 --- a/skaled/main.cpp +++ b/skaled/main.cpp @@ -1768,7 +1768,7 @@ int main( int argc, char** argv ) try { "Unknown seal engine: " + chainParams.sealEngineName ) ); g_client->dbRotationPeriod( - ( ( clock_t )( clockDbRotationPeriodInSeconds ) ) * CLOCKS_PER_SEC ); + ( ( clock_t ) ( clockDbRotationPeriodInSeconds ) ) * CLOCKS_PER_SEC ); // XXX nested lambdas and strlen hacks.. auto client_debug_handler = g_client->getDebugHandler(); @@ -1980,9 +1980,9 @@ int main( int argc, char** argv ) try { auto pAdminEthFace = bEnabledAPIs_admin ? new rpc::AdminEth( *g_client, *gasPricer.get(), keyManager, *sessionManager.get() ) : nullptr; - auto pDebugFace = bEnabledAPIs_debug ? - new rpc::Debug( *g_client, &debugInterface, argv_string ) : - nullptr; + auto pDebugFace = + new rpc::Debug( *g_client, &debugInterface, argv_string, bEnabledAPIs_debug ); + auto pPerformanceTrackerFace = bEnabledAPIs_performanceTracker ? new rpc::SkalePerformanceTracker( configPath.string() ) : nullptr; From 4ebfa1ae84b7f0c07b151d030da27e0080bfffd3 Mon Sep 17 00:00:00 2001 From: Stan Kladko <13399135+kladkogex@users.noreply.github.com> Date: Fri, 29 Sep 2023 21:03:17 +0100 Subject: [PATCH 009/414] 1664 adding tests --- test/historicstate/hardhat/contracts/Lock.sol | 27 +-- test/historicstate/hardhat/scripts/trace.js | 198 ++++++++++++++++++ 2 files changed, 207 insertions(+), 18 deletions(-) create mode 100644 test/historicstate/hardhat/scripts/trace.js diff --git a/test/historicstate/hardhat/contracts/Lock.sol b/test/historicstate/hardhat/contracts/Lock.sol index 14762d32e..c5bfd5937 100644 --- a/test/historicstate/hardhat/contracts/Lock.sol +++ b/test/historicstate/hardhat/contracts/Lock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.9; -contract Lock { +contract Lock { uint public totalSupply; mapping(address => uint) public balanceOf; mapping(address => mapping(address => uint)) public allowance; @@ -30,7 +30,7 @@ contract Lock { } - function die(address payable recipient) external { + function die(address payable recipient) external { selfdestruct(recipient); } @@ -46,10 +46,10 @@ contract Lock { address recipient, uint amount ) external returns (bool) { - // allowance[sender][msg.sender] -= amount; - // balanceOf[sender] -= amount; - // balanceOf[recipient] += amount; - // emit Transfer(sender, recipient, amount); + allowance[sender][msg.sender] -= amount; + balanceOf[sender] -= amount; + balanceOf[recipient] += amount; + emit Transfer(sender, recipient, amount); return true; } @@ -66,29 +66,20 @@ contract Lock { } - - - - function initialize() public { - require(!initialized, "Contract instance has already been initialized"); - initialized = true; + constructor() public { + require(!initialized, "Contract instance has already been initialized"); + initialized = true; name = "Lock"; symbol = "LOCK"; decimals = 18; owner = msg.sender; counter = 1; - - mint(10000000000000000000000000000000000000000); - - } - - function store() public { // Uncomment this line, and the import of "hardhat/console.sol", to print a log in your terminal // console.log("Unlock time is %o and block timestamp is %o", unlockTime, block.timestamp); diff --git a/test/historicstate/hardhat/scripts/trace.js b/test/historicstate/hardhat/scripts/trace.js new file mode 100644 index 000000000..d4bf630d9 --- /dev/null +++ b/test/historicstate/hardhat/scripts/trace.js @@ -0,0 +1,198 @@ +// We require the Hardhat Runtime Environment explicitly here. This is optional +// but useful for running the script in a standalone fashion through `node