Skip to content

Commit

Permalink
Merge pull request #1869 from skalenetwork/feature/1719-eip1559
Browse files Browse the repository at this point in the history
Feature/1719 eip1559
  • Loading branch information
olehnikolaiev authored May 13, 2024
2 parents 55f1b96 + d7ba751 commit 006c55a
Show file tree
Hide file tree
Showing 40 changed files with 1,454 additions and 356 deletions.
445 changes: 366 additions & 79 deletions libethcore/TransactionBase.cpp

Large diffs are not rendered by default.

67 changes: 53 additions & 14 deletions libethcore/TransactionBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ enum IncludeSignature {

enum class CheckTransaction { None, Cheap, Everything };

enum TransactionType { Legacy, Type1, Type2 };

/// Encodes a transaction, ready to be exported to or freshly imported from RLP.
class TransactionBase {
public:
Expand Down Expand Up @@ -96,13 +98,13 @@ class TransactionBase {
m_type( ContractCreation ) {}

/// Constructs a transaction from the given RLP.
explicit TransactionBase(
bytesConstRef _rlp, CheckTransaction _checkSig, bool _allowInvalid = false );
explicit TransactionBase( bytesConstRef _rlp, CheckTransaction _checkSig,
bool _allowInvalid = false, bool _eip1559Enabled = false );

/// Constructs a transaction from the given RLP.
explicit TransactionBase(
bytes const& _rlp, CheckTransaction _checkSig, bool _allowInvalid = false )
: TransactionBase( &_rlp, _checkSig, _allowInvalid ) {}
explicit TransactionBase( bytes const& _rlp, CheckTransaction _checkSig,
bool _allowInvalid = false, bool _eip1559Enabled = false )
: TransactionBase( &_rlp, _checkSig, _allowInvalid, _eip1559Enabled ) {}

TransactionBase( TransactionBase const& ) = default;

Expand Down Expand Up @@ -145,17 +147,14 @@ class TransactionBase {
/// @returns true if transaction is contract-creation.
bool isCreation() const { return m_type == ContractCreation; }

/// Serialises this transaction to an RLPStream.
/// @throws TransactionIsUnsigned if including signature was requested but it was not
/// initialized
void streamRLP(
RLPStream& _s, IncludeSignature _sig = WithSignature, bool _forEip155hash = false ) const;

/// @returns the RLP serialisation of this transaction.
bytes rlp( IncludeSignature _sig = WithSignature ) const {
bytes toBytes( IncludeSignature _sig = WithSignature, bool _forEip155hash = false ) const {
RLPStream s;
streamRLP( s, _sig );
return s.out();
streamRLP( s, _sig, _forEip155hash );
bytes output = s.out();
if ( m_txType != TransactionType::Legacy )
output.insert( output.begin(), m_txType );
return output;
}

/// @returns the SHA3 hash of the RLP serialisation of this transaction.
Expand Down Expand Up @@ -249,6 +248,14 @@ class TransactionBase {

bool isInvalid() const { return m_type == Type::Invalid; }

TransactionType txType() const { return m_txType; }

std::vector< bytes > accessList() const { return m_accessList; }

u256 maxPriorityFeePerGas() const { return m_maxPriorityFeePerGas; }

u256 maxFeePerGas() const { return m_maxFeePerGas; }

/// Get the fee associated for a transaction with the given data.
static int64_t baseGasRequired(
bool _contractCreation, bytesConstRef _data, EVMSchedule const& _es );
Expand Down Expand Up @@ -285,9 +292,39 @@ class TransactionBase {
bytes m_data; ///< The data associated with the transaction, or the initialiser if it's a
///< creation transaction.
bytes m_rawData;
std::vector< bytes > m_accessList; ///< The access list. see more
///< https://eips.ethereum.org/EIPS/eip-2930. Not valid for
///< legacy txns
u256 m_maxPriorityFeePerGas; ///< The maximum priority fee per gas. Only valid for type2 txns
u256 m_maxFeePerGas; ///< The maximum fee per gas. Only valid for type2 txns

TransactionType m_txType = TransactionType::Legacy;

Counter< TransactionBase > c;

private:
/// Serialises this transaction to an RLPStream.
/// @throws TransactionIsUnsigned if including signature was requested but it was not
/// initialized
void streamRLP(
RLPStream& _s, IncludeSignature _sig = WithSignature, bool _forEip155hash = false ) const;

static TransactionType getTransactionType( bytesConstRef _rlp );

/// Constructs a transaction from the given RLP and transaction type.
void fillFromBytesByType( bytesConstRef _rlpData, CheckTransaction _checkSig,
bool _allowInvalid, TransactionType _type );
void fillFromBytesLegacy(
bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid );
void fillFromBytesType1(
bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid );
void fillFromBytesType2(
bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid );

void streamLegacyTransaction( RLPStream& _s, IncludeSignature _sig, bool _forEip155hash ) const;
void streamType1Transaction( RLPStream& _s, IncludeSignature _sig ) const;
void streamType2Transaction( RLPStream& _s, IncludeSignature _sig ) const;

public:
mutable int64_t verifiedOn = -1; // on which block it was imported

Expand Down Expand Up @@ -321,5 +358,7 @@ inline std::ostream& operator<<( std::ostream& _out, TransactionBase const& _t )
return _out;
}

extern bytesConstRef bytesRefFromTransactionRlp( const RLP& _rlp );

} // namespace eth
} // namespace dev
3 changes: 2 additions & 1 deletion libethereum/BasicGasPricer.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ class BasicGasPricer : public GasPricer {
}

u256 ask( Block const& ) const override { return m_weiPerRef * m_refsPerBlock / m_gasPerBlock; }
u256 bid( TransactionPriority _p = TransactionPriority::Medium ) const override {
u256 bid( unsigned = dev::eth::LatestBlock,
TransactionPriority _p = TransactionPriority::Medium ) const override {
return m_octiles[( int ) _p] > 0 ? m_octiles[( int ) _p] :
( m_weiPerRef * m_refsPerBlock / m_gasPerBlock );
}
Expand Down
13 changes: 9 additions & 4 deletions libethereum/Block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1017,11 +1017,16 @@ void Block::commitToSeal(
receipt( i ).streamRLP( receiptrlp );
receiptsMap.insert( std::make_pair( k.out(), receiptrlp.out() ) );

RLPStream txrlp;
m_transactions[i].streamRLP( txrlp );
transactionsMap.insert( std::make_pair( k.out(), txrlp.out() ) );
dev::bytes txOutput = m_transactions[i].toBytes();
if ( EIP1559TransactionsPatch::isEnabledInWorkingBlock() &&
m_transactions[i].txType() != dev::eth::TransactionType::Legacy ) {
RLPStream s;
s.append( txOutput );
txOutput = s.out();
}
transactionsMap.insert( std::make_pair( k.out(), txOutput ) );

txs.appendRaw( txrlp.out() );
txs.appendRaw( txOutput );
}

txs.swapOut( m_currentTxs );
Expand Down
18 changes: 13 additions & 5 deletions libethereum/BlockChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ using skale::BaseState;
using skale::State;
using namespace skale::error;

extern bytesConstRef bytesRefFromTransactionRlp( const RLP& _rlp );

#define ETH_TIMED_IMPORTS 1

namespace {
Expand Down Expand Up @@ -761,8 +763,10 @@ size_t BlockChain::prepareDbDataAndReturnSize( VerifiedBlockRef const& _block,
for ( RLP::iterator it = txns_rlp.begin(); it != txns_rlp.end(); ++it ) {
MICROPROFILE_SCOPEI( "insertBlockAndExtras", "for2", MP_HONEYDEW );

extrasWriteBatch.insert( toSlice( sha3( ( *it ).data() ), ExtraTransactionAddress ),
auto txBytes = bytesRefFromTransactionRlp( *it );
extrasWriteBatch.insert( toSlice( sha3( txBytes ), ExtraTransactionAddress ),
( db::Slice ) dev::ref( ta.rlp() ) );

++ta.index;
}
}
Expand Down Expand Up @@ -1730,11 +1734,15 @@ VerifiedBlockRef BlockChain::verifyBlock( bytesConstRef _block,
( ImportRequirements::TransactionBasic | ImportRequirements::TransactionSignatures ) ) {
MICROPROFILE_SCOPEI( "BlockChain", "check txns", MP_ROSYBROWN );
for ( RLP const& tr : r[1] ) {
bytesConstRef d = tr.data();
bytesConstRef d = bytesRefFromTransactionRlp( tr );
try {
Transaction t( d, ( _ir & ImportRequirements::TransactionSignatures ) ?
CheckTransaction::Everything :
CheckTransaction::None );
Transaction t( d,
( _ir & ImportRequirements::TransactionSignatures ) ?
CheckTransaction::Everything :
CheckTransaction::None,
false,
EIP1559TransactionsPatch::isEnabledWhen(
this->info( numberHash( h.number() - 1 ) ).timestamp() ) );
Ethash::verifyTransaction( chainParams(), _ir, t,
this->info( numberHash( h.number() - 1 ) ).timestamp(), h,
0 ); // the gasUsed vs
Expand Down
8 changes: 4 additions & 4 deletions libethereum/BlockChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,8 @@ class BlockChain {
auto b = block( _hash );
RLP rlp( b );
h256s ret;
for ( auto t : rlp[1] )
ret.push_back( sha3( t.data() ) );
for ( auto d : rlp[1] )
ret.push_back( sha3( bytesRefFromTransactionRlp( d ) ) );
return ret;
}
TransactionHashes transactionHashes() const { return transactionHashes( currentHash() ); }
Expand Down Expand Up @@ -319,7 +319,7 @@ class BlockChain {
/// none given) & index. Thread-safe.
bytes transaction( h256 const& _blockHash, unsigned _i ) const {
bytes b = block( _blockHash );
return RLP( b )[1][_i].data().toBytes();
return bytesRefFromTransactionRlp( RLP( b )[1][_i] ).toBytes();
}
bytes transaction( unsigned _i ) const { return transaction( currentHash(), _i ); }

Expand All @@ -328,7 +328,7 @@ class BlockChain {
bytes b = block( _blockHash );
std::vector< bytes > ret;
for ( auto const& i : RLP( b )[1] )
ret.push_back( i.data().toBytes() );
ret.push_back( bytesRefFromTransactionRlp( i ).toBytes() );
return ret;
}
std::vector< bytes > transactions() const { return transactions( currentHash() ); }
Expand Down
4 changes: 3 additions & 1 deletion libethereum/Client.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,9 @@ class Client : public ClientBase, protected Worker {
/// Get the remaining gas limit in this block.
u256 gasLimitRemaining() const override { return m_postSeal.gasLimitRemaining(); }
/// Get the gas bid price
u256 gasBidPrice() const override { return m_gp->bid(); }
u256 gasBidPrice( unsigned _blockNumber = dev::eth::LatestBlock ) const override {
return m_gp->bid( _blockNumber );
}

// [PRIVATE API - only relevant for base clients, not available in general]
/// Get the block.
Expand Down
29 changes: 21 additions & 8 deletions libethereum/ClientBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,10 @@ BlockDetails ClientBase::blockDetails( h256 _hash ) const {

Transaction ClientBase::transaction( h256 _transactionHash ) const {
// allow invalid!
return Transaction( bc().transaction( _transactionHash ), CheckTransaction::Cheap, true );
auto tl = bc().transactionLocation( _transactionHash );
return Transaction( bc().transaction( _transactionHash ), CheckTransaction::Cheap, true,
EIP1559TransactionsPatch::isEnabledWhen(
blockInfo( numberFromHash( tl.first ) - 1 ).timestamp() ) );
}

LocalisedTransaction ClientBase::localisedTransaction( h256 const& _transactionHash ) const {
Expand All @@ -393,15 +396,18 @@ Transaction ClientBase::transaction( h256 _blockHash, unsigned _i ) const {
RLP b( bl );
if ( _i < b[1].itemCount() )
// allow invalid
return Transaction( b[1][_i].data(), CheckTransaction::Cheap, true );
return Transaction( b[1][_i].data(), CheckTransaction::Cheap, true,
EIP1559TransactionsPatch::isEnabledWhen(
blockInfo( numberFromHash( _blockHash ) - 1 ).timestamp() ) );
else
return Transaction();
}

LocalisedTransaction ClientBase::localisedTransaction( h256 const& _blockHash, unsigned _i ) const {
// allow invalid
Transaction t =
Transaction( bc().transaction( _blockHash, _i ), CheckTransaction::Cheap, true );
Transaction t = Transaction( bc().transaction( _blockHash, _i ), CheckTransaction::Cheap, true,
EIP1559TransactionsPatch::isEnabledWhen(
blockInfo( numberFromHash( _blockHash ) - 1 ).timestamp() ) );
return LocalisedTransaction( t, _blockHash, _i, numberFromHash( _blockHash ) );
}

Expand All @@ -414,7 +420,9 @@ LocalisedTransactionReceipt ClientBase::localisedTransactionReceipt(
std::pair< h256, unsigned > tl = bc().transactionLocation( _transactionHash );
// allow invalid
Transaction t =
Transaction( bc().transaction( tl.first, tl.second ), CheckTransaction::Cheap, true );
Transaction( bc().transaction( tl.first, tl.second ), CheckTransaction::Cheap, true,
EIP1559TransactionsPatch::isEnabledWhen(
blockInfo( numberFromHash( tl.first ) - 1 ).timestamp() ) );
TransactionReceipt tr = bc().transactionReceipt( tl.first, tl.second );
u256 gasUsed = tr.cumulativeGasUsed();
if ( tl.second > 0 )
Expand All @@ -433,7 +441,8 @@ LocalisedTransactionReceipt ClientBase::localisedTransactionReceipt(
//
return LocalisedTransactionReceipt( tr, t.sha3(), tl.first, numberFromHash( tl.first ),
tl.second, t.isInvalid() ? dev::Address( 0 ) : t.from(),
t.isInvalid() ? dev::Address( 0 ) : t.to(), gasUsed, contractAddress );
t.isInvalid() ? dev::Address( 0 ) : t.to(), gasUsed, contractAddress, int( t.txType() ),
t.isInvalid() ? 0 : t.gasPrice() );
}

pair< h256, unsigned > ClientBase::transactionLocation( h256 const& _transactionHash ) const {
Expand All @@ -444,8 +453,12 @@ Transactions ClientBase::transactions( h256 _blockHash ) const {
auto bl = bc().block( _blockHash );
RLP b( bl );
Transactions res;
for ( unsigned i = 0; i < b[1].itemCount(); i++ )
res.emplace_back( b[1][i].data(), CheckTransaction::Cheap, true );
for ( unsigned i = 0; i < b[1].itemCount(); i++ ) {
auto txRlp = b[1][i];
res.emplace_back( bytesRefFromTransactionRlp( txRlp ), CheckTransaction::Cheap, true,
EIP1559TransactionsPatch::isEnabledWhen(
blockInfo( numberFromHash( _blockHash ) - 1 ).timestamp() ) );
}
return res;
}

Expand Down
2 changes: 1 addition & 1 deletion libethereum/ClientBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ class ClientBase : public Interface {
ImportResult injectBlock( bytes const& _block ) override;

u256 gasLimitRemaining() const override;
u256 gasBidPrice() const override { return DefaultGasPrice; }
u256 gasBidPrice( unsigned = dev::eth::LatestBlock ) const override { return DefaultGasPrice; }

/// Get the block author
Address author() const override;
Expand Down
8 changes: 6 additions & 2 deletions libethereum/GasPricer.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ class GasPricer {
virtual ~GasPricer() = default;

virtual u256 ask( Block const& ) const = 0;
virtual u256 bid( TransactionPriority _p = TransactionPriority::Medium ) const = 0;
virtual u256 bid( unsigned _blockNumber = dev::eth::LatestBlock,
TransactionPriority _p = TransactionPriority::Medium ) const = 0;

virtual void update( BlockChain const& ) {}
};
Expand All @@ -56,7 +57,10 @@ class TrivialGasPricer : public GasPricer {

u256 ask() const { return m_ask; }
u256 ask( Block const& ) const override { return m_ask; }
u256 bid( TransactionPriority = TransactionPriority::Medium ) const override { return m_bid; }
u256 bid( unsigned = dev::eth::LatestBlock,
TransactionPriority = TransactionPriority::Medium ) const override {
return m_bid;
}

private:
u256 m_ask = DefaultGasPrice;
Expand Down
2 changes: 1 addition & 1 deletion libethereum/Interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ class Interface {
/// Get the remaining gas limit in this block.
virtual u256 gasLimitRemaining() const = 0;
// Get the gas bidding price
virtual u256 gasBidPrice() const = 0;
virtual u256 gasBidPrice( unsigned _blockNumber = dev::eth::LatestBlock ) const = 0;

/// Get some information on the block queue.
virtual SyncStatus syncStatus() const = 0;
Expand Down
4 changes: 4 additions & 0 deletions libethereum/SchainPatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ SchainPatchEnum getEnumForPatchName( const std::string& _patchName ) {
return SchainPatchEnum::StorageDestructionPatch;
else if ( _patchName == "SkipInvalidTransactionsPatch" )
return SchainPatchEnum::SkipInvalidTransactionsPatch;
else if ( _patchName == "EIP1559TransactionsPatch" )
return SchainPatchEnum::EIP1559TransactionsPatch;
else
throw std::out_of_range( _patchName );
}
Expand Down Expand Up @@ -56,6 +58,8 @@ std::string getPatchNameForEnum( SchainPatchEnum _enumValue ) {
return "SkipInvalidTransactionsPatch";
case SchainPatchEnum::SelfdestructStorageLimitPatch:
return "SelfdestructStorageLimitPatch";
case SchainPatchEnum::EIP1559TransactionsPatch:
return "EIP1559TransactionsPatch";
default:
throw std::out_of_range(
"UnknownPatch #" + std::to_string( static_cast< size_t >( _enumValue ) ) );
Expand Down
5 changes: 5 additions & 0 deletions libethereum/SchainPatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,9 @@ DEFINE_AMNESIC_PATCH( StorageDestructionPatch );
*/
DEFINE_SIMPLE_PATCH( SelfdestructStorageLimitPatch );

/*
* Enable restriction on contract storage size, when it's doing selfdestruct
*/
DEFINE_SIMPLE_PATCH( EIP1559TransactionsPatch );

#endif // SCHAINPATCH_H
1 change: 1 addition & 0 deletions libethereum/SchainPatchEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ enum class SchainPatchEnum {
StorageDestructionPatch,
SkipInvalidTransactionsPatch,
SelfdestructStorageLimitPatch,
EIP1559TransactionsPatch,
PatchesCount
};

Expand Down
Loading

0 comments on commit 006c55a

Please sign in to comment.