Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug/is 1022 sigsegv in rollback #1947

Merged
merged 10 commits into from
Aug 5, 2024
11 changes: 7 additions & 4 deletions libethcore/ChainOperationParams.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ class PrecompiledContract {
u256 const& _blockNumber ) const {
return m_cost( _in, _chainParams, _blockNumber );
}
std::pair< bool, bytes > execute( bytesConstRef _in ) const { return m_execute( _in ); }
std::pair< bool, bytes > execute(
bytesConstRef _in, skale::OverlayFS* _overlayFS = nullptr ) const {
return m_execute( _in, _overlayFS );
}

u256 const& startingBlock() const { return m_startingBlock; }

Expand Down Expand Up @@ -270,9 +273,9 @@ struct ChainOperationParams {
Address const& _a, bytesConstRef _in, u256 const& _blockNumber ) const {
return precompiled.at( _a ).cost( _in, *this, _blockNumber );
}
std::pair< bool, bytes > executePrecompiled(
Address const& _a, bytesConstRef _in, u256 const& ) const {
return precompiled.at( _a ).execute( _in );
std::pair< bool, bytes > executePrecompiled( Address const& _a, bytesConstRef _in, u256 const&,
skale::OverlayFS* _overlayFS = nullptr ) const {
return precompiled.at( _a ).execute( _in, _overlayFS );
}
bool precompiledExecutionAllowedFrom(
Address const& _a, Address const& _from, bool _readOnly ) const {
Expand Down
7 changes: 2 additions & 5 deletions libethereum/Executive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,11 +331,8 @@ bool Executive::call( CallParameters const& _p, u256 const& _gasPrice, Address c
m_gas = ( u256 )( _p.gas - g );
bytes output;
bool success;
// dev::eth::g_state = m_s.delegateWrite();
dev::eth::g_overlayFS = m_s.fs();
tie( success, output ) =
m_chainParams.executePrecompiled( _p.codeAddress, _p.data, m_envInfo.number() );
// m_s = dev::eth::g_state.delegateWrite();
tie( success, output ) = m_chainParams.executePrecompiled(
_p.codeAddress, _p.data, m_envInfo.number(), m_s.fs().get() );
size_t outputSize = output.size();
m_output = owning_bytes_ref{ std::move( output ), 0, outputSize };
if ( !success ) {
Expand Down
114 changes: 31 additions & 83 deletions libethereum/Precompiled.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ namespace eth {

std::shared_ptr< skutils::json_config_file_accessor > g_configAccesssor;
std::shared_ptr< SkaleHost > g_skaleHost;
std::shared_ptr< skale::OverlayFS > g_overlayFS;

}; // namespace eth
}; // namespace dev
Expand Down Expand Up @@ -281,7 +280,10 @@ boost::filesystem::path getFileStorageDir( const Address& _address ) {
}

// TODO: check file name and file existance
ETH_REGISTER_PRECOMPILED( createFile )( bytesConstRef _in ) {
ETH_REGISTER_FS_PRECOMPILED( createFile )( bytesConstRef _in, skale::OverlayFS* _overlayFS ) {
if ( !_overlayFS )
throw runtime_error( "_overlayFS is nullptr " );

try {
auto rawAddress = _in.cropped( 12, 20 ).toBytes();
std::string address;
Expand All @@ -297,14 +299,14 @@ ETH_REGISTER_PRECOMPILED( createFile )( bytesConstRef _in ) {
const fs::path filePath( rawFilename );
const fs::path fsDirectoryPath = getFileStorageDir( Address( address ) );
if ( !fs::exists( fsDirectoryPath ) ) {
g_overlayFS->createDirectory( fsDirectoryPath.string() );
_overlayFS->createDirectory( fsDirectoryPath.string() );
}
const fs::path fsFilePath = fsDirectoryPath / filePath.parent_path();
if ( filePath.filename().extension() == "._hash" ) {
throw std::runtime_error(
"createFile() failed because _hash extension is not allowed" );
}
g_overlayFS->createFile( ( fsFilePath / filePath.filename() ).string(), fileSize );
_overlayFS->createFile( ( fsFilePath / filePath.filename() ).string(), fileSize );

u256 code = 1;
bytes response = toBigEndian( code );
Expand All @@ -322,7 +324,10 @@ ETH_REGISTER_PRECOMPILED( createFile )( bytesConstRef _in ) {
return { false, response };
}

ETH_REGISTER_PRECOMPILED( uploadChunk )( bytesConstRef _in ) {
ETH_REGISTER_FS_PRECOMPILED( uploadChunk )( bytesConstRef _in, skale::OverlayFS* _overlayFS ) {
if ( !_overlayFS )
throw runtime_error( "_overlayFS is nullptr " );

try {
auto rawAddress = _in.cropped( 12, 20 ).toBytes();
std::string address;
Expand All @@ -349,7 +354,7 @@ ETH_REGISTER_PRECOMPILED( uploadChunk )( bytesConstRef _in ) {
const _byte_* data =
_in.cropped( 128 + filenameBlocksCount * UINT256_SIZE, dataLength ).data();

g_overlayFS->writeChunk( filePath.string(), position, dataLength, data );
_overlayFS->writeChunk( filePath.string(), position, dataLength, data );

u256 code = 1;
bytes response = toBigEndian( code );
Expand Down Expand Up @@ -451,7 +456,10 @@ ETH_REGISTER_PRECOMPILED( getFileSize )( bytesConstRef _in ) {
return { false, response };
}

ETH_REGISTER_PRECOMPILED( deleteFile )( bytesConstRef _in ) {
ETH_REGISTER_FS_PRECOMPILED( deleteFile )( bytesConstRef _in, skale::OverlayFS* _overlayFS ) {
if ( !_overlayFS )
throw runtime_error( "_overlayFS is nullptr " );

try {
auto rawAddress = _in.cropped( 12, 20 ).toBytes();
std::string address;
Expand All @@ -462,8 +470,8 @@ ETH_REGISTER_PRECOMPILED( deleteFile )( bytesConstRef _in ) {

const fs::path filePath = getFileStorageDir( Address( address ) ) / filename;

g_overlayFS->deleteFile( filePath.string() );
g_overlayFS->deleteFile( filePath.string() + "._hash" );
_overlayFS->deleteFile( filePath.string() );
_overlayFS->deleteFile( filePath.string() + "._hash" );

u256 code = 1;
bytes response = toBigEndian( code );
Expand All @@ -481,7 +489,10 @@ ETH_REGISTER_PRECOMPILED( deleteFile )( bytesConstRef _in ) {
return { false, response };
}

ETH_REGISTER_PRECOMPILED( createDirectory )( bytesConstRef _in ) {
ETH_REGISTER_FS_PRECOMPILED( createDirectory )( bytesConstRef _in, skale::OverlayFS* _overlayFS ) {
if ( !_overlayFS )
throw runtime_error( "_overlayFS is nullptr " );

try {
auto rawAddress = _in.cropped( 12, 20 ).toBytes();
std::string address;
Expand All @@ -491,7 +502,7 @@ ETH_REGISTER_PRECOMPILED( createDirectory )( bytesConstRef _in ) {
convertBytesToString( _in, 32, directoryPath, directoryPathLength );

const fs::path absolutePath = getFileStorageDir( Address( address ) ) / directoryPath;
g_overlayFS->createDirectory( absolutePath.string() );
_overlayFS->createDirectory( absolutePath.string() );

u256 code = 1;
bytes response = toBigEndian( code );
Expand All @@ -509,7 +520,10 @@ ETH_REGISTER_PRECOMPILED( createDirectory )( bytesConstRef _in ) {
return { false, response };
}

ETH_REGISTER_PRECOMPILED( deleteDirectory )( bytesConstRef _in ) {
ETH_REGISTER_FS_PRECOMPILED( deleteDirectory )( bytesConstRef _in, skale::OverlayFS* _overlayFS ) {
if ( !_overlayFS )
throw runtime_error( "_overlayFS is nullptr " );

try {
auto rawAddress = _in.cropped( 12, 20 ).toBytes();
std::string address;
Expand All @@ -525,8 +539,8 @@ ETH_REGISTER_PRECOMPILED( deleteDirectory )( bytesConstRef _in ) {

const std::string absolutePathStr = absolutePath.string();

g_overlayFS->deleteFile( absolutePathStr + "._hash" );
g_overlayFS->deleteDirectory( absolutePath.string() );
_overlayFS->deleteFile( absolutePathStr + "._hash" );
_overlayFS->deleteDirectory( absolutePath.string() );

u256 code = 1;
bytes response = toBigEndian( code );
Expand All @@ -544,7 +558,8 @@ ETH_REGISTER_PRECOMPILED( deleteDirectory )( bytesConstRef _in ) {
return { false, response };
}

ETH_REGISTER_PRECOMPILED( calculateFileHash )( bytesConstRef _in ) {
ETH_REGISTER_FS_PRECOMPILED( calculateFileHash )
( bytesConstRef _in, skale::OverlayFS* _overlayFS ) {
try {
auto rawAddress = _in.cropped( 12, 20 ).toBytes();
std::string address;
Expand All @@ -560,7 +575,7 @@ ETH_REGISTER_PRECOMPILED( calculateFileHash )( bytesConstRef _in ) {
throw std::runtime_error( "calculateFileHash() failed because file does not exist" );
}

g_overlayFS->calculateFileHash( filePath.string() );
_overlayFS->calculateFileHash( filePath.string() );

u256 code = 1;
bytes response = toBigEndian( code );
Expand Down Expand Up @@ -1057,30 +1072,6 @@ ETH_REGISTER_PRECOMPILED( getBlockRandom )( bytesConstRef ) {
}

ETH_REGISTER_PRECOMPILED( addBalance )( [[maybe_unused]] bytesConstRef _in ) {
/*
try {
auto rawAddress = _in.cropped( 0, 20 ).toBytes();
std::string address;
boost::algorithm::hex( rawAddress.begin(), rawAddress.end(), back_inserter( address ) );
auto add = parseBigEndianRightPadded( _in, 20, 32 );

auto value = u256( add );

g_state.addBalance( Address( address ), value );

dev::u256 code = 1;
bytes response = toBigEndian( code );
return {true, response};
} catch ( std::exception& ex ) {
std::string strError = ex.what();
if ( strError.empty() )
strError = "exception without description";
LOG( getLogger( VerbosityError ) )
<< "Exception in precompiled/addBalance(): " << strError << "\n";
} catch ( ... ) {
LOG( getLogger( VerbosityError ) ) << "Unknown exception in precompiled/addBalance()\n";
}
*/
dev::u256 code = 0;
bytes response = toBigEndian( code );
return { false, response }; // 1st false - means bad error occur
Expand Down Expand Up @@ -1111,47 +1102,4 @@ ETH_REGISTER_PRECOMPILED( getIMABLSPublicKey )( bytesConstRef ) {
return { false, response }; // 1st false - means bad error occur
}

// ETH_REGISTER_PRECOMPILED( convertUint256ToString )( bytesConstRef _in ) {
// try {
// auto rawValue = _in.cropped( 0, 32 ).toBytes();
// std::string strValue = "";
// boost::algorithm::hex( rawValue.begin(), rawValue.end(), back_inserter( strValue ) );
// bytes response = stat_string_to_bytes_with_length( strValue );
// return {true, response};
// } catch ( std::exception& ex ) {
// std::string strError = ex.what();
// if ( strError.empty() )
// strError = "exception without description";
// LOG( getLogger( VerbosityError ) )
// << "Exception in precompiled/convertUint256ToString(): " << strError << "\n";
// } catch ( ... ) {
// LOG( getLogger( VerbosityError ) )
// << "Unknown exception in precompiled/convertUint256ToString()\n";
// }
// u256 code = 0;
// bytes response = toBigEndian( code );
// return {false, response}; // 1st false - means bad error occur
//}
// ETH_REGISTER_PRECOMPILED( convertAddressToString )( bytesConstRef _in ) {
// try {
// auto rawAddress = _in.cropped( 12, 20 ).toBytes();
// std::string strValue = "";
// boost::algorithm::hex( rawAddress.begin(), rawAddress.end(), back_inserter( strValue ) );
// bytes response = stat_string_to_bytes_with_length( strValue );
// return {true, response};
// } catch ( std::exception& ex ) {
// std::string strError = ex.what();
// if ( strError.empty() )
// strError = "exception without description";
// LOG( getLogger( VerbosityError ) )
// << "Exception in precompiled/convertAddressToString(): " << strError << "\n";
// } catch ( ... ) {
// LOG( getLogger( VerbosityError ) )
// << "Unknown exception in precompiled/convertAddressToString()\n";
// }
// u256 code = 0;
// bytes response = toBigEndian( code );
// return {false, response}; // 1st false - means bad error occur
//}

} // namespace
34 changes: 31 additions & 3 deletions libethereum/Precompiled.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,26 @@ namespace eth {
extern std::shared_ptr< skutils::json_config_file_accessor > g_configAccesssor;
extern std::shared_ptr< SkaleHost > g_skaleHost;
extern skale::State g_state;
extern std::shared_ptr< skale::OverlayFS > g_overlayFS;

struct ChainOperationParams;

using PrecompiledExecutor = std::function< std::pair< bool, bytes >( bytesConstRef _in ) >;
// allow call both with overlayFS and without it
class PrecompiledExecutor {
public:
std::pair< bool, bytes > operator()(
bytesConstRef _in, skale::OverlayFS* _overlayFS = nullptr ) const {
return proxy( _in, _overlayFS );
}
PrecompiledExecutor() {}
PrecompiledExecutor( const std::function< std::pair< bool, bytes >(
bytesConstRef _in, skale::OverlayFS* _overlayFS ) >& _func )
: proxy( _func ) {}

private:
std::function< std::pair< bool, bytes >( bytesConstRef _in, skale::OverlayFS* _overlayFS ) >
proxy;
};

using PrecompiledPricer = std::function< bigint(
bytesConstRef _in, ChainOperationParams const& _chainParams, u256 const& _blockNumber ) >;

Expand Down Expand Up @@ -98,13 +113,26 @@ class PrecompiledRegistrar {
static PrecompiledRegistrar* s_this;
};

// ignore _overlayFS param and call registered function with 1 parameter
// TODO: unregister on unload with a static object.
#define ETH_REGISTER_PRECOMPILED( Name ) \
static std::pair< bool, bytes > __eth_registerPrecompiledFunction##Name( bytesConstRef _in ); \
static PrecompiledExecutor __eth_registerPrecompiledFactory##Name = \
::dev::eth::PrecompiledRegistrar::registerExecutor( \
#Name, &__eth_registerPrecompiledFunction##Name ); \
#Name, PrecompiledExecutor( \
[]( bytesConstRef _in, skale::OverlayFS* ) -> std::pair< bool, bytes > { \
return __eth_registerPrecompiledFunction##Name( _in ); \
} ) ); \
static std::pair< bool, bytes > __eth_registerPrecompiledFunction##Name

#define ETH_REGISTER_FS_PRECOMPILED( Name ) \
static std::pair< bool, bytes > __eth_registerPrecompiledFunction##Name( \
bytesConstRef _in, skale::OverlayFS* _overlayFS ); \
static PrecompiledExecutor __eth_registerPrecompiledFactory##Name = \
::dev::eth::PrecompiledRegistrar::registerExecutor( \
#Name, PrecompiledExecutor( &__eth_registerPrecompiledFunction##Name ) ); \
static std::pair< bool, bytes > __eth_registerPrecompiledFunction##Name

#define ETH_REGISTER_PRECOMPILED_PRICER( Name ) \
static bigint __eth_registerPricerFunction##Name( \
bytesConstRef _in, ChainOperationParams const& _chainParams, u256 const& _blockNumber ); \
Expand Down
Loading
Loading