Skip to content

Commit

Permalink
#1545 state locking
Browse files Browse the repository at this point in the history
  • Loading branch information
kladkogex committed Jul 23, 2024
1 parent 1115682 commit 9c2ea64
Show file tree
Hide file tree
Showing 3 changed files with 2 additions and 151 deletions.
124 changes: 0 additions & 124 deletions libethereum/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,6 @@ using namespace skale::error;
static_assert( BOOST_VERSION >= 106400, "Wrong boost headers version" );


static const int64_t c_maxGasEstimate = 50000000;

namespace {
std::string filtersToString( h256Hash const& _fs ) {
std::stringstream str;
Expand Down Expand Up @@ -1507,127 +1505,5 @@ bytes Client::historicStateCodeAt( Address _a, BlockNumber _block ) const {
}
#endif

std::pair< u256, ExecutionResult > Client::estimateGas( Address const& _from, u256 _value,
Address _dest, bytes const& _data, int64_t _maxGas, u256 _gasPrice,
GasEstimationCallback const& _callback ) {
try {
int64_t upperBound = _maxGas;
if ( upperBound == Invalid256 || upperBound > c_maxGasEstimate )
upperBound = c_maxGasEstimate;
int64_t lowerBound;
if ( CorrectForkInPowPatch::isEnabledInWorkingBlock() )
lowerBound = Transaction::baseGasRequired( !_dest, &_data,
bc().sealEngine()->chainParams().makeEvmSchedule(
bc().info().timestamp(), bc().number() ) );
else
lowerBound = Transaction::baseGasRequired( !_dest, &_data, EVMSchedule() );

Block latest = getReadOnlyLatestBlockCopy();
Block pending = latest;

if ( upperBound > pending.info().gasLimit() ) {
upperBound = pending.info().gasLimit().convert_to< int64_t >();
}
u256 gasPrice = _gasPrice == Invalid256 ? gasBidPrice() : _gasPrice;

// We execute transact u256 countAt( Address _a ) const override;
// u256 balanceAt( Address _a ) const override;
// u256 stateAt( Address _a, u256 _l ) const override;
// bytes codeAt( Address _a ) const override;
// h256 codeHashAt( Address _a ) const override;
// std::map< h256, std::pair< u256, u256 > > storageAt( Address _a ) const override;ion with maximum gas limit
// to calculate how many of gas will be used.
// Then we execute transaction with this gas limit
// and check if it will be enough.
// If not run binary search to find optimal gas limit.

auto estimatedStep =
estimateGasStep( upperBound, latest, pending, _from, _dest, _value, gasPrice, _data );
if ( estimatedStep.first ) {
auto executionResult = estimatedStep.second;
auto gasUsed = std::max( executionResult.gasUsed.convert_to< int64_t >(), lowerBound );

estimatedStep =
estimateGasStep( gasUsed, latest, pending, _from, _dest, _value, gasPrice, _data );
if ( estimatedStep.first ) {
return make_pair( gasUsed, executionResult );
}
while ( lowerBound + 1 < upperBound ) {
int64_t middle = ( lowerBound + upperBound ) / 2;
estimatedStep = estimateGasStep(
middle, latest, pending, _from, _dest, _value, gasPrice, _data );
if ( estimatedStep.first ) {
upperBound = middle;
} else {
lowerBound = middle;
}
if ( _callback ) {
_callback( GasEstimationProgress{ lowerBound, upperBound } );
}
}
}

return make_pair( upperBound,
estimateGasStep( upperBound, latest, pending, _from, _dest, _value, gasPrice, _data )
.second );
} catch ( ... ) {
// TODO: Some sort of notification of failure.
return make_pair( u256(), ExecutionResult() );
}
}


std::pair< bool, ExecutionResult > Client::estimateGasStep( int64_t _gas, Block& _latestBlock,
Block& _pendingBlock, Address const& _from, Address const& _destination, u256 const& _value,
u256 const& _gasPrice, bytes const& _data ) {
u256 nonce = _latestBlock.transactionsFrom( _from );
Transaction t;
if ( _destination )
t = Transaction( _value, _gasPrice, _gas, _destination, _data, nonce );
else
t = Transaction( _value, _gasPrice, _gas, _data, nonce );
t.forceSender( _from );
t.forceChainId( chainId() );
t.ignoreExternalGas();
EnvInfo const env( _pendingBlock.info(), bc().lastBlockHashes(),
_pendingBlock.previousInfo().timestamp(), 0, _gas );
// Make a copy of state!! It will be deleted after step!
State tempState = _latestBlock.mutableState();
tempState.addBalance( _from, ( u256 )( t.gas() * t.gasPrice() + t.value() ) );
ExecutionResult executionResult =
tempState.execute( env, bc().chainParams(), t, Permanence::Reverted ).first;
if ( executionResult.excepted == TransactionException::OutOfGas ||
executionResult.excepted == TransactionException::OutOfGasBase ||
executionResult.excepted == TransactionException::OutOfGasIntrinsic ||
executionResult.codeDeposit == CodeDeposit::Failed ||
executionResult.excepted == TransactionException::BadJumpDestination ||
executionResult.excepted == TransactionException::RevertInstruction ) {
return make_pair( false, executionResult );
} else {
return make_pair( true, executionResult );
}
}

u256 Client::countAt( Address _a ) const {
return getReadOnlyLatestBlockCopy().state().getNonce( _a );
}

u256 Client::balanceAt( Address _a ) const {
return getReadOnlyLatestBlockCopy().state().balance( _a );
}

u256 Client::stateAt( Address _a, u256 _l ) const {
return getReadOnlyLatestBlockCopy().state().storage( _a, _l );
}

bytes Client::codeAt( Address _a ) const {
return getReadOnlyLatestBlockCopy().state().code( _a );
}

h256 Client::codeHashAt( Address _a ) const {
return getReadOnlyLatestBlockCopy().state().codeHash( _a );
}

map< h256, pair< u256, u256 > > Client::storageAt( Address _a ) const {
return getReadOnlyLatestBlockCopy().state().storage( _a );
}
26 changes: 1 addition & 25 deletions libethereum/Client.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,16 +128,7 @@ namespace dev {
/// Imports the given transaction into the transaction queue
h256 importTransaction(Transaction const &_t) override;


/// Estimate gas usage for call/create.
/// @param _maxGas An upper bound value for estimation, if not provided default value of
/// c_maxGasEstimate will be used.
/// @param _callback Optional callback function for progress reporting
std::pair<u256, ExecutionResult> estimateGas(Address const &_from, u256 _value, Address _dest,
bytes const &_data, int64_t _maxGas,
u256 _gasPrice,
GasEstimationCallback const &_callback = GasEstimationCallback()) override;


/// Makes the given call. Nothing is recorded into the state.
ExecutionResult call(Address const &_secret, u256 _value, Address _dest, bytes const &_data,
u256 _gas, u256 _gasPrice,
Expand Down Expand Up @@ -762,21 +753,6 @@ namespace dev {
void initStateFromDiskOrGenesis();

void populateNewChainStateFromGenesis();

u256 countAt( Address _a ) const override;
u256 balanceAt( Address _a ) const override;
u256 stateAt( Address _a, u256 _l ) const override;
bytes codeAt( Address _a ) const override;
h256 codeHashAt( Address _a ) const override;
std::map< h256, std::pair< u256, u256 > > storageAt( Address _a ) const override;


private:
std::pair<bool, ExecutionResult> estimateGasStep(int64_t _gas, Block &_latestBlock,
Block &_pendingBlock, Address const &_from,
Address const &_destination, u256 const &_value,
u256 const &_gasPrice, bytes const &_data);

};

} // namespace eth
Expand Down
3 changes: 1 addition & 2 deletions libethereum/ClientBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,7 @@ class ClientBase : public Interface {
std::map< h256, std::pair< u256, u256 > > storageAt( Address _a ) const override;
std::pair< u256, ExecutionResult > estimateGas( Address const& _from, u256 _value,
Address _dest, bytes const& _data, int64_t _maxGas, u256 _gasPrice,
GasEstimationCallback const& _callback ) override;

GasEstimationCallback const& _callback = GasEstimationCallback() ) override;
std::pair< bool, ExecutionResult > estimateGasStep( int64_t _gas, Block& _latestBlock,
Block& _pendingBlock, Address const& _from, Address const& _destination, u256 const& _value,
u256 const& _gasPrice, bytes const& _data );
Expand Down

0 comments on commit 9c2ea64

Please sign in to comment.