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

SKALED-1600 Use correct fork in gas estimation #1743

Merged
merged 7 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion libethereum/ClientBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ std::pair< u256, ExecutionResult > ClientBase::estimateGas( Address const& _from
int64_t upperBound = _maxGas;
if ( upperBound == Invalid256 || upperBound > c_maxGasEstimate )
upperBound = c_maxGasEstimate;
int64_t lowerBound = Transaction::baseGasRequired( !_dest, &_data, EVMSchedule() );
int64_t lowerBound = Transaction::baseGasRequired( !_dest, &_data,
bc().sealEngine()->chainParams().scheduleForBlockNumber( bc().number() ) );
Block bk = latestBlock();
if ( upperBound > bk.info().gasLimit() ) {
upperBound = bk.info().gasLimit().convert_to< int64_t >();
Expand Down
5 changes: 4 additions & 1 deletion libweb3jsonrpc/EthFace.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@
jsonrpc::JSON_OBJECT, NULL ),
&dev::rpc::EthFace::eth_syncingI );
this->bindAndAddMethod( jsonrpc::Procedure( "eth_estimateGas", jsonrpc::PARAMS_BY_POSITION,
jsonrpc::JSON_STRING, "param1", jsonrpc::JSON_OBJECT, NULL ),
jsonrpc::JSON_STRING, NULL ),
&dev::rpc::EthFace::eth_estimateGasI );
this->bindAndAddMethod( jsonrpc::Procedure( "eth_chainId", jsonrpc::PARAMS_BY_POSITION,
jsonrpc::JSON_STRING, NULL ),
Expand Down Expand Up @@ -419,6 +419,9 @@
response = this->eth_syncing();
}
inline virtual void eth_estimateGasI( const Json::Value& request, Json::Value& response ) {
if ( !request.isArray() || request.empty() )
BOOST_THROW_EXCEPTION(

Check warning on line 423 in libweb3jsonrpc/EthFace.h

View check run for this annotation

Codecov / codecov/patch

libweb3jsonrpc/EthFace.h#L423

Added line #L423 was not covered by tests
jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ) );
response = this->eth_estimateGas( request[0u] );
}
inline virtual void eth_chainIdI( const Json::Value& request, Json::Value& response ) {
Expand Down
42 changes: 36 additions & 6 deletions test/unittests/libethereum/ClientTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,11 @@ static std::string const c_configString = R"(
"allowFutureBlocks": true,
"homesteadForkBlock": "0x00",
"EIP150ForkBlock": "0x00",
"EIP158ForkBlock": "0x00"
"EIP158ForkBlock": "0x00",
"byzantiumForkBlock": "0x00",
"constantinopleForkBlock": "0x00",
"constantinopleFixForkBlock": "0x00",
"istanbulForkBlock": "0x00"
},
"genesis": {
"nonce": "0x0000000000000042",
Expand Down Expand Up @@ -375,6 +379,7 @@ static std::string const c_genesisInfoSkaleTest = std::string() +
"byzantiumForkBlock": "0x00",
"constantinopleForkBlock": "0x00",
"constantinopleFixForkBlock": "0x00",
"istanbulForkBlock": "0x00",
"networkID" : "12313219",
"chainID": "0x01",
"maximumExtraDataSize": "0x20",
Expand Down Expand Up @@ -439,6 +444,25 @@ static std::string const c_genesisInfoSkaleTest = std::string() +

BOOST_AUTO_TEST_SUITE( EstimateGas )

BOOST_AUTO_TEST_CASE( transactionWithData ) {
TestClientFixture fixture( c_genesisInfoSkaleTest );
ClientTest* testClient = asClientTest( fixture.ethereum() );

dev::eth::simulateMining( *( fixture.ethereum() ), 10 );

Address addr( "0xca4409573a5129a72edf85d6c51e26760fc9c903" );

bytes data =
jsToBytes( "0x11223344556600770000" );

u256 estimate = testClient
->estimateGas( addr, 0, addr, data, 10000000, 1000000,
GasEstimationCallback() )
.first;

BOOST_CHECK_EQUAL( estimate, u256( 21000+7*16+3*4 ) );
}

BOOST_AUTO_TEST_CASE( constantConsumption ) {
TestClientFixture fixture( c_genesisInfoSkaleTest );
ClientTest* testClient = asClientTest( fixture.ethereum() );
Expand Down Expand Up @@ -475,7 +499,8 @@ BOOST_AUTO_TEST_CASE( constantConsumption ) {
GasEstimationCallback() )
.first;

BOOST_CHECK_EQUAL( estimate, u256( 71800 ) );
// 71488 checked in reall call under Istanbul fork
BOOST_CHECK_EQUAL( estimate, u256( 71488 ) );
}

BOOST_AUTO_TEST_CASE( linearConsumption ) {
Expand Down Expand Up @@ -513,7 +538,7 @@ BOOST_AUTO_TEST_CASE( linearConsumption ) {
GasEstimationCallback() )
.first;

BOOST_CHECK_EQUAL( estimate, u256( 2367016 ) );
BOOST_CHECK_EQUAL( estimate, u256( 2366934 ) );
}

BOOST_AUTO_TEST_CASE( exceedsGasLimit ) {
Expand Down Expand Up @@ -589,7 +614,7 @@ BOOST_AUTO_TEST_CASE( runsInterference ) {
GasEstimationCallback() )
.first;

BOOST_CHECK_EQUAL( estimate, u256( 41684 ) );
BOOST_CHECK_EQUAL( estimate, u256( 41424 ) );
}

BOOST_AUTO_TEST_CASE( consumptionWithRefunds ) {
Expand Down Expand Up @@ -810,7 +835,7 @@ BOOST_AUTO_TEST_CASE( consumptionWithReverts ) {
GasEstimationCallback() )
.first;

BOOST_CHECK_EQUAL( estimate, u256( 121944 ) );
BOOST_CHECK_EQUAL( estimate, u256( 121632 ) );
}

BOOST_AUTO_TEST_SUITE_END()
Expand All @@ -829,6 +854,7 @@ static std::string const c_genesisInfoSkaleIMABLSPublicKeyTest = std::string() +
"byzantiumForkBlock": "0x00",
"constantinopleForkBlock": "0x00",
"constantinopleFixForkBlock": "0x00",
"istanbulForkBlock": "0x00",
"networkID" : "12313219",
"chainID": "0x01",
"maximumExtraDataSize": "0x20",
Expand Down Expand Up @@ -953,7 +979,11 @@ static std::string const c_skaleConfigString = R"E(
"allowFutureBlocks": true,
"homesteadForkBlock": "0x00",
"EIP150ForkBlock": "0x00",
"EIP158ForkBlock": "0x00"
"EIP158ForkBlock": "0x00",
"byzantiumForkBlock": "0x00",
"constantinopleForkBlock": "0x00",
"constantinopleFixForkBlock": "0x00",
"istanbulForkBlock": "0x00"
},
"genesis": {
"nonce": "0x0000000000000042",
Expand Down
4 changes: 3 additions & 1 deletion test/unittests/libweb3jsonrpc/WebThreeStubClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -396,9 +396,11 @@ std::string WebThreeStubClient::eth_sendTransaction( const Json::Value& param1 )
jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString() );
}

std::string WebThreeStubClient::eth_estimateGas( const Json::Value& param1 ) {
std::string WebThreeStubClient::eth_estimateGas( const Json::Value& param1, const std::string& param2 ) {
Json::Value p;
p.append( param1 );
if(!param2.empty())
p.append( param2 );
Json::Value result = this->CallMethod( "eth_estimateGas", p );
if ( result.isString() )
return result.asString();
Expand Down
2 changes: 1 addition & 1 deletion test/unittests/libweb3jsonrpc/WebThreeStubClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class WebThreeStubClient : public jsonrpc::Client {
std::string eth_call( const Json::Value& param1, const std::string& param2 ) noexcept( false );
std::string eth_callEIP1898( const Json::Value& param1, const Json::Value& param2 ) noexcept( false );
bool eth_flush() noexcept( false );
std::string eth_estimateGas( const Json::Value& param1 ) noexcept( false );
std::string eth_estimateGas( const Json::Value& param1, const std::string& param2 = "" ) noexcept( false );
Json::Value eth_getBlockByHash( const std::string& param1, bool param2 ) noexcept( false );
Json::Value eth_getBlockByNumber( const std::string& param1, bool param2 ) noexcept( false );
Json::Value eth_getTransactionByHash( const std::string& param1 ) noexcept( false );
Expand Down
45 changes: 35 additions & 10 deletions test/unittests/libweb3jsonrpc/jsonrpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ static std::string const c_genesisConfigString =
"EIP158ForkBlock": "0x00",
"byzantiumForkBlock": "0x00",
"constantinopleForkBlock": "0x00",
"istanbulForkBlock": "0x00",
"skaleDisableChainIdCheck": true,
"externalGasDifficulty": "0x1"
},
Expand Down Expand Up @@ -280,6 +281,7 @@ struct JsonRpcFixture : public TestOutputHelperFixture {
chainParams.byzantiumForkBlock = 0;
chainParams.EIP158ForkBlock = 0;
chainParams.constantinopleForkBlock = 0;
chainParams.istanbulForkBlock = 0;
chainParams.externalGasDifficulty = 1;
chainParams.sChain.contractStorageLimit = 128;
// 615 + 1430 is experimentally-derived block size + average extras size
Expand Down Expand Up @@ -1263,7 +1265,11 @@ BOOST_AUTO_TEST_CASE( eth_estimateGas ) {
testPositive["to"] = "0xD2001300000000000000000000000000000000D4";
testPositive["data"] = "0xfdde8d66000000000000000000000000000000000000000000000000000000000000c350";
response = fixture.rpcClient->eth_estimateGas( testPositive );
BOOST_CHECK( response == "0x1dc58" );
string response2 = fixture.rpcClient->eth_estimateGas( testPositive, "latest" );
string response3 = fixture.rpcClient->eth_estimateGas( testPositive, "1" );
BOOST_CHECK_EQUAL( response, "0x1db20" );
BOOST_CHECK_EQUAL( response2, "0x1db20" );
BOOST_CHECK_EQUAL( response3, "0x1db20" );
}

BOOST_AUTO_TEST_CASE( eth_sendRawTransaction_gasLimitExceeded ) {
Expand Down Expand Up @@ -1596,22 +1602,26 @@ BOOST_AUTO_TEST_CASE( transactionWithoutFunds ) {
string balanceString = fixture.rpcClient->eth_getBalance( toJS( address2 ), "latest" );
BOOST_REQUIRE_EQUAL( toJS( 0 ), balanceString );

Json::Value transact;
transact["from"] = toJS( address2 );
transact["to"] = contractAddress;
transact["data"] = "0x15b2eec30000000000000000000000000000000000000000000000000000000000000003";

string gasEstimateStr = fixture.rpcClient->eth_estimateGas(transact);
u256 gasEstimate = jsToU256(gasEstimateStr);

u256 powGasPrice = 0;
do {
const u256 GAS_PER_HASH = 1;
u256 candidate = h256::random();
h256 hash = dev::sha3( address2 ) ^ dev::sha3( u256( 0 ) ) ^ dev::sha3( candidate );
u256 externalGas = ~u256( 0 ) / u256( hash ) * GAS_PER_HASH;
if ( externalGas >= 21000 + 21000 ) {
if ( externalGas >= gasEstimate && externalGas < gasEstimate + gasEstimate/10 ) {
powGasPrice = candidate;
}
} while ( !powGasPrice );

Json::Value transact;
transact["from"] = toJS( address2 );
transact["to"] = contractAddress;
transact["gasPrice"] = toJS( powGasPrice );
transact["data"] = "0x15b2eec30000000000000000000000000000000000000000000000000000000000000003";

fixture.rpcClient->eth_sendTransaction( transact );
dev::eth::mineTransaction( *( fixture.client ), 1 );

Expand Down Expand Up @@ -1865,7 +1875,8 @@ contract TestEstimateGas {
txStore1["data"] = "0x6057361d0000000000000000000000000000000000000000000000000000000000000001";
txStore1["from"] = toJS( senderAddress );
txStore1["gasPrice"] = fixture.rpcClient->eth_gasPrice();
string txHash = fixture.rpcClient->eth_call( txStore1, "latest" );
fixture.rpcClient->eth_sendTransaction( txStore1 );
dev::eth::mineTransaction( *( fixture.client ), 1 );

Json::Value estimateGasCall; // call clear(0)
estimateGasCall["to"] = contractAddress;
Expand All @@ -1875,11 +1886,25 @@ contract TestEstimateGas {
string estimatedGas = fixture.rpcClient->eth_estimateGas( estimateGasCall );

dev::bytes data = dev::jsToBytes( estimateGasCall["data"].asString() );

BOOST_REQUIRE( dev::jsToU256( estimatedGas ) > dev::eth::TransactionBase::baseGasRequired(
false, &data, fixture.client->chainParams().scheduleForBlockNumber(
fixture.client->number() ) ) );
BOOST_REQUIRE( dev::jsToU256( estimatedGas ) == 21871 );

// try to send with this gas
estimateGasCall["gas"] = toJS( jsToInt( estimatedGas ) );
string clearHash = fixture.rpcClient->eth_sendTransaction( estimateGasCall );
dev::eth::mineTransaction( *( fixture.client ), 1 );
Json::Value clearReceipt = fixture.rpcClient->eth_getTransactionReceipt( clearHash );
BOOST_REQUIRE_EQUAL(clearReceipt["status"], "0x1");
BOOST_REQUIRE_LT(jsToInt(clearReceipt["gasUsed"].asString()), 21000);

// try to lower gas
estimateGasCall["gas"] = toJS( jsToInt( estimatedGas ) - 1 );
clearHash = fixture.rpcClient->eth_sendTransaction( estimateGasCall );
dev::eth::mineTransaction( *( fixture.client ), 1 );
clearReceipt = fixture.rpcClient->eth_getTransactionReceipt( clearHash );
BOOST_REQUIRE_EQUAL(clearReceipt["status"], "0x0");
BOOST_REQUIRE_GT(jsToInt(clearReceipt["gasUsed"].asString()), 21000);
}

BOOST_AUTO_TEST_CASE( storage_limit_contract ) {
Expand Down
Loading