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-1745 Fixed version of corrent fork in checkOutExternalGas #1782

Merged
merged 4 commits into from
Jan 12, 2024
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
1 change: 1 addition & 0 deletions libethcore/ChainOperationParams.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ struct SChain {
time_t precompiledConfigPatchTimestamp = 0;
time_t pushZeroPatchTimestamp = 0;
time_t skipInvalidTransactionsPatchTimestamp = 0;
time_t correctForkInPowPatchTimestamp = 0;

SChain() {
name = "TestChain";
Expand Down
5 changes: 2 additions & 3 deletions libethereum/Block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ pair< TransactionReceipts, bool > Block::sync(
// caller if we hit the limit

for ( Transaction& transaction : transactions ) {
transaction.checkOutExternalGas( _bc.chainParams().externalGasDifficulty );
transaction.checkOutExternalGas( _bc.chainParams(), _bc.number() );
}

assert( _bc.currentHash() == m_currentBlock.parentHash() );
Expand Down Expand Up @@ -631,8 +631,7 @@ u256 Block::enact( VerifiedBlockRef const& _block, BlockChain const& _bc ) {
// << " (state #"
// << state().getNonce( tr.from() ) << ") value = " << tr.value() <<
// endl;
const_cast< Transaction& >( tr ).checkOutExternalGas(
_bc.chainParams().externalGasDifficulty );
const_cast< Transaction& >( tr ).checkOutExternalGas( _bc.chainParams(), _bc.number() );
execute( _bc.lastBlockHashes(), tr );
// cerr << "Now: "
// << "State #" << state().getNonce( tr.from() ) << endl;
Expand Down
5 changes: 5 additions & 0 deletions libethereum/ChainParams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,11 @@ ChainParams ChainParams::loadConfig(
sChainObj.at( "skipInvalidTransactionsPatchTimestamp" ).get_int64() :
0;

s.correctForkInPowPatchTimestamp =
sChainObj.count( "correctForkInPowPatchTimestamp" ) ?
sChainObj.at( "correctForkInPowPatchTimestamp" ).get_int64() :
0;

if ( sChainObj.count( "nodeGroups" ) ) {
std::vector< NodeGroup > nodeGroups;
for ( const auto& nodeGroupConf : sChainObj["nodeGroups"].get_obj() ) {
Expand Down
23 changes: 19 additions & 4 deletions libethereum/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@

#include <libskale/ContractStorageLimitPatch.h>
#include <libskale/ContractStorageZeroValuePatch.h>
#include <libskale/CorrectForkInPowPatch.h>
#include <libskale/POWCheckPatch.h>
#include <libskale/PrecompiledConfigPatch.h>
#include <libskale/PushZeroPatch.h>
Expand Down Expand Up @@ -169,6 +170,7 @@ Client::Client( ChainParams const& _params, int _networkID,
SkipInvalidTransactionsPatch::setTimestamp(
this->chainParams().sChain.skipInvalidTransactionsPatchTimestamp );
PrecompiledConfigPatch::setTimestamp( chainParams().sChain.precompiledConfigPatchTimestamp );
CorrectForkInPowPatch::setTimestamp( chainParams().sChain.correctForkInPowPatchTimestamp );
}


Expand Down Expand Up @@ -331,6 +333,10 @@ void Client::init( WithExisting _forceAction, u256 _networkId ) {
// HACK Needed to set env var for consensus
AmsterdamFixPatch::isEnabled( *this );

// needed for checkOutExternalGas
CorrectForkInPowPatch::lastBlockTimestamp = blockChain().info().timestamp();
CorrectForkInPowPatch::lastBlockNumber = blockChain().number();

initCPUUSage();

doWork( false );
Expand Down Expand Up @@ -600,6 +606,10 @@ size_t Client::importTransactionsAsBlock(
sealUnconditionally( false );
importWorkingBlock();

// this needs to be updated as soon as possible, as it's used in new transactions validation
CorrectForkInPowPatch::lastBlockTimestamp = blockChain().info().timestamp();
CorrectForkInPowPatch::lastBlockNumber = blockChain().number();

if ( !UnsafeRegion::isActive() ) {
LOG( m_loggerDetail ) << "Total unsafe time so far = "
<< std::chrono::duration_cast< std::chrono::seconds >(
Expand Down Expand Up @@ -668,6 +678,9 @@ size_t Client::syncTransactions(
PushZeroPatch::lastBlockTimestamp = blockChain().info().timestamp();
SkipInvalidTransactionsPatch::lastBlockTimestamp = blockChain().info().timestamp();
PrecompiledConfigPatch::lastBlockTimestamp = blockChain().info().timestamp();
CorrectForkInPowPatch::lastBlockTimestamp = blockChain().info().timestamp();
CorrectForkInPowPatch::lastBlockNumber = blockChain().number();


DEV_WRITE_GUARDED( x_working ) {
assert( !m_working.isSealed() );
Expand Down Expand Up @@ -1190,15 +1203,17 @@ h256 Client::importTransaction( Transaction const& _t ) {
// the latest block in the client's blockchain. This can throw but
// we'll catch the exception at the RPC level.

const_cast< Transaction& >( _t ).checkOutExternalGas( chainParams().externalGasDifficulty );

// throws in case of error
State state;
u256 gasBidPrice;

DEV_GUARDED( m_blockImportMutex ) {
state = this->state().createStateReadOnlyCopy();
gasBidPrice = this->gasBidPrice();

// We need to check external gas under mutex to be sure about current block bumber
// correctness
const_cast< Transaction& >( _t ).checkOutExternalGas( chainParams(), number() );
}

Executive::verifyTransaction( _t,
Expand Down Expand Up @@ -1255,7 +1270,7 @@ ExecutionResult Client::call( Address const& _from, u256 _value, Address _dest,
Transaction t( _value, gasPrice, gas, _dest, _data, nonce );
t.forceSender( _from );
t.forceChainId( chainParams().chainID );
t.checkOutExternalGas( ~u256( 0 ) );
t.ignoreExternalGas();
if ( _ff == FudgeFactor::Lenient ) {
historicBlock.mutableState().mutableHistoricState().addBalance(
_from, ( u256 )( t.gas() * t.gasPrice() + t.value() ) );
Expand All @@ -1280,7 +1295,7 @@ ExecutionResult Client::call( Address const& _from, u256 _value, Address _dest,
Transaction t( _value, gasPrice, gas, _dest, _data, nonce );
t.forceSender( _from );
t.forceChainId( chainParams().chainID );
t.checkOutExternalGas( ~u256( 0 ) );
t.ignoreExternalGas();
if ( _ff == FudgeFactor::Lenient )
temp.mutableState().addBalance( _from, ( u256 )( t.gas() * t.gasPrice() + t.value() ) );
ret = temp.execute( bc().lastBlockHashes(), t, skale::Permanence::Reverted );
Expand Down
2 changes: 0 additions & 2 deletions libethereum/Client.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,6 @@ class Client : public ClientBase, protected Worker {
/// Retrieve pending transactions
Transactions pending() const override;

Transactions debugGetFutureTransactions() const { return m_tq.debugGetFutureTransactions(); }

/// Queues a block for import.
ImportResult queueBlock( bytes const& _block, bool _isSafe = false );

Expand Down
11 changes: 8 additions & 3 deletions libethereum/ClientBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/

#include "ClientBase.h"
#include <libskale/CorrectForkInPowPatch.h>

#include <algorithm>
#include <utility>
Expand Down Expand Up @@ -89,7 +90,7 @@ std::pair< bool, ExecutionResult > ClientBase::estimateGasStep( int64_t _gas, Bl
t = Transaction( _value, _gasPrice, _gas, _data, nonce );
t.forceSender( _from );
t.forceChainId( chainId() );
t.checkOutExternalGas( ~u256( 0 ) );
t.ignoreExternalGas();
EnvInfo const env( _latestBlock.info(), bc().lastBlockHashes(), 0, _gas );
// Make a copy of state!! It will be deleted after step!
State tempState = _latestBlock.mutableState();
Expand All @@ -115,8 +116,12 @@ 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,
bc().sealEngine()->chainParams().scheduleForBlockNumber( bc().number() ) );
int64_t lowerBound =
CorrectForkInPowPatch::isEnabled() ?
Transaction::baseGasRequired( !_dest, &_data,
bc().sealEngine()->chainParams().scheduleForBlockNumber( bc().number() ) ) :
Transaction::baseGasRequired( !_dest, &_data, EVMSchedule() );

Block bk = latestBlock();
if ( upperBound > bk.info().gasLimit() ) {
upperBound = bk.info().gasLimit().convert_to< int64_t >();
Expand Down
3 changes: 2 additions & 1 deletion libethereum/SkaleHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,7 @@ void SkaleHost::createBlock( const ConsensusExtFace::transactions_vector& _appro
// TODO clear occasionally this cache?!
if ( m_m_transaction_cache.find( sha.asArray() ) != m_m_transaction_cache.cend() ) {
Transaction t = m_m_transaction_cache.at( sha.asArray() );
t.checkOutExternalGas( m_client.chainParams(), m_client.number(), true );
out_txns.push_back( t );
LOG( m_debugLogger ) << "Dropping good txn " << sha << std::endl;
m_debugTracer.tracepoint( "drop_good" );
Expand All @@ -666,7 +667,7 @@ void SkaleHost::createBlock( const ConsensusExtFace::transactions_vector& _appro
// ).detach();
} else {
Transaction t( data, CheckTransaction::Everything, true );
t.checkOutExternalGas( m_client.chainParams().externalGasDifficulty );
t.checkOutExternalGas( m_client.chainParams(), m_client.number() );
out_txns.push_back( t );
LOG( m_debugLogger ) << "Will import consensus-born txn";
m_debugTracer.tracepoint( "import_consensus_born" );
Expand Down
26 changes: 20 additions & 6 deletions libethereum/Transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <libdevcrypto/Common.h>
#include <libethcore/Exceptions.h>
#include <libevm/VMFace.h>
#include <libskale/CorrectForkInPowPatch.h>

using namespace std;
using namespace dev;
Expand Down Expand Up @@ -180,19 +181,32 @@
}
}

void Transaction::checkOutExternalGas( u256 const& _difficulty ) {
assert( _difficulty > 0 );
if ( !m_externalGasIsChecked && !isInvalid() ) {
void Transaction::checkOutExternalGas( const ChainParams& _cp, uint64_t _bn, bool _force ) {
u256 const& difficulty = _cp.externalGasDifficulty;
assert( difficulty > 0 );
if ( ( _force || !m_externalGasIsChecked ) && !isInvalid() ) {
h256 hash = dev::sha3( sender().ref() ) ^ dev::sha3( nonce() ) ^ dev::sha3( gasPrice() );
if ( !hash ) {
hash = h256( 1 );
}
u256 externalGas = ~u256( 0 ) / u256( hash ) / _difficulty;
u256 externalGas = ~u256( 0 ) / u256( hash ) / difficulty;
if ( externalGas > 0 )
ctrace << "Mined gas: " << externalGas << endl;
if ( externalGas >= baseGasRequired( ConstantinopleSchedule ) ) {
m_externalGas = externalGas;

EVMSchedule scheduleForUse = ConstantinopleSchedule;
if ( CorrectForkInPowPatch::isEnabled() )
scheduleForUse = _cp.scheduleForBlockNumber( _bn );

// never call checkOutExternalGas with non-last block
if ( _bn != CorrectForkInPowPatch::getLastBlockNumber() ) {
ctrace << _bn << " != " << CorrectForkInPowPatch::getLastBlockNumber();
BOOST_THROW_EXCEPTION( std::runtime_error(

Check warning on line 203 in libethereum/Transaction.cpp

View check run for this annotation

Codecov / codecov/patch

libethereum/Transaction.cpp#L202-L203

Added lines #L202 - L203 were not covered by tests
"Internal error: checkOutExternalGas() has invalid block number" ) );
}

if ( externalGas >= baseGasRequired( scheduleForUse ) )
m_externalGas = externalGas;

m_externalGasIsChecked = true;
}
}
Expand Down
9 changes: 8 additions & 1 deletion libethereum/Transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include <libethcore/Common.h>
#include <libethcore/TransactionBase.h>

#include "ChainParams.h"

namespace dev {
namespace eth {

Expand Down Expand Up @@ -120,7 +122,12 @@ class Transaction : public TransactionBase {

u256 gasPrice() const;

void checkOutExternalGas( u256 const& _difficulty );
void checkOutExternalGas( const ChainParams& _cp, uint64_t _bn, bool _force = false );

void ignoreExternalGas() {
m_externalGasIsChecked = true;
m_externalGas = 0;
}

private:
bool m_externalGasIsChecked = false;
Expand Down
11 changes: 0 additions & 11 deletions libethereum/TransactionQueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -537,14 +537,3 @@ void TransactionQueue::verifierBody() {
MICROPROFILE_LEAVE();
}
}

Transactions TransactionQueue::debugGetFutureTransactions() const {
Transactions res;
ReadGuard l( m_lock );
for ( auto addressAndMap : m_future ) {
for ( auto nonceAndTransaction : addressAndMap.second ) {
res.push_back( nonceAndTransaction.second.transaction );
} // for nonce
} // for address
return res;
}
2 changes: 0 additions & 2 deletions libethereum/TransactionQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,6 @@ class TransactionQueue {
template < class... Args >
Transactions topTransactionsSync( unsigned _limit, Args... args );

Transactions debugGetFutureTransactions() const;

/// Get a hash set of transactions in the queue
/// @returns A hash set of all transactions in the queue
const h256Hash knownTransactions() const;
Expand Down
2 changes: 2 additions & 0 deletions libethereum/ValidationSchemes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ void validateConfigJson( js::mObject const& _obj ) {
{ "skipInvalidTransactionsPatchTimestamp",
{ { js::int_type }, JsonFieldPresence::Optional } },
{ "precompiledConfigPatchTimestamp",
{ { js::int_type }, JsonFieldPresence::Optional } },
{ "correctForkInPowPatchTimestamp",
{ { js::int_type }, JsonFieldPresence::Optional } } } );

js::mArray const& nodes = sChain.at( "nodes" ).get_array();
Expand Down
2 changes: 2 additions & 0 deletions libskale/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ set(sources
PrecompiledConfigPatch.cpp
PushZeroPatch.cpp
SkipInvalidTransactionsPatch.cpp
CorrectForkInPowPatch.cpp
)

set(headers
Expand All @@ -44,6 +45,7 @@ set(headers
PrecompiledConfigPatch.h
OverlayFS.h
SkipInvalidTransactionsPatch.h
CorrectForkInPowPatch.h
)

add_library(skale ${sources} ${headers})
Expand Down
12 changes: 12 additions & 0 deletions libskale/CorrectForkInPowPatch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include "CorrectForkInPowPatch.h"

time_t CorrectForkInPowPatch::activationTimestamp;
time_t CorrectForkInPowPatch::lastBlockTimestamp;
unsigned CorrectForkInPowPatch::lastBlockNumber;

bool CorrectForkInPowPatch::isEnabled() {
if ( activationTimestamp == 0 ) {
return false;
}
return activationTimestamp <= lastBlockTimestamp;
}
41 changes: 41 additions & 0 deletions libskale/CorrectForkInPowPatch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#ifndef CORRECTFORKINPOWPATCH_H
#define CORRECTFORKINPOWPATCH_H

#include <libethereum/SchainPatch.h>

#include <time.h>

namespace dev {
namespace eth {
class Client;
}
namespace test {
class TestBlockChain;
class TestOutputHelperFixture;
} // namespace test
} // namespace dev

/*
* Context: use current, and not Constantinople, fork in Transaction::checkOutExternalGas()
*/
class CorrectForkInPowPatch : public SchainPatch {
public:
static bool isEnabled();

static void setTimestamp( time_t _timeStamp ) {
printInfo( __FILE__, _timeStamp );
activationTimestamp = _timeStamp;
}

static unsigned getLastBlockNumber() { return lastBlockNumber; }

private:
friend class dev::eth::Client;
friend class dev::test::TestBlockChain;
friend class dev::test::TestOutputHelperFixture;
static time_t activationTimestamp;
static time_t lastBlockTimestamp;
static unsigned lastBlockNumber;
};

#endif // CORRECTFORKINPOWPATCH_H
7 changes: 0 additions & 7 deletions libweb3jsonrpc/Debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,10 +314,3 @@ uint64_t Debug::debug_doBlocksDbCompaction() {

return boost::chrono::duration_cast< boost::chrono::milliseconds >( t2 - t1 ).count();
}

Json::Value Debug::debug_getFutureTransactions() {
auto res = toJson( m_eth.debugGetFutureTransactions() );
for ( auto& t : res )
t.removeMember( "data" );
return res;
}
2 changes: 0 additions & 2 deletions libweb3jsonrpc/Debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ class Debug : public DebugFace {
virtual uint64_t debug_doStateDbCompaction() override;
virtual uint64_t debug_doBlocksDbCompaction() override;

virtual Json::Value debug_getFutureTransactions() override;

private:
eth::Client const& m_eth;
SkaleDebugInterface* m_debugInterface = nullptr;
Expand Down
Loading
Loading