Skip to content

Commit

Permalink
Merge pull request #1720 from skalenetwork/develop
Browse files Browse the repository at this point in the history
New beta
  • Loading branch information
DmytroNazarenko authored Nov 6, 2023
2 parents baf8a6e + ea41014 commit bc932a7
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 41 deletions.
1 change: 1 addition & 0 deletions libethcore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ target_include_directories( ethcore PRIVATE
target_link_libraries( ethcore PUBLIC
devcrypto
devcore
skale
)
21 changes: 16 additions & 5 deletions libethcore/SealEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "SealEngine.h"
#include "TransactionBase.h"

#include <libskale/POWCheckPatch.h>

#include "../libdevcore/microprofile.h"

using namespace std;
Expand Down Expand Up @@ -94,6 +96,16 @@ void SealEngineFace::populateFromParent( BlockHeader& _bi, BlockHeader const& _p

void SealEngineFace::verifyTransaction( ImportRequirements::value _ir, TransactionBase const& _t,
BlockHeader const& _header, u256 const& _gasUsed ) const {
// verifyTransaction is the only place where TransactionBase is used instead of Transaction.
u256 gas;
if ( POWCheckPatch::isEnabled() ) {
// new behavior is to use pow-enabled gas
gas = _t.gas();
} else {
// old behavior is to use non-POW gas
gas = _t.nonPowGas();
}

MICROPROFILE_SCOPEI( "SealEngineFace", "verifyTransaction", MP_ORCHID );
if ( ( _ir & ImportRequirements::TransactionSignatures ) &&
_header.number() < chainParams().EIP158ForkBlock && _t.isReplayProtected() )
Expand All @@ -118,17 +130,16 @@ void SealEngineFace::verifyTransaction( ImportRequirements::value _ir, Transacti
eth::EVMSchedule const& schedule = evmSchedule( _header.number() );

// Pre calculate the gas needed for execution
if ( ( _ir & ImportRequirements::TransactionBasic ) &&
_t.baseGasRequired( schedule ) > _t.gas() )
if ( ( _ir & ImportRequirements::TransactionBasic ) && _t.baseGasRequired( schedule ) > gas )
BOOST_THROW_EXCEPTION( OutOfGasIntrinsic() << RequirementError(
static_cast< bigint >( _t.baseGasRequired( schedule ) ),
static_cast< bigint >( _t.gas() ) ) );
static_cast< bigint >( gas ) ) );

// Avoid transactions that would take us beyond the block gas limit.
if ( _gasUsed + static_cast< bigint >( _t.gas() ) > _header.gasLimit() )
if ( _gasUsed + static_cast< bigint >( gas ) > _header.gasLimit() )
BOOST_THROW_EXCEPTION( BlockGasLimitReached() << RequirementErrorComment(
static_cast< bigint >( _header.gasLimit() - _gasUsed ),
static_cast< bigint >( _t.gas() ),
static_cast< bigint >( gas ),
string( "_gasUsed + (bigint)_t.gas() > _header.gasLimit()" ) ) );
}

Expand Down
12 changes: 12 additions & 0 deletions libethcore/TransactionBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,18 @@ u256 TransactionBase::gasPrice() const {
}

u256 TransactionBase::gas() const {
/* Note that gas() function has been removed from Transaction.
* instead the logic has been moved to the gas() function of TransactionBase
* this has been done in order to address the problem of switching "virtual" on/off
*/
assert( !isInvalid() );
if ( getExternalGas() != 0 ) {
return getExternalGas();
} else {
return m_gas;
}
}

u256 TransactionBase::nonPowGas() const {
return m_gas;
}
14 changes: 13 additions & 1 deletion libethcore/TransactionBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,12 @@ class TransactionBase {
/// @returns the base fee and thus the implied exchange rate of ETH to GAS.
u256 gasPrice() const;

/// @returns the non-PoW gas
u256 nonPowGas() const;

/// @returns the total gas to convert, paid for from sender's account. Any unused gas gets
/// refunded once the contract is ended.
virtual u256 gas() const;
u256 gas() const;

/// @returns the receiving address of the message-call transaction (undefined for
/// contract-creation transactions).
Expand Down Expand Up @@ -261,6 +264,15 @@ class TransactionBase {

static bool isZeroSignature( u256 const& _r, u256 const& _s ) { return !_r && !_s; }

/*
* this function is provided in order for aleth tests and utilities to compile.
* In will never be called in skaled since in skaled TransactionBase objects are never
* instantiated. Aleth tests and utilities do instantiate TransactionBase
*
* The function always returns zero, which means no PoW.
*/
virtual u256 getExternalGas() const { return 0; }

/// Clears the signature.
void clearSignature() { m_vrs = SignatureStruct(); }

Expand Down
62 changes: 62 additions & 0 deletions libethereum/BlockChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <libethcore/Exceptions.h>

#include <libskale/AmsterdamFixPatch.h>
#include <libskale/SkipInvalidTransactionsPatch.h>
#include <libskale/TotalStorageUsedPatch.h>

#include "Block.h"
Expand Down Expand Up @@ -172,6 +173,24 @@ unsigned c_maxCacheSize = 1024 * 1024 * 64;
/// Min size, below which we don't bother flushing it.
unsigned c_minCacheSize = 1024 * 1024 * 32;

bool hasPotentialInvalidTransactionsInBlock( BlockNumber _bn, const BlockChain& _bc ) {
if ( _bn == 0 )
return false;

if ( SkipInvalidTransactionsPatch::getActivationTimestamp() == 0 )
return true;

if ( _bn == PendingBlock )
return !SkipInvalidTransactionsPatch::isEnabled();

if ( _bn == LatestBlock )
_bn = _bc.number();

time_t prev_ts = _bc.info( _bc.numberHash( _bn - 1 ) ).timestamp();

return prev_ts < SkipInvalidTransactionsPatch::getActivationTimestamp();
}

string BlockChain::getChainDirName( const ChainParams& _cp ) {
return toHex( BlockHeader( _cp.genesisBlock() ).hash().ref().cropped( 0, 4 ) );
}
Expand Down Expand Up @@ -334,6 +353,49 @@ void BlockChain::close() {
m_lastBlockHashes->clear();
}

std::pair< h256, unsigned > BlockChain::transactionLocation( h256 const& _transactionHash ) const {
// cached transactionAddresses for transactions with gasUsed==0 should be re-queried from DB
bool cached = false;
{
ReadGuard g( x_transactionAddresses );
cached = m_transactionAddresses.count( _transactionHash ) > 0;
}

// get transactionAddresses from DB or cache
TransactionAddress ta = queryExtras< TransactionAddress, ExtraTransactionAddress >(
_transactionHash, m_transactionAddresses, x_transactionAddresses, NullTransactionAddress );

if ( !ta )
return std::pair< h256, unsigned >( h256(), 0 );

auto blockNumber = this->number( ta.blockHash );

if ( !hasPotentialInvalidTransactionsInBlock( blockNumber, *this ) )
return std::make_pair( ta.blockHash, ta.index );

// rest is for blocks with possibility of invalid transactions

// compute gas used
TransactionReceipt receipt = transactionReceipt( ta.blockHash, ta.index );
u256 cumulativeGasUsed = receipt.cumulativeGasUsed();
u256 prevGasUsed =
ta.index == 0 ? 0 : transactionReceipt( ta.blockHash, ta.index - 1 ).cumulativeGasUsed();
u256 gasUsed = cumulativeGasUsed - prevGasUsed;

// re-query receipt from DB if gasUsed==0 (and cache might have wrong value)
if ( gasUsed == 0 && cached ) {
// remove from cache
{
WriteGuard g( x_transactionAddresses );
m_transactionAddresses.erase( _transactionHash );
}
// re-read from DB
ta = queryExtras< TransactionAddress, ExtraTransactionAddress >( _transactionHash,
m_transactionAddresses, x_transactionAddresses, NullTransactionAddress );
}
return std::make_pair( ta.blockHash, ta.index );
}

string BlockChain::dumpDatabase() const {
ostringstream oss;
oss << m_lastBlockHash << '\n';
Expand Down
21 changes: 8 additions & 13 deletions libethereum/BlockChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,13 @@ class BlockChain {

/// Get the transaction receipt by transaction hash. Thread-safe.
TransactionReceipt transactionReceipt( h256 const& _transactionHash ) const {
TransactionAddress ta =
queryExtras< TransactionAddress, ExtraTransactionAddress >( _transactionHash,
m_transactionAddresses, x_transactionAddresses, NullTransactionAddress );
if ( !ta )
std::pair< h256, unsigned > tl = transactionLocation( _transactionHash );

if ( !tl.first )
return bytesConstRef();
return transactionReceipt( ta.blockHash, ta.index );

// in most cases will hit cache because of transactionLocation() call above
return transactionReceipt( tl.first, tl.second );
}

/// Get a list of transaction hashes for a given block. Thread-safe.
Expand Down Expand Up @@ -311,14 +312,8 @@ class BlockChain {
return bytes();
return transaction( ta.blockHash, ta.index );
}
std::pair< h256, unsigned > transactionLocation( h256 const& _transactionHash ) const {
TransactionAddress ta =
queryExtras< TransactionAddress, ExtraTransactionAddress >( _transactionHash,
m_transactionAddresses, x_transactionAddresses, NullTransactionAddress );
if ( !ta )
return std::pair< h256, unsigned >( h256(), 0 );
return std::make_pair( ta.blockHash, ta.index );
}

std::pair< h256, unsigned > transactionLocation( h256 const& _transactionHash ) const;

/// Get a block's transaction (RLP format) for the given block hash (or the most recent mined if
/// none given) & index. Thread-safe.
Expand Down
11 changes: 1 addition & 10 deletions libethereum/Transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
#include <libdevcrypto/Common.h>
#include <libethcore/Exceptions.h>
#include <libevm/VMFace.h>
#include <libskale/POWCheckPatch.h>

using namespace std;
using namespace dev;
Expand Down Expand Up @@ -166,21 +165,13 @@ bool Transaction::hasExternalGas() const {
}

u256 Transaction::getExternalGas() const {
if ( hasExternalGas() ) {
if ( m_externalGasIsChecked && hasExternalGas() ) {
return *m_externalGas;
} else {
return u256( 0 );
}
}

u256 Transaction::gas() const {
if ( m_externalGasIsChecked && hasExternalGas() && POWCheckPatch::isEnabled() ) {
return *m_externalGas;
} else {
return TransactionBase::gas();
}
}

u256 Transaction::gasPrice() const {
if ( m_externalGasIsChecked && hasExternalGas() ) {
return 0;
Expand Down
2 changes: 0 additions & 2 deletions libethereum/Transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ class Transaction : public TransactionBase {

u256 getExternalGas() const;

u256 gas() const;

u256 gasPrice() const;

void checkOutExternalGas( u256 const& _difficulty );
Expand Down
6 changes: 4 additions & 2 deletions libweb3jsonrpc/Eth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,10 @@ void GappedTransactionIndexCache::ensureCached( BlockNumber _bn,
u256 diff = gasAfter - gasBefore;
gasBefore = gasAfter;

// ignore transactions with 0 gas usage
if ( diff == 0 )
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 )
continue;

// cache it
Expand Down
42 changes: 34 additions & 8 deletions test/unittests/libethereum/SkaleHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,8 @@ struct SkaleHostFixture : public TestOutputHelperFixture {
#define CHECK_BLOCK_BEGIN auto blockBefore = client->number()

#define REQUIRE_BLOCK_INCREASE( increase ) \
auto blockAfter = client->number(); \
BOOST_REQUIRE_EQUAL( blockAfter - blockBefore, increase )
{ auto blockAfter = client->number(); \
BOOST_REQUIRE_EQUAL( blockAfter - blockBefore, increase ); }

#define REQUIRE_BLOCK_SIZE( number, s ) \
{ \
Expand All @@ -214,18 +214,18 @@ struct SkaleHostFixture : public TestOutputHelperFixture {
#define CHECK_NONCE_BEGIN( senderAddress ) u256 nonceBefore = client->countAt( senderAddress )

#define REQUIRE_NONCE_INCREASE( senderAddress, increase ) \
u256 nonceAfter = client->countAt( senderAddress ); \
BOOST_REQUIRE_EQUAL( nonceAfter - nonceBefore, increase )
{ u256 nonceAfter = client->countAt( senderAddress ); \
BOOST_REQUIRE_EQUAL( nonceAfter - nonceBefore, increase ); }

#define CHECK_BALANCE_BEGIN( senderAddress ) u256 balanceBefore = client->balanceAt( senderAddress )

#define REQUIRE_BALANCE_DECREASE( senderAddress, decrease ) \
u256 balanceAfter = client->balanceAt( senderAddress ); \
BOOST_REQUIRE_EQUAL( balanceBefore - balanceAfter, decrease )
{ u256 balanceAfter = client->balanceAt( senderAddress ); \
BOOST_REQUIRE_EQUAL( balanceBefore - balanceAfter, decrease ); }

#define REQUIRE_BALANCE_DECREASE_GE( senderAddress, decrease ) \
u256 balanceAfter = client->balanceAt( senderAddress ); \
BOOST_REQUIRE_GE( balanceBefore - balanceAfter, decrease )
{ u256 balanceAfter = client->balanceAt( senderAddress ); \
BOOST_REQUIRE_GE( balanceBefore - balanceAfter, decrease ); }

BOOST_FIXTURE_TEST_SUITE( SkaleHostSuite, SkaleHostFixture ) //, *boost::unit_test::disabled() )

Expand Down Expand Up @@ -752,6 +752,32 @@ BOOST_DATA_TEST_CASE( transactionBalanceBad, skipInvalidTransactionsVariants, sk

REQUIRE_NONCE_INCREASE( senderAddress, 0 );
REQUIRE_BALANCE_DECREASE( senderAddress, 0 );

// step 2: check that receipt "moved" to another block after successfull re-execution of the same transaction

if(!skipInvalidTransactionsFlag){
LocalisedTransactionReceipt r1 = client->localisedTransactionReceipt(txHash);
BOOST_REQUIRE_EQUAL(r1.blockNumber(), 1);
BOOST_REQUIRE_EQUAL(r1.gasUsed(), 0);
LocalisedTransaction lt = client->localisedTransaction(txHash);
BOOST_REQUIRE_EQUAL(lt.blockNumber(), 1);
}

// make money
dev::eth::simulateMining( *client, 1, senderAddress );

stub->createBlock( ConsensusExtFace::transactions_vector{stream.out()}, utcTime(), 2U );

REQUIRE_BLOCK_SIZE( 2, 1 );
REQUIRE_BLOCK_TRANSACTION( 2, 0, txHash );
REQUIRE_NONCE_INCREASE( senderAddress, 1 );
REQUIRE_BALANCE_DECREASE_GE( senderAddress, 1 );

LocalisedTransactionReceipt r2 = client->localisedTransactionReceipt(txHash);
BOOST_REQUIRE_EQUAL(r2.blockNumber(), 2);
BOOST_REQUIRE_GE(r2.gasUsed(), 21000);
LocalisedTransaction lt = client->localisedTransaction(txHash);
BOOST_REQUIRE_EQUAL(lt.blockNumber(), 2);
}

// Transaction should be IGNORED during execution or absent if skipInvalidTransactionsFlag
Expand Down
14 changes: 14 additions & 0 deletions test/unittests/libweb3jsonrpc/jsonrpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2988,6 +2988,20 @@ BOOST_AUTO_TEST_CASE( skip_invalid_transactions ) {
BOOST_REQUIRE_EQUAL(cnt.asString(), "0x3");
cnt = fixture.rpcClient->eth_getBlockTransactionCountByHash(bh);
BOOST_REQUIRE_EQUAL(cnt.asString(), "0x3");

// send it successfully

// make money
dev::eth::simulateMining( *fixture.client, 1);

h2 = fixture.client->importTransaction( tx2 ); // invalid

dev::eth::mineTransaction(*(fixture.client), 1);

// checks:
Json::Value r2;
BOOST_REQUIRE_NO_THROW(r2 = fixture.rpcClient->eth_getTransactionReceipt(toJS(h2)));
BOOST_REQUIRE_EQUAL(r2["blockNumber"], toJS(fixture.client->number()));
#endif
}

Expand Down

0 comments on commit bc932a7

Please sign in to comment.