Skip to content

Commit

Permalink
Merge branch 'v3.18.0' into bug/1640-change-snapshot-hash-computation
Browse files Browse the repository at this point in the history
  • Loading branch information
olehnikolaiev authored Jan 17, 2024
2 parents c4cffb1 + 678f59b commit 2d0e3d5
Show file tree
Hide file tree
Showing 23 changed files with 388 additions and 172 deletions.
196 changes: 102 additions & 94 deletions .github/workflows/test.yml

Large diffs are not rendered by default.

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
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
12 changes: 11 additions & 1 deletion libethereum/SkaleHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ using namespace dev::eth;
#define CONSENSUS 1
#endif

const int SkaleHost::REJECT_OLD_TRANSACTION_THROUGH_BROADCAST_INTERVAL_SEC = 600;

std::unique_ptr< ConsensusInterface > DefaultConsensusFactory::create(
ConsensusExtFace& _extFace ) const {
#if CONSENSUS
Expand Down Expand Up @@ -325,6 +327,13 @@ void SkaleHost::logState() {
}

h256 SkaleHost::receiveTransaction( std::string _rlp ) {
// drop incoming transactions if skaled has an outdated state
if ( m_client.bc().info().timestamp() + REJECT_OLD_TRANSACTION_THROUGH_BROADCAST_INTERVAL_SEC <
std::time( NULL ) ) {
LOG( m_debugLogger ) << "Dropped the transaction received through broadcast";
return h256();
}

Transaction transaction( jsToBytes( _rlp, OnFailed::Throw ), CheckTransaction::None );

h256 sha = transaction.sha3();
Expand Down Expand Up @@ -644,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 @@ -657,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
4 changes: 4 additions & 0 deletions libethereum/SkaleHost.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,4 +229,8 @@ class SkaleHost {
std::atomic_int total_sent, total_arrived;

boost::chrono::high_resolution_clock::time_point latestBlockTime;

// reject old transactions that come through broadcast
// if current ts is much bigger than currentBlock.ts
static const int REJECT_OLD_TRANSACTION_THROUGH_BROADCAST_INTERVAL_SEC;
};
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 @@ u256 Transaction::gasPrice() const {
}
}

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(
"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
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
8 changes: 7 additions & 1 deletion libweb3jsonrpc/Eth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ void GappedTransactionIndexCache::ensureCached( BlockNumber _bn,
_readLock.unlock();
_writeLock.lock();

unsigned realBn = _bn;
if ( _bn == LatestBlock )
realBn = client.number();
else if ( _bn == PendingBlock )
realBn = client.number() + 1; // TODO test this case and decide

assert( real2gappedCache.size() <= cacheSize );
if ( real2gappedCache.size() >= cacheSize ) {
real2gappedCache.erase( real2gappedCache.begin() );
Expand All @@ -89,7 +95,7 @@ void GappedTransactionIndexCache::ensureCached( BlockNumber _bn,
pair< h256, unsigned > loc = client.transactionLocation( th );

// ignore transactions with 0 gas usage OR different location!
if ( diff == 0 || client.numberFromHash( loc.first ) != _bn || loc.second != realIndex )
if ( diff == 0 || client.numberFromHash( loc.first ) != realBn || loc.second != realIndex )
continue;

// cache it
Expand Down
Loading

0 comments on commit 2d0e3d5

Please sign in to comment.