From 5a6f7d0077ad803543342cfbdbbc62d81a1e5381 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 19 Mar 2024 19:23:46 +0000 Subject: [PATCH 01/53] #1719 add support for type1 and type2 txns --- libethcore/TransactionBase.cpp | 380 +++++++++++++++++----- libethcore/TransactionBase.h | 32 +- libethereum/Block.cpp | 11 +- libethereum/BlockChain.cpp | 11 +- libethereum/BlockChain.h | 20 +- libethereum/ClientBase.cpp | 12 +- test/unittests/libweb3jsonrpc/jsonrpc.cpp | 53 +++ 7 files changed, 431 insertions(+), 88 deletions(-) diff --git a/libethcore/TransactionBase.cpp b/libethcore/TransactionBase.cpp index 198fabab3..f0eaff71b 100644 --- a/libethcore/TransactionBase.cpp +++ b/libethcore/TransactionBase.cpp @@ -49,79 +49,254 @@ TransactionBase::TransactionBase( TransactionSkeleton const& _ts, Secret const& sign( _s ); } -TransactionBase::TransactionBase( +TransactionBase TransactionBase::makeLegacyTransaction( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ) { - MICROPROFILE_SCOPEI( "TransactionBase", "ctor", MP_GOLD2 ); + RLP const rlp( _rlpData ); try { - RLP const rlp( _rlpData ); - try { - if ( !rlp.isList() ) - BOOST_THROW_EXCEPTION( InvalidTransactionFormat() - << errinfo_comment( "transaction RLP must be a list" ) ); - - m_nonce = rlp[0].toInt< u256 >(); - m_gasPrice = rlp[1].toInt< u256 >(); - m_gas = rlp[2].toInt< u256 >(); - if ( !rlp[3].isData() ) - BOOST_THROW_EXCEPTION( InvalidTransactionFormat() - << errinfo_comment( "recepient RLP must be a byte array" ) ); - m_type = rlp[3].isEmpty() ? ContractCreation : MessageCall; - m_receiveAddress = - rlp[3].isEmpty() ? Address() : rlp[3].toHash< Address >( RLP::VeryStrict ); - m_value = rlp[4].toInt< u256 >(); - - if ( !rlp[5].isData() ) - BOOST_THROW_EXCEPTION( InvalidTransactionFormat() << errinfo_comment( - "transaction data RLP must be an array" ) ); - - m_data = rlp[5].toBytes(); - - u256 const v = rlp[6].toInt< u256 >(); - h256 const r = rlp[7].toInt< u256 >(); - h256 const s = rlp[8].toInt< u256 >(); - - if ( isZeroSignature( r, s ) ) { - m_chainId = static_cast< uint64_t >( v ); - m_vrs = SignatureStruct{ r, s, 0 }; - } else { - if ( v > 36 ) { - auto const chainId = ( v - 35 ) / 2; - if ( chainId > std::numeric_limits< uint64_t >::max() ) - BOOST_THROW_EXCEPTION( InvalidSignature() ); - m_chainId = static_cast< uint64_t >( chainId ); - } else if ( v != 27 && v != 28 ) + if ( !rlp.isList() ) + BOOST_THROW_EXCEPTION( + InvalidTransactionFormat() << errinfo_comment( "transaction RLP must be a list" ) ); + + m_nonce = rlp[0].toInt< u256 >(); + m_gasPrice = rlp[1].toInt< u256 >(); + m_gas = rlp[2].toInt< u256 >(); + if ( !rlp[3].isData() ) + BOOST_THROW_EXCEPTION( InvalidTransactionFormat() + << errinfo_comment( "recipient RLP must be a byte array" ) ); + m_type = rlp[3].isEmpty() ? ContractCreation : MessageCall; + m_receiveAddress = + rlp[3].isEmpty() ? Address() : rlp[3].toHash< Address >( RLP::VeryStrict ); + m_value = rlp[4].toInt< u256 >(); + + if ( !rlp[5].isData() ) + BOOST_THROW_EXCEPTION( InvalidTransactionFormat() + << errinfo_comment( "transaction data RLP must be an array" ) ); + + m_data = rlp[5].toBytes(); + + u256 const v = rlp[6].toInt< u256 >(); + h256 const r = rlp[7].toInt< u256 >(); + h256 const s = rlp[8].toInt< u256 >(); + + if ( isZeroSignature( r, s ) ) { + m_chainId = static_cast< uint64_t >( v ); + m_vrs = SignatureStruct{ r, s, 0 }; + } else { + if ( v > 36 ) { + auto const chainId = ( v - 35 ) / 2; + if ( chainId > std::numeric_limits< uint64_t >::max() ) BOOST_THROW_EXCEPTION( InvalidSignature() ); - // else leave m_chainId as is (unitialized) + m_chainId = static_cast< uint64_t >( chainId ); + } else if ( v != 27 && v != 28 ) + BOOST_THROW_EXCEPTION( InvalidSignature() ); + // else leave m_chainId as is (unitialized) - auto const recoveryID = m_chainId.has_value() ? - _byte_{ v - ( u256{ *m_chainId } * 2 + 35 ) } : - _byte_{ v - 27 }; - m_vrs = SignatureStruct{ r, s, recoveryID }; + auto const recoveryID = m_chainId.has_value() ? + _byte_{ v - ( u256{ *m_chainId } * 2 + 35 ) } : + _byte_{ v - 27 }; + m_vrs = SignatureStruct{ r, s, recoveryID }; - if ( _checkSig >= CheckTransaction::Cheap && !m_vrs->isValid() ) - BOOST_THROW_EXCEPTION( InvalidSignature() ); - } - - if ( _checkSig == CheckTransaction::Everything ) - m_sender = sender(); - - if ( rlp.itemCount() > 9 ) - BOOST_THROW_EXCEPTION( InvalidTransactionFormat() << errinfo_comment( - "too many fields in the transaction RLP" ) ); - // XXX Strange "catch"-s %) - - } catch ( Exception& _e ) { - _e << errinfo_name( - "invalid transaction format: " + toString( rlp ) + " RLP: " + toHex( rlp.data() ) ); - m_type = Type::Invalid; - m_rawData = _rlpData.toBytes(); - - if ( !_allowInvalid ) - throw; - else { - cwarn << _e.what(); - } + if ( _checkSig >= CheckTransaction::Cheap && !m_vrs->isValid() ) + BOOST_THROW_EXCEPTION( InvalidSignature() ); + } + + if ( _checkSig == CheckTransaction::Everything ) + m_sender = sender(); + + m_txType = TransactionType::Legacy; + + if ( rlp.itemCount() > 9 ) + BOOST_THROW_EXCEPTION( InvalidTransactionFormat() + << errinfo_comment( "too many fields in the transaction RLP" ) ); + // XXX Strange "catch"-s %) + + TransactionBase t( *this ); + return t; + } catch ( Exception& _e ) { + _e << errinfo_name( + "invalid transaction format: " + toString( rlp ) + " RLP: " + toHex( rlp.data() ) ); + m_type = Type::Invalid; + m_rawData = _rlpData.toBytes(); + + if ( !_allowInvalid ) + throw; + else { + cwarn << _e.what(); + TransactionBase t( *this ); + return t; + } + } +} + +TransactionBase TransactionBase::makeType1Transaction( + bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ) { + bytes croppedRlp( _rlpData.begin() + 1, _rlpData.end() ); + RLP const rlp( croppedRlp ); + try { + if ( !rlp.isList() ) + BOOST_THROW_EXCEPTION( + InvalidTransactionFormat() << errinfo_comment( "transaction RLP must be a list" ) ); + + m_chainId = rlp[0].toInt< u256 >(); + m_nonce = rlp[1].toInt< u256 >(); + m_gasPrice = rlp[2].toInt< u256 >(); + m_gas = rlp[3].toInt< u256 >(); + + if ( !rlp[4].isData() ) + BOOST_THROW_EXCEPTION( InvalidTransactionFormat() + << errinfo_comment( "recipient RLP must be a byte array" ) ); + m_type = rlp[4].isEmpty() ? ContractCreation : MessageCall; + m_receiveAddress = + rlp[4].isEmpty() ? Address() : rlp[4].toHash< Address >( RLP::VeryStrict ); + m_value = rlp[5].toInt< u256 >(); + + if ( !rlp[6].isData() ) + BOOST_THROW_EXCEPTION( InvalidTransactionFormat() + << errinfo_comment( "transaction data RLP must be an array" ) ); + + m_data = rlp[6].toBytes(); + + m_accessList = rlp[7].toList(); + + bool const yParity = rlp[8].toInt< uint8_t >(); + h256 const r = rlp[9].toInt< u256 >(); + h256 const s = rlp[10].toInt< u256 >(); + + m_vrs = SignatureStruct{ r, s, yParity }; + + if ( _checkSig >= CheckTransaction::Cheap && !m_vrs->isValid() ) + BOOST_THROW_EXCEPTION( InvalidSignature() ); + + if ( _checkSig == CheckTransaction::Everything ) + m_sender = sender(); + + m_txType = TransactionType::Type1; + + if ( rlp.itemCount() > 11 ) + BOOST_THROW_EXCEPTION( InvalidTransactionFormat() + << errinfo_comment( "too many fields in the transaction RLP" ) ); + + TransactionBase t( *this ); + return t; + } catch ( Exception& _e ) { + _e << errinfo_name( + "invalid transaction format: " + toString( rlp ) + " RLP: " + toHex( rlp.data() ) ); + m_type = Type::Invalid; + m_rawData = _rlpData.toBytes(); + + if ( !_allowInvalid ) + throw; + else { + cwarn << _e.what(); + TransactionBase t( *this ); + return t; + } + } +} + +TransactionBase TransactionBase::makeType2Transaction( + bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ) { + bytes croppedRlp( _rlpData.begin() + 1, _rlpData.end() ); + RLP const rlp( croppedRlp ); + try { + if ( !rlp.isList() ) + BOOST_THROW_EXCEPTION( + InvalidTransactionFormat() << errinfo_comment( "transaction RLP must be a list" ) ); + + m_chainId = rlp[0].toInt< u256 >(); + m_nonce = rlp[1].toInt< u256 >(); + m_maxPriorityFeePerGas = rlp[2].toInt< u256 >(); + m_maxFeePerGas = rlp[3].toInt< u256 >(); + m_gas = rlp[4].toInt< u256 >(); + + if ( !rlp[5].isData() ) + BOOST_THROW_EXCEPTION( InvalidTransactionFormat() + << errinfo_comment( "recipient RLP must be a byte array" ) ); + m_type = rlp[5].isEmpty() ? ContractCreation : MessageCall; + m_receiveAddress = + rlp[5].isEmpty() ? Address() : rlp[5].toHash< Address >( RLP::VeryStrict ); + m_value = rlp[6].toInt< u256 >(); + + if ( !rlp[7].isData() ) + BOOST_THROW_EXCEPTION( InvalidTransactionFormat() + << errinfo_comment( "transaction data RLP must be an array" ) ); + + m_data = rlp[7].toBytes(); + + m_accessList = rlp[8].toList(); + + bool const yParity = rlp[9].toInt< uint8_t >(); + h256 const r = rlp[10].toInt< u256 >(); + h256 const s = rlp[11].toInt< u256 >(); + + m_vrs = SignatureStruct{ r, s, yParity }; + + if ( _checkSig >= CheckTransaction::Cheap && !m_vrs->isValid() ) + BOOST_THROW_EXCEPTION( InvalidSignature() ); + + if ( _checkSig == CheckTransaction::Everything ) + m_sender = sender(); + + m_txType = TransactionType::Type2; + + if ( rlp.itemCount() > 12 ) + BOOST_THROW_EXCEPTION( InvalidTransactionFormat() + << errinfo_comment( "too many fields in the transaction RLP" ) ); + + TransactionBase t( *this ); + return t; + } catch ( Exception& _e ) { + _e << errinfo_name( + "invalid transaction format: " + toString( rlp ) + " RLP: " + toHex( rlp.data() ) ); + m_type = Type::Invalid; + m_rawData = _rlpData.toBytes(); + + if ( !_allowInvalid ) + throw; + else { + cwarn << _e.what(); + TransactionBase t( *this ); + return t; } + } +} + +TransactionBase::TransactionBase( + bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid, TransactionType type ) { + switch ( type ) { + case TransactionType::Legacy: + *this = makeLegacyTransaction( _rlpData, _checkSig, _allowInvalid ); + break; + case TransactionType::Type1: + *this = makeType1Transaction( _rlpData, _checkSig, _allowInvalid ); + break; + case TransactionType::Type2: + *this = makeType2Transaction( _rlpData, _checkSig, _allowInvalid ); + break; + default: + BOOST_THROW_EXCEPTION( + InvalidTransactionFormat() << errinfo_comment( + "transaction format doesn't correspond to any of the supported formats" ) ); + } +} + +TransactionType TransactionBase::getTransactionType( bytesConstRef _rlp ) { + if ( _rlp.size() < 1 ) { + BOOST_THROW_EXCEPTION( + InvalidTransactionFormat() << errinfo_comment( + "transaction format doesn't correspond to any of the supported formats" ) ); + } + if ( _rlp[0] > 2 ) + return TransactionType::Legacy; + return TransactionType( _rlp[0] ); +} + +TransactionBase::TransactionBase( + bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ) { + MICROPROFILE_SCOPEI( "TransactionBase", "ctor", MP_GOLD2 ); + try { + TransactionType txnType = getTransactionType( _rlpData ); + *this = TransactionBase( _rlpData, _checkSig, _allowInvalid, txnType ); } catch ( ... ) { m_type = Type::Invalid; RLPStream s; @@ -176,15 +351,8 @@ void TransactionBase::sign( Secret const& _priv ) { m_vrs = sigStruct; } -void TransactionBase::streamRLP( RLPStream& _s, IncludeSignature _sig, bool _forEip155hash ) const { - if ( isInvalid() ) { - _s.appendRaw( m_rawData ); - return; - } - - if ( m_type == NullTransaction ) - return; - +void TransactionBase::streamLegacyTransaction( + RLPStream& _s, IncludeSignature _sig, bool _forEip155hash ) const { _s.appendList( ( _sig || _forEip155hash ? 3 : 0 ) + 6 ); _s << m_nonce << m_gasPrice << m_gas; if ( m_type == MessageCall ) @@ -208,6 +376,60 @@ void TransactionBase::streamRLP( RLPStream& _s, IncludeSignature _sig, bool _for _s << *m_chainId << 0 << 0; } +void TransactionBase::streamType1Transaction( RLPStream& _s, IncludeSignature _sig ) const { + _s.appendList( ( _sig ? 3 : 0 ) + 8 ); + _s << *m_chainId << m_nonce << m_gasPrice << m_gas; + if ( m_type == MessageCall ) + _s << m_receiveAddress; + else + _s << ""; + _s << m_value << m_data; + + _s << m_accessList; + + if ( _sig ) + _s << ( u256 ) m_vrs->v << ( u256 ) m_vrs->r << ( u256 ) m_vrs->s; +} + +void TransactionBase::streamType2Transaction( RLPStream& _s, IncludeSignature _sig ) const { + _s.appendList( ( _sig ? 3 : 0 ) + 9 ); + _s << *m_chainId << m_nonce << m_maxPriorityFeePerGas << m_maxFeePerGas << m_gas; + if ( m_type == MessageCall ) + _s << m_receiveAddress; + else + _s << ""; + _s << m_value << m_data; + + _s << m_accessList; + + if ( _sig ) + _s << ( u256 ) m_vrs->v << ( u256 ) m_vrs->r << ( u256 ) m_vrs->s; +} + +void TransactionBase::streamRLP( RLPStream& _s, IncludeSignature _sig, bool _forEip155hash ) const { + if ( isInvalid() ) { + _s.appendRaw( m_rawData ); + return; + } + + if ( m_type == NullTransaction ) + return; + + switch ( m_txType ) { + case TransactionType::Legacy: + streamLegacyTransaction( _s, _sig, _forEip155hash ); + break; + case TransactionType::Type1: + streamType1Transaction( _s, _sig ); + break; + case TransactionType::Type2: + streamType2Transaction( _s, _sig ); + break; + default: + break; + } +} + static const u256 c_secp256k1n( "115792089237316195423570985008687907852837564279074904382605163141518161494337" ); @@ -250,7 +472,11 @@ h256 TransactionBase::sha3( IncludeSignature _sig ) const { RLPStream s; streamRLP( s, _sig, !isInvalid() && isReplayProtected() && _sig == WithoutSignature ); - auto ret = dev::sha3( s.out() ); + dev::bytes input = s.out(); + if ( m_txType != TransactionType::Legacy ) + input.insert( input.begin(), m_txType ); + + auto ret = dev::sha3( input ); if ( _sig == WithSignature ) m_hashWith = ret; return ret; diff --git a/libethcore/TransactionBase.h b/libethcore/TransactionBase.h index 2b93c6bd2..d3773166d 100644 --- a/libethcore/TransactionBase.h +++ b/libethcore/TransactionBase.h @@ -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: @@ -104,6 +106,10 @@ class TransactionBase { bytes const& _rlp, CheckTransaction _checkSig, bool _allowInvalid = false ) : TransactionBase( &_rlp, _checkSig, _allowInvalid ) {} + /// Constructs a transaction from the given RLP and transaction type. + TransactionBase( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid, + TransactionType type ); + TransactionBase( TransactionBase const& ) = default; /// Checks equality of transactions. @@ -155,7 +161,10 @@ class TransactionBase { bytes rlp( IncludeSignature _sig = WithSignature ) const { RLPStream s; streamRLP( s, _sig ); - return s.out(); + 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. @@ -249,6 +258,8 @@ class TransactionBase { bool isInvalid() const { return m_type == Type::Invalid; } + TransactionType txType() const { return m_txType; } + /// Get the fee associated for a transaction with the given data. static int64_t baseGasRequired( bool _contractCreation, bytesConstRef _data, EVMSchedule const& _es ); @@ -285,9 +296,28 @@ class TransactionBase { bytes m_data; ///< The data associated with the transaction, or the initialiser if it's a ///< creation transaction. bytes m_rawData; + RLPs 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: + static TransactionType getTransactionType( bytesConstRef _rlp ); + TransactionBase makeLegacyTransaction( + bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ); + TransactionBase makeType1Transaction( + bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ); + TransactionBase makeType2Transaction( + 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 diff --git a/libethereum/Block.cpp b/libethereum/Block.cpp index d98705d88..05f0e77b3 100644 --- a/libethereum/Block.cpp +++ b/libethereum/Block.cpp @@ -975,9 +975,16 @@ void Block::commitToSeal( RLPStream txrlp; m_transactions[i].streamRLP( txrlp ); - transactionsMap.insert( std::make_pair( k.out(), txrlp.out() ) ); + dev::bytes txOutput = txrlp.out(); + if ( m_transactions[i].txType() != dev::eth::TransactionType::Legacy ) { + txOutput.insert( txOutput.begin(), m_transactions[i].txType() ); + 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 ); diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 677d19b48..f67c3be6e 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -777,8 +777,15 @@ 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 ), - ( db::Slice ) dev::ref( ta.rlp() ) ); + if ( RLP( *it ).isList() ) + // means Legacy transaction + extrasWriteBatch.insert( toSlice( sha3( ( *it ).data() ), ExtraTransactionAddress ), + ( db::Slice ) dev::ref( ta.rlp() ) ); + else { + auto payload = ( *it ).payload(); + extrasWriteBatch.insert( toSlice( sha3( payload ), ExtraTransactionAddress ), + ( db::Slice ) dev::ref( ta.rlp() ) ); + } ++ta.index; } } diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index 593475fb1..2cfe2658f 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -231,8 +231,13 @@ 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] ) { + if ( d.isList() ) + // means Legacy transaction + ret.push_back( sha3( d.data() ) ); + else + ret.push_back( sha3( d.payload() ) ); + } return ret; } TransactionHashes transactionHashes() const { return transactionHashes( currentHash() ); } @@ -319,7 +324,10 @@ 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(); + if ( RLP( b )[1][_i].isList() ) + // means Legacy transaction + return RLP( b )[1][_i].data().toBytes(); + return RLP( b )[1][_i].payload().toBytes(); } bytes transaction( unsigned _i ) const { return transaction( currentHash(), _i ); } @@ -328,7 +336,11 @@ class BlockChain { bytes b = block( _blockHash ); std::vector< bytes > ret; for ( auto const& i : RLP( b )[1] ) - ret.push_back( i.data().toBytes() ); + if ( i.isList() ) + // means Legacy transaction + ret.push_back( i.data().toBytes() ); + else + ret.push_back( i.payload().toBytes() ); return ret; } std::vector< bytes > transactions() const { return transactions( currentHash() ); } diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index 6b6d530b4..b4a4a6592 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -446,8 +446,16 @@ 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 tx = b[1][i].data().toBytes(); + if ( RLP( tx ).isList() ) + // means Legacy transaction + res.emplace_back( tx, CheckTransaction::Cheap, true ); + else { + tx = RLP( tx ).payload().toBytes(); + res.emplace_back( tx, CheckTransaction::Cheap, true ); + } + } return res; } diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index 041b8d6b0..fb9dfcb32 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -2604,6 +2604,59 @@ BOOST_AUTO_TEST_CASE( EIP1898Calls ) { } } +BOOST_AUTO_TEST_CASE( eip2930Transactions ) { + std::string _config = c_genesisConfigString; + Json::Value ret; + Json::Reader().parse( _config, ret ); + + // Set chainID = 65535 + ret["params"]["chainID"] = "0xffff"; + + Json::FastWriter fastWriter; + std::string config = fastWriter.write( ret ); + JsonRpcFixture fixture( config ); + + dev::eth::simulateMining( *( fixture.client ), 20 ); + string senderAddress = toJS(fixture.coinbase.address()); + + Json::Value txRefill; + txRefill["to"] = "0xc868AF52a6549c773082A334E5AE232e0Ea3B513"; + txRefill["from"] = senderAddress; + txRefill["gas"] = "100000"; + txRefill["gasPrice"] = fixture.rpcClient->eth_gasPrice(); + txRefill["value"] = 100000000000000000; + string txHash = fixture.rpcClient->eth_sendTransaction( txRefill ); + dev::eth::mineTransaction( *( fixture.client ), 1 ); + + Json::Value receipt = fixture.rpcClient->eth_getTransactionReceipt( txHash ); + BOOST_REQUIRE( receipt["status"] == string( "0x1" ) ); + + BOOST_REQUIRE( fixture.rpcClient->eth_getBalance( "0xc868AF52a6549c773082A334E5AE232e0Ea3B513", "latest" ) == "0x16345785d8a0000" ); + + // send 1 WEI from 0xc868AF52a6549c773082A334E5AE232e0Ea3B513 to 0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b + // encoded type 1 txn + txHash = fixture.rpcClient->eth_sendRawTransaction( "0x01f86882ffff808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180c001a0c171a6fd330b71e278b9030986e0aa9aeba4cad9594bcbe8a608d12f3751f53fa03a24cbd1ab14a62d9f30cf9ace7b5aef04c2289160993ce7df5059d8708762dc" ); + dev::eth::mineTransaction( *( fixture.client ), 1 ); + + BOOST_REQUIRE( fixture.rpcClient->eth_getBalance( "0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b", "latest" ) == "0x1" ); + + auto block = fixture.rpcClient->eth_getBlockByNumber( "3", false ); + BOOST_REQUIRE( block["transactions"].size() == 1 ); + BOOST_REQUIRE( block["transactions"][0].asString() == txHash ); + + + block = fixture.rpcClient->eth_getBlockByNumber( "3", true ); + BOOST_REQUIRE( block["transactions"].size() == 1 ); + BOOST_REQUIRE( block["transactions"][0]["hash"].asString() == txHash ); + + receipt = fixture.rpcClient->eth_getTransactionReceipt( txHash ); + BOOST_REQUIRE( receipt["status"] == string( "0x1" ) ); +} + +BOOST_AUTO_TEST_CASE( eip1559Transactions ) { + JsonRpcFixture fixture; +} + BOOST_AUTO_TEST_CASE( etherbase_generation2 ) { JsonRpcFixture fixture(c_genesisGeneration2ConfigString, false, false, true); string etherbase = fixture.rpcClient->eth_coinbase(); From 1288218714729b7cccf4e27404e5ad89ed8f9723 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 20 Mar 2024 11:12:37 +0000 Subject: [PATCH 02/53] #1719 fix txn handling in verifyBlock --- libethereum/BlockChain.cpp | 7 ++++++- test/unittests/libweb3jsonrpc/jsonrpc.cpp | 11 +++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index f67c3be6e..a6452f497 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -1754,7 +1754,12 @@ 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; + if ( tr.isList() ) + // means Legacy transaction + d = tr.data(); + else + d = tr.payload(); try { Transaction t( d, ( _ir & ImportRequirements::TransactionSignatures ) ? CheckTransaction::Everything : diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index fb9dfcb32..2f70d4366 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -2649,8 +2649,19 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { BOOST_REQUIRE( block["transactions"].size() == 1 ); BOOST_REQUIRE( block["transactions"][0]["hash"].asString() == txHash ); + std::string blockHash = block["hash"].asString(); + receipt = fixture.rpcClient->eth_getTransactionReceipt( txHash ); BOOST_REQUIRE( receipt["status"] == string( "0x1" ) ); + + auto result = fixture.rpcClient->eth_getTransactionByHash( txHash ); + BOOST_REQUIRE( result["hash"].asString() == txHash ); + + result = fixture.rpcClient->eth_getTransactionByBlockHashAndIndex( blockHash, "0x0" ); + BOOST_REQUIRE( result["hash"].asString() == txHash ); + + result = fixture.rpcClient->eth_getTransactionByBlockNumberAndIndex( "0x3", "0x0" ); + BOOST_REQUIRE( result["hash"].asString() == txHash ); } BOOST_AUTO_TEST_CASE( eip1559Transactions ) { From aadb0e2398cc9ae0b6cb8285e0be8088995b87a2 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Thu, 21 Mar 2024 11:04:10 +0000 Subject: [PATCH 03/53] #1719 add more tests --- libethcore/TransactionBase.cpp | 7 ++----- libethereum/ClientBase.cpp | 4 ++-- test/unittests/libweb3jsonrpc/jsonrpc.cpp | 12 +++++++----- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/libethcore/TransactionBase.cpp b/libethcore/TransactionBase.cpp index f0eaff71b..c14fca0e3 100644 --- a/libethcore/TransactionBase.cpp +++ b/libethcore/TransactionBase.cpp @@ -281,11 +281,8 @@ TransactionBase::TransactionBase( } TransactionType TransactionBase::getTransactionType( bytesConstRef _rlp ) { - if ( _rlp.size() < 1 ) { - BOOST_THROW_EXCEPTION( - InvalidTransactionFormat() << errinfo_comment( - "transaction format doesn't correspond to any of the supported formats" ) ); - } + if ( _rlp.empty() ) + return TransactionType::Legacy; if ( _rlp[0] > 2 ) return TransactionType::Legacy; return TransactionType( _rlp[0] ); diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index b4a4a6592..d120b58bd 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -447,12 +447,12 @@ Transactions ClientBase::transactions( h256 _blockHash ) const { RLP b( bl ); Transactions res; for ( unsigned i = 0; i < b[1].itemCount(); i++ ) { - auto tx = b[1][i].data().toBytes(); + auto tx = b[1][i].data(); if ( RLP( tx ).isList() ) // means Legacy transaction res.emplace_back( tx, CheckTransaction::Cheap, true ); else { - tx = RLP( tx ).payload().toBytes(); + tx = RLP( tx ).payload(); res.emplace_back( tx, CheckTransaction::Cheap, true ); } } diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index 2f70d4366..c1dafd758 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -2609,8 +2609,8 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { Json::Value ret; Json::Reader().parse( _config, ret ); - // Set chainID = 65535 - ret["params"]["chainID"] = "0xffff"; + // Set chainID = 151 + ret["params"]["chainID"] = "0x97"; Json::FastWriter fastWriter; std::string config = fastWriter.write( ret ); @@ -2635,16 +2635,18 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { // send 1 WEI from 0xc868AF52a6549c773082A334E5AE232e0Ea3B513 to 0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b // encoded type 1 txn - txHash = fixture.rpcClient->eth_sendRawTransaction( "0x01f86882ffff808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180c001a0c171a6fd330b71e278b9030986e0aa9aeba4cad9594bcbe8a608d12f3751f53fa03a24cbd1ab14a62d9f30cf9ace7b5aef04c2289160993ce7df5059d8708762dc" ); + txHash = fixture.rpcClient->eth_sendRawTransaction( "0x01f8678197808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180c001a01ebdc546c8b85511b7ba831f47c4981069d7af972d10b7dce2c57225cb5df6a7a055ae1e84fea41d37589eb740a0a93017a5cd0e9f10ee50f165bf4b1b4c78ddae" ); dev::eth::mineTransaction( *( fixture.client ), 1 ); + // compare with txn hash from geth + BOOST_REQUIRE( txHash == "0xc843560015a655b8f81f65a458be9019bdb5cd8e416b6329ca18f36de0b8244d" ); + BOOST_REQUIRE( fixture.rpcClient->eth_getBalance( "0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b", "latest" ) == "0x1" ); auto block = fixture.rpcClient->eth_getBlockByNumber( "3", false ); BOOST_REQUIRE( block["transactions"].size() == 1 ); BOOST_REQUIRE( block["transactions"][0].asString() == txHash ); - block = fixture.rpcClient->eth_getBlockByNumber( "3", true ); BOOST_REQUIRE( block["transactions"].size() == 1 ); BOOST_REQUIRE( block["transactions"][0]["hash"].asString() == txHash ); @@ -2665,7 +2667,7 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { } BOOST_AUTO_TEST_CASE( eip1559Transactions ) { - JsonRpcFixture fixture; + BOOST_REQUIRE( true ); } BOOST_AUTO_TEST_CASE( etherbase_generation2 ) { From 2fe5699d26a8ae200d74a51bfc0441998aace0a4 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Fri, 22 Mar 2024 12:59:05 +0000 Subject: [PATCH 04/53] #1719 add new required fields to json api responses --- libethcore/TransactionBase.h | 2 ++ libethereum/ClientBase.cpp | 2 +- libethereum/TransactionReceipt.h | 8 ++++++-- test/unittests/libweb3jsonrpc/jsonrpc.cpp | 21 ++++++++++++++++++++- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/libethcore/TransactionBase.h b/libethcore/TransactionBase.h index d3773166d..a931d7852 100644 --- a/libethcore/TransactionBase.h +++ b/libethcore/TransactionBase.h @@ -260,6 +260,8 @@ class TransactionBase { TransactionType txType() const { return m_txType; } + RLPs accessList() const { return m_accessList; } + /// Get the fee associated for a transaction with the given data. static int64_t baseGasRequired( bool _contractCreation, bytesConstRef _data, EVMSchedule const& _es ); diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index d120b58bd..0a27211e0 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -435,7 +435,7 @@ 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() ) ); } pair< h256, unsigned > ClientBase::transactionLocation( h256 const& _transactionHash ) const { diff --git a/libethereum/TransactionReceipt.h b/libethereum/TransactionReceipt.h index dcbeff84c..66170ea4c 100644 --- a/libethereum/TransactionReceipt.h +++ b/libethereum/TransactionReceipt.h @@ -97,7 +97,8 @@ class LocalisedTransactionReceipt : public TransactionReceipt { public: LocalisedTransactionReceipt( TransactionReceipt const& _t, h256 const& _hash, h256 const& _blockHash, BlockNumber _blockNumber, unsigned _transactionIndex, Address _from, - Address _to, u256 const& _gasUsed, Address const& _contractAddress = Address() ) + Address _to, u256 const& _gasUsed, Address const& _contractAddress = Address(), + int _txType = 0 ) : TransactionReceipt( _t ), m_hash( _hash ), m_blockHash( _blockHash ), @@ -106,7 +107,8 @@ class LocalisedTransactionReceipt : public TransactionReceipt { m_from( _from ), m_to( _to ), m_gasUsed( _gasUsed ), - m_contractAddress( _contractAddress ) { + m_contractAddress( _contractAddress ), + m_txType( _txType ) { LogEntries entries = log(); for ( unsigned i = 0; i < entries.size(); i++ ) m_localisedLogs.push_back( LocalisedLogEntry( @@ -124,6 +126,7 @@ class LocalisedTransactionReceipt : public TransactionReceipt { u256 const& gasUsed() const { return m_gasUsed; } Address const& contractAddress() const { return m_contractAddress; } LocalisedLogEntries const& localisedLogs() const { return m_localisedLogs; }; + int txType() const { return m_txType; } private: h256 m_hash; @@ -134,6 +137,7 @@ class LocalisedTransactionReceipt : public TransactionReceipt { u256 m_gasUsed; Address m_contractAddress; LocalisedLogEntries m_localisedLogs; + int m_txType; Counter< TransactionReceipt > c; diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index c1dafd758..91684cb05 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -2630,6 +2630,12 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { Json::Value receipt = fixture.rpcClient->eth_getTransactionReceipt( txHash ); BOOST_REQUIRE( receipt["status"] == string( "0x1" ) ); + BOOST_REQUIRE( receipt["type"] == "0x0" ); + + auto result = fixture.rpcClient->eth_getTransactionByHash( txHash ); + BOOST_REQUIRE( result["type"] == "0x0" ); + BOOST_REQUIRE( !result.isMember( "yParity" ) ); + BOOST_REQUIRE( !result.isMember( "accessList" ) ); BOOST_REQUIRE( fixture.rpcClient->eth_getBalance( "0xc868AF52a6549c773082A334E5AE232e0Ea3B513", "latest" ) == "0x16345785d8a0000" ); @@ -2650,20 +2656,33 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { block = fixture.rpcClient->eth_getBlockByNumber( "3", true ); BOOST_REQUIRE( block["transactions"].size() == 1 ); BOOST_REQUIRE( block["transactions"][0]["hash"].asString() == txHash ); + BOOST_REQUIRE( block["transactions"][0]["type"] == "0x1" ); + BOOST_REQUIRE( block["transactions"][0]["yParity"] == block["transactions"][0]["v"] ); + BOOST_REQUIRE( block["transactions"][0]["accessList"].isArray() ); std::string blockHash = block["hash"].asString(); receipt = fixture.rpcClient->eth_getTransactionReceipt( txHash ); BOOST_REQUIRE( receipt["status"] == string( "0x1" ) ); + BOOST_REQUIRE( receipt["type"] == "0x1" ); - auto result = fixture.rpcClient->eth_getTransactionByHash( txHash ); + result = fixture.rpcClient->eth_getTransactionByHash( txHash ); BOOST_REQUIRE( result["hash"].asString() == txHash ); + BOOST_REQUIRE( result["type"] == "0x1" ); + BOOST_REQUIRE( result["yParity"] == result["v"] ); + BOOST_REQUIRE( result["accessList"].isArray() ); result = fixture.rpcClient->eth_getTransactionByBlockHashAndIndex( blockHash, "0x0" ); BOOST_REQUIRE( result["hash"].asString() == txHash ); + BOOST_REQUIRE( result["type"] == "0x1" ); + BOOST_REQUIRE( result["yParity"] == result["v"] ); + BOOST_REQUIRE( result["accessList"].isArray() ); result = fixture.rpcClient->eth_getTransactionByBlockNumberAndIndex( "0x3", "0x0" ); BOOST_REQUIRE( result["hash"].asString() == txHash ); + BOOST_REQUIRE( result["type"] == "0x1" ); + BOOST_REQUIRE( result["yParity"] == result["v"] ); + BOOST_REQUIRE( result["accessList"].isArray() ); } BOOST_AUTO_TEST_CASE( eip1559Transactions ) { From aa00f502f8d16279f8cc96d00cb693e75839b116 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Fri, 22 Mar 2024 12:59:19 +0000 Subject: [PATCH 05/53] #1719 add new required fields to json api responses --- libweb3jsonrpc/JsonHelper.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/libweb3jsonrpc/JsonHelper.cpp b/libweb3jsonrpc/JsonHelper.cpp index 883374885..ed26a1efe 100644 --- a/libweb3jsonrpc/JsonHelper.cpp +++ b/libweb3jsonrpc/JsonHelper.cpp @@ -105,6 +105,14 @@ Json::Value toJson( dev::eth::Transaction const& _t, std::pair< h256, unsigned > toJS( 27 + _t.signature().v ); res["r"] = toJS( _t.signature().r ); res["s"] = toJS( _t.signature().s ); + res["type"] = toJS( int( _t.txType() ) ); + if ( _t.txType() != dev::eth::TransactionType::Legacy ) { + res["yParity"] = res["v"].asString(); + res["accessList"] = Json::Value( Json::arrayValue ); + for ( const auto& d : _t.accessList() ) { + res["accessList"].append( dev::toHexPrefixed( d.toBytes() ) ); + } + } } return res; } @@ -203,6 +211,8 @@ Json::Value toJson( dev::eth::LocalisedTransactionReceipt const& _t ) { std::string strRevertReason = _t.getRevertReason(); if ( !strRevertReason.empty() ) res["revertReason"] = strRevertReason; + // + res["type"] = toJS( _t.txType() ); return res; } @@ -310,6 +320,8 @@ rapidjson::Document toRapidJson( dev::eth::LocalisedTransactionReceipt const& _t ADD_FIELD_TO_RAPIDJSON( res, "revertReason", strRevertReason, allocator ); } + ADD_FIELD_TO_RAPIDJSON( res, "type", toJS( _t.txType() ), allocator ); + return res; } @@ -359,6 +371,14 @@ Json::Value toJson( dev::eth::LocalisedTransaction const& _t ) { toJS( 27 + _t.signature().v ); res["r"] = toJS( _t.signature().r.hex() ); res["s"] = toJS( _t.signature().s.hex() ); + res["type"] = toJS( int( _t.txType() ) ); + if ( _t.txType() != dev::eth::TransactionType::Legacy ) { + res["yParity"] = res["v"].asString(); + res["accessList"] = Json::Value( Json::arrayValue ); + for ( const auto& d : _t.accessList() ) { + res["accessList"].append( dev::toHexPrefixed( d.toBytes() ) ); + } + } } return res; } From 41b71124e7472452a29ad7b2291cea5b02e1f7d5 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 25 Mar 2024 13:44:09 +0000 Subject: [PATCH 06/53] #1719 handle accessList in transactions --- libethcore/TransactionBase.cpp | 35 +++++++++++++++++++++-- libweb3jsonrpc/JsonHelper.cpp | 18 ++++++++++-- test/unittests/libweb3jsonrpc/jsonrpc.cpp | 31 ++++++++++++++++++++ 3 files changed, 80 insertions(+), 4 deletions(-) diff --git a/libethcore/TransactionBase.cpp b/libethcore/TransactionBase.cpp index c14fca0e3..0f85ab00c 100644 --- a/libethcore/TransactionBase.cpp +++ b/libethcore/TransactionBase.cpp @@ -36,6 +36,37 @@ using namespace std; using namespace dev; using namespace dev::eth; +RLPs validateAccessListRLP( const RLP& data ) { + if ( !data.isList() ) + BOOST_THROW_EXCEPTION( InvalidTransactionFormat() + << errinfo_comment( "transaction accessList RLP must be a list" ) ); + auto rlpList = data.toList(); + if ( rlpList.empty() ) + // empty accessList, ignore it + return rlpList; + + for ( const auto& d : rlpList ) { + if ( !d.isList() ) + BOOST_THROW_EXCEPTION( InvalidTransactionFormat() << errinfo_comment( + "transaction accessList RLP must be a list" ) ); + auto accessList = d.toList(); + if ( accessList.size() != 2 ) + BOOST_THROW_EXCEPTION( InvalidTransactionFormat() << errinfo_comment( + "transaction accessList RLP must be a list of size 2" ) ); + if ( !accessList[0].isData() || !accessList[1].isList() ) + BOOST_THROW_EXCEPTION( + InvalidTransactionFormat() << errinfo_comment( + "transaction accessList RLP must be a list of byte array and a list" ) ); + for ( const auto& k : accessList[1].toList() ) + if ( !k.isData() ) + BOOST_THROW_EXCEPTION( + InvalidTransactionFormat() << errinfo_comment( + "transaction storageKeys RLP must be a list of byte array" ) ); + } + + return rlpList; +} + TransactionBase::TransactionBase( TransactionSkeleton const& _ts, Secret const& _s ) : m_nonce( _ts.nonce ), m_value( _ts.value ), @@ -156,7 +187,7 @@ TransactionBase TransactionBase::makeType1Transaction( m_data = rlp[6].toBytes(); - m_accessList = rlp[7].toList(); + m_accessList = validateAccessListRLP( rlp[7] ); bool const yParity = rlp[8].toInt< uint8_t >(); h256 const r = rlp[9].toInt< u256 >(); @@ -223,7 +254,7 @@ TransactionBase TransactionBase::makeType2Transaction( m_data = rlp[7].toBytes(); - m_accessList = rlp[8].toList(); + m_accessList = validateAccessListRLP( rlp[8] ); bool const yParity = rlp[9].toInt< uint8_t >(); h256 const r = rlp[10].toInt< u256 >(); diff --git a/libweb3jsonrpc/JsonHelper.cpp b/libweb3jsonrpc/JsonHelper.cpp index ed26a1efe..7f6a55021 100644 --- a/libweb3jsonrpc/JsonHelper.cpp +++ b/libweb3jsonrpc/JsonHelper.cpp @@ -110,7 +110,14 @@ Json::Value toJson( dev::eth::Transaction const& _t, std::pair< h256, unsigned > res["yParity"] = res["v"].asString(); res["accessList"] = Json::Value( Json::arrayValue ); for ( const auto& d : _t.accessList() ) { - res["accessList"].append( dev::toHexPrefixed( d.toBytes() ) ); + auto list = d.toList(); + Json::Value accessList; + accessList["address"] = dev::toHexPrefixed( list[0].toBytes() ); + accessList["storageKeys"] = Json::Value( Json::arrayValue ); + for ( const auto& k : list[1].toList() ) { + accessList["storageKeys"].append( dev::toHexPrefixed( k.toBytes() ) ); + } + res["accessList"].append( accessList ); } } } @@ -376,7 +383,14 @@ Json::Value toJson( dev::eth::LocalisedTransaction const& _t ) { res["yParity"] = res["v"].asString(); res["accessList"] = Json::Value( Json::arrayValue ); for ( const auto& d : _t.accessList() ) { - res["accessList"].append( dev::toHexPrefixed( d.toBytes() ) ); + auto list = d.toList(); + Json::Value accessList; + accessList["address"] = dev::toHexPrefixed( list[0].toBytes() ); + accessList["storageKeys"] = Json::Value( Json::arrayValue ); + for ( const auto& k : list[1].toList() ) { + accessList["storageKeys"].append( dev::toHexPrefixed( k.toBytes() ) ); + } + res["accessList"].append( accessList ); } } } diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index 91684cb05..97d5c4846 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -2683,6 +2683,37 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { BOOST_REQUIRE( result["type"] == "0x1" ); BOOST_REQUIRE( result["yParity"] == result["v"] ); BOOST_REQUIRE( result["accessList"].isArray() ); + + // now the same txn with accessList and increased nonce + // [ { 'address': HexBytes( "0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae" ), 'storageKeys': ( "0x0000000000000000000000000000000000000000000000000000000000000003", "0x0000000000000000000000000000000000000000000000000000000000000007" ) } ] + txHash = fixture.rpcClient->eth_sendRawTransaction( "0x01f8c38197018504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0b03eaf481958e22fc39bd1d526eb9255be1e6625614f02ca939e51c3d7e64bcaa05f675640c04bb050d27bd1f39c07b6ff742311b04dab760bb3bc206054332879" ); + dev::eth::mineTransaction( *( fixture.client ), 1 ); + + // compare with txn hash from geth + BOOST_REQUIRE( txHash == "0xa6d3541e06dff71fb8344a4db2a4ad4e0b45024eb23a8f568982b70a5f50f94d" ); + + result = fixture.rpcClient->eth_getTransactionByHash( txHash ); + BOOST_REQUIRE( result["type"] == "0x1" ); + BOOST_REQUIRE( result["accessList"].isArray() ); + BOOST_REQUIRE( result["accessList"].size() == 1 ); + BOOST_REQUIRE( result["accessList"][0].isObject() && result["accessList"][0].getMemberNames().size() == 2 ); + BOOST_REQUIRE( result["accessList"][0].isMember( "address" ) && result["accessList"][0].isMember( "storageKeys" ) ); + BOOST_REQUIRE( result["accessList"][0]["address"].asString() == "0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae" ); + BOOST_REQUIRE( result["accessList"][0]["storageKeys"].isArray() && result["accessList"][0]["storageKeys"].size() == 2 ); + BOOST_REQUIRE( result["accessList"][0]["storageKeys"][0].asString() == "0x0000000000000000000000000000000000000000000000000000000000000003" ); + BOOST_REQUIRE( result["accessList"][0]["storageKeys"][1].asString() == "0x0000000000000000000000000000000000000000000000000000000000000007" ); + + block = fixture.rpcClient->eth_getBlockByNumber( "4", true ); + result = block["transactions"][0]; + BOOST_REQUIRE( result["type"] == "0x1" ); + BOOST_REQUIRE( result["accessList"].isArray() ); + BOOST_REQUIRE( result["accessList"].size() == 1 ); + BOOST_REQUIRE( result["accessList"][0].isObject() && result["accessList"][0].getMemberNames().size() == 2 ); + BOOST_REQUIRE( result["accessList"][0].isMember( "address" ) && result["accessList"][0].isMember( "storageKeys" ) ); + BOOST_REQUIRE( result["accessList"][0]["address"].asString() == "0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae" ); + BOOST_REQUIRE( result["accessList"][0]["storageKeys"].isArray() && result["accessList"][0]["storageKeys"].size() == 2 ); + BOOST_REQUIRE( result["accessList"][0]["storageKeys"][0].asString() == "0x0000000000000000000000000000000000000000000000000000000000000003" ); + BOOST_REQUIRE( result["accessList"][0]["storageKeys"][1].asString() == "0x0000000000000000000000000000000000000000000000000000000000000007" ); } BOOST_AUTO_TEST_CASE( eip1559Transactions ) { From 4d6da0844c72d248c47749f1e133ebdcd7d770c1 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 25 Mar 2024 19:09:22 +0000 Subject: [PATCH 07/53] #1719 add eth_createAccessList method --- libweb3jsonrpc/Eth.cpp | 15 +++++++++++++++ libweb3jsonrpc/Eth.h | 2 ++ libweb3jsonrpc/EthFace.h | 12 ++++++++++++ 3 files changed, 29 insertions(+) diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index 63d4a8ff3..e20781ed7 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -896,6 +896,21 @@ string Eth::eth_chainId() { return toJS( client()->chainId() ); } +Json::Value Eth::eth_createAccessList( + const Json::Value& _param1, const std::string& /*_param2*/ ) { + TransactionSkeleton t = toTransactionSkeleton( _param1 ); + setTransactionDefaults( t ); + + int64_t gas = static_cast< int64_t >( t.gas ); + auto executionResult = client()->estimateGas( t.from, t.value, t.to, t.data, gas, t.gasPrice ); + + auto result = Json::Value( Json::objectValue ); + result["accessList"] = Json::Value( Json::arrayValue ); + result["gasUsed"] = toJS( executionResult.first ); + + return result; +} + bool Eth::eth_submitWork( string const& _nonce, string const&, string const& _mixHash ) { try { return asEthashClient( client() ) diff --git a/libweb3jsonrpc/Eth.h b/libweb3jsonrpc/Eth.h index 8059860d7..729409144 100644 --- a/libweb3jsonrpc/Eth.h +++ b/libweb3jsonrpc/Eth.h @@ -216,6 +216,8 @@ class Eth : public dev::rpc::EthFace, public skutils::json_config_file_accessor virtual Json::Value eth_subscribe( Json::Value const& _transaction ) override; virtual Json::Value eth_unsubscribe( Json::Value const& _transaction ) override; virtual Json::Value setSchainExitTime( Json::Value const& _transaction ) override; + virtual Json::Value eth_createAccessList( + const Json::Value& param1, const std::string& param2 ) override; void setTransactionDefaults( eth::TransactionSkeleton& _t ); diff --git a/libweb3jsonrpc/EthFace.h b/libweb3jsonrpc/EthFace.h index b7bafedd3..9e7680cf9 100644 --- a/libweb3jsonrpc/EthFace.h +++ b/libweb3jsonrpc/EthFace.h @@ -217,6 +217,10 @@ class EthFace : public ServerInterface< EthFace > { this->bindAndAddMethod( jsonrpc::Procedure( "eth_chainId", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL ), &dev::rpc::EthFace::eth_chainIdI ); + this->bindAndAddMethod( + jsonrpc::Procedure( "eth_createAccessList", jsonrpc::PARAMS_BY_POSITION, + jsonrpc::JSON_STRING, jsonrpc::JSON_STRING, NULL ), + &dev::rpc::EthFace::eth_createAccessListI ); } inline virtual void eth_protocolVersionI( const Json::Value& request, Json::Value& response ) { @@ -428,6 +432,12 @@ class EthFace : public ServerInterface< EthFace > { ( void ) request; response = this->eth_chainId(); } + inline virtual void eth_createAccessListI( const Json::Value& request, Json::Value& response ) { + if ( !request.isArray() || request.empty() ) + BOOST_THROW_EXCEPTION( + jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ) ); + response = this->eth_createAccessList( request[0u], request[1u].asString() ); + } virtual std::string eth_protocolVersion() = 0; virtual std::string eth_hashrate() = 0; virtual std::string eth_coinbase() = 0; @@ -493,6 +503,8 @@ class EthFace : public ServerInterface< EthFace > { virtual Json::Value eth_syncing() = 0; virtual std::string eth_estimateGas( const Json::Value& param1 ) = 0; virtual std::string eth_chainId() = 0; + virtual Json::Value eth_createAccessList( + const Json::Value& param1, const std::string& param2 ) = 0; }; } // namespace rpc From b43a6241f4a0eddb907f118098fc15ab0c24bcfa Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 27 Mar 2024 12:44:43 +0000 Subject: [PATCH 08/53] #1719 add unittests for type2 txns --- libethcore/TransactionBase.cpp | 2 + libethcore/TransactionBase.h | 4 ++ libweb3jsonrpc/JsonHelper.cpp | 8 +++ test/unittests/libweb3jsonrpc/jsonrpc.cpp | 86 ++++++++++++++++++++++- 4 files changed, 99 insertions(+), 1 deletion(-) diff --git a/libethcore/TransactionBase.cpp b/libethcore/TransactionBase.cpp index 0f85ab00c..66308d5ca 100644 --- a/libethcore/TransactionBase.cpp +++ b/libethcore/TransactionBase.cpp @@ -238,6 +238,8 @@ TransactionBase TransactionBase::makeType2Transaction( m_nonce = rlp[1].toInt< u256 >(); m_maxPriorityFeePerGas = rlp[2].toInt< u256 >(); m_maxFeePerGas = rlp[3].toInt< u256 >(); + // set m_gasPrice as SKALE ignores priority fees + m_gasPrice = m_maxFeePerGas; m_gas = rlp[4].toInt< u256 >(); if ( !rlp[5].isData() ) diff --git a/libethcore/TransactionBase.h b/libethcore/TransactionBase.h index a931d7852..0f262fac6 100644 --- a/libethcore/TransactionBase.h +++ b/libethcore/TransactionBase.h @@ -262,6 +262,10 @@ class TransactionBase { RLPs 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 ); diff --git a/libweb3jsonrpc/JsonHelper.cpp b/libweb3jsonrpc/JsonHelper.cpp index 7f6a55021..3d928b3a9 100644 --- a/libweb3jsonrpc/JsonHelper.cpp +++ b/libweb3jsonrpc/JsonHelper.cpp @@ -119,6 +119,10 @@ Json::Value toJson( dev::eth::Transaction const& _t, std::pair< h256, unsigned > } res["accessList"].append( accessList ); } + if ( _t.txType() != dev::eth::TransactionType::Type1 ) { + res["maxPriorityFeePerGas"] = toJS( _t.maxPriorityFeePerGas() ); + res["maxFeePerGas"] = toJS( _t.maxPriorityFeePerGas() ); + } } } return res; @@ -392,6 +396,10 @@ Json::Value toJson( dev::eth::LocalisedTransaction const& _t ) { } res["accessList"].append( accessList ); } + if ( _t.txType() != dev::eth::TransactionType::Type1 ) { + res["maxPriorityFeePerGas"] = toJS( _t.maxPriorityFeePerGas() ); + res["maxFeePerGas"] = toJS( _t.maxPriorityFeePerGas() ); + } } } return res; diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index 97d5c4846..f5c85157c 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -2717,7 +2717,91 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { } BOOST_AUTO_TEST_CASE( eip1559Transactions ) { - BOOST_REQUIRE( true ); + std::string _config = c_genesisConfigString; + Json::Value ret; + Json::Reader().parse( _config, ret ); + + // Set chainID = 151 + ret["params"]["chainID"] = "0x97"; + + Json::FastWriter fastWriter; + std::string config = fastWriter.write( ret ); + JsonRpcFixture fixture( config ); + + dev::eth::simulateMining( *( fixture.client ), 20 ); + string senderAddress = toJS(fixture.coinbase.address()); + + Json::Value txRefill; + txRefill["to"] = "0x5EdF1e852fdD1B0Bc47C0307EF755C76f4B9c251"; + txRefill["from"] = senderAddress; + txRefill["gas"] = "100000"; + txRefill["gasPrice"] = fixture.rpcClient->eth_gasPrice(); + txRefill["value"] = 100000000000000000; + string txHash = fixture.rpcClient->eth_sendTransaction( txRefill ); + dev::eth::mineTransaction( *( fixture.client ), 1 ); + + Json::Value receipt = fixture.rpcClient->eth_getTransactionReceipt( txHash ); + BOOST_REQUIRE( receipt["status"] == string( "0x1" ) ); + BOOST_REQUIRE( receipt["type"] == "0x0" ); + + auto result = fixture.rpcClient->eth_getTransactionByHash( txHash ); + BOOST_REQUIRE( result["type"] == "0x0" ); + BOOST_REQUIRE( !result.isMember( "yParity" ) ); + BOOST_REQUIRE( !result.isMember( "accessList" ) ); + + BOOST_REQUIRE( fixture.rpcClient->eth_getBalance( "0x5EdF1e852fdD1B0Bc47C0307EF755C76f4B9c251", "latest" ) == "0x16345785d8a0000" ); + + // send 1 WEI from 0x5EdF1e852fdD1B0Bc47C0307EF755C76f4B9c251 to 0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b + // encoded type 1 txn + txHash = fixture.rpcClient->eth_sendRawTransaction( "0x02f8c98197808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0f1a407dfc1a9f782001d89f617e9b3a2f295378533784fb39960dea60beea2d0a05ac3da2946554ba3d5721850f4f89ee7a0c38e4acab7130908e7904d13174388" ); + dev::eth::mineTransaction( *( fixture.client ), 1 ); + + // compare with txn hash from geth + BOOST_REQUIRE( txHash == "0x7bd586e93e3012577de4ba33e3b887baf520cbb92c5dd10996b262f9c5c8f747" ); + + BOOST_REQUIRE( fixture.rpcClient->eth_getBalance( "0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b", "latest" ) == "0x1" ); + + auto block = fixture.rpcClient->eth_getBlockByNumber( "3", false ); + BOOST_REQUIRE( block["transactions"].size() == 1 ); + BOOST_REQUIRE( block["transactions"][0].asString() == txHash ); + + block = fixture.rpcClient->eth_getBlockByNumber( "3", true ); +// BOOST_REQUIRE( !block["baseGasFee"].asString().empty() ); + BOOST_REQUIRE( block["transactions"].size() == 1 ); + BOOST_REQUIRE( block["transactions"][0]["hash"].asString() == txHash ); + BOOST_REQUIRE( block["transactions"][0]["type"] == "0x2" ); + BOOST_REQUIRE( block["transactions"][0]["yParity"] == block["transactions"][0]["v"] ); + BOOST_REQUIRE( block["transactions"][0]["accessList"].isArray() ); + + std::string blockHash = block["hash"].asString(); + + receipt = fixture.rpcClient->eth_getTransactionReceipt( txHash ); + BOOST_REQUIRE( receipt["status"] == string( "0x1" ) ); + BOOST_REQUIRE( receipt["type"] == "0x2" ); + + result = fixture.rpcClient->eth_getTransactionByHash( txHash ); + BOOST_REQUIRE( result["hash"].asString() == txHash ); + BOOST_REQUIRE( result["type"] == "0x2" ); + BOOST_REQUIRE( result["yParity"] == result["v"] ); + BOOST_REQUIRE( result["accessList"].isArray() ); + BOOST_REQUIRE( result.isMember( "maxPriorityFeePerGas" ) && result["maxPriorityFeePerGas"].isString() ); + BOOST_REQUIRE( result.isMember( "maxFeePerGas" ) && result["maxFeePerGas"].isString() ); + + result = fixture.rpcClient->eth_getTransactionByBlockHashAndIndex( blockHash, "0x0" ); + BOOST_REQUIRE( result["hash"].asString() == txHash ); + BOOST_REQUIRE( result["type"] == "0x2" ); + BOOST_REQUIRE( result["yParity"] == result["v"] ); + BOOST_REQUIRE( result["accessList"].isArray() ); + BOOST_REQUIRE( result["maxPriorityFeePerGas"] == "0x4a817c800" ); + BOOST_REQUIRE( result["maxFeePerGas"] == "0x4a817c800" ); + + result = fixture.rpcClient->eth_getTransactionByBlockNumberAndIndex( "0x3", "0x0" ); + BOOST_REQUIRE( result["hash"].asString() == txHash ); + BOOST_REQUIRE( result["type"] == "0x2" ); + BOOST_REQUIRE( result["yParity"] == result["v"] ); + BOOST_REQUIRE( result["accessList"].isArray() ); + BOOST_REQUIRE( result["maxPriorityFeePerGas"] == "0x4a817c800" ); + BOOST_REQUIRE( result["maxFeePerGas"] == "0x4a817c800" ); } BOOST_AUTO_TEST_CASE( etherbase_generation2 ) { From 48c71800804396df72c624fa1a8b96dfda1a6cc5 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 27 Mar 2024 12:53:31 +0000 Subject: [PATCH 09/53] #1719 add new json rpc api methods --- libweb3jsonrpc/Eth.cpp | 11 +++++++++++ libweb3jsonrpc/Eth.h | 3 +++ libweb3jsonrpc/EthFace.h | 23 ++++++++++++++++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index e20781ed7..11b1e9ea2 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -896,6 +896,8 @@ string Eth::eth_chainId() { return toJS( client()->chainId() ); } +// SKALE ignores gas costs +// make response default, only fill in gasUsed field Json::Value Eth::eth_createAccessList( const Json::Value& _param1, const std::string& /*_param2*/ ) { TransactionSkeleton t = toTransactionSkeleton( _param1 ); @@ -911,6 +913,15 @@ Json::Value Eth::eth_createAccessList( return result; } +Json::Value Eth::eth_feeHistory( + int64_t /*param1*/, const std::string& /*param2*/, const Json::Value& /*param3*/ ) { + return Json::Value( Json::objectValue ); +} + +std::string Eth::eth_maxPriorityFeePerGas() { + return "0x1"; +} + bool Eth::eth_submitWork( string const& _nonce, string const&, string const& _mixHash ) { try { return asEthashClient( client() ) diff --git a/libweb3jsonrpc/Eth.h b/libweb3jsonrpc/Eth.h index 729409144..3e9e0d3d3 100644 --- a/libweb3jsonrpc/Eth.h +++ b/libweb3jsonrpc/Eth.h @@ -218,6 +218,9 @@ class Eth : public dev::rpc::EthFace, public skutils::json_config_file_accessor virtual Json::Value setSchainExitTime( Json::Value const& _transaction ) override; virtual Json::Value eth_createAccessList( const Json::Value& param1, const std::string& param2 ) override; + virtual Json::Value eth_feeHistory( + int64_t param1, const std::string& param2, const Json::Value& param3 ) override; + virtual std::string eth_maxPriorityFeePerGas() override; void setTransactionDefaults( eth::TransactionSkeleton& _t ); diff --git a/libweb3jsonrpc/EthFace.h b/libweb3jsonrpc/EthFace.h index 9e7680cf9..7d213e966 100644 --- a/libweb3jsonrpc/EthFace.h +++ b/libweb3jsonrpc/EthFace.h @@ -219,8 +219,14 @@ class EthFace : public ServerInterface< EthFace > { &dev::rpc::EthFace::eth_chainIdI ); this->bindAndAddMethod( jsonrpc::Procedure( "eth_createAccessList", jsonrpc::PARAMS_BY_POSITION, - jsonrpc::JSON_STRING, jsonrpc::JSON_STRING, NULL ), + jsonrpc::JSON_OBJECT, "param1", jsonrpc::JSON_STRING, NULL ), &dev::rpc::EthFace::eth_createAccessListI ); + this->bindAndAddMethod( jsonrpc::Procedure( "eth_feeHistory", jsonrpc::PARAMS_BY_POSITION, + jsonrpc::JSON_ARRAY, "param1", jsonrpc::JSON_OBJECT, NULL ), + &dev::rpc::EthFace::eth_feeHistoryI ); + this->bindAndAddMethod( jsonrpc::Procedure( "eth_maxPriorityFeePerGas", + jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL ), + &dev::rpc::EthFace::eth_maxPriorityFeePerGasI ); } inline virtual void eth_protocolVersionI( const Json::Value& request, Json::Value& response ) { @@ -438,6 +444,18 @@ class EthFace : public ServerInterface< EthFace > { jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ) ); response = this->eth_createAccessList( request[0u], request[1u].asString() ); } + inline virtual void eth_feeHistoryI( const Json::Value& request, Json::Value& response ) { + if ( !request.isArray() || request.size() != 3 ) + BOOST_THROW_EXCEPTION( + jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ) ); + response = + this->eth_feeHistory( request[0u].asInt64(), request[1u].asString(), request[2u] ); + } + inline virtual void eth_maxPriorityFeePerGasI( + const Json::Value& request, Json::Value& response ) { + ( void ) request; + response = this->eth_maxPriorityFeePerGas(); + } virtual std::string eth_protocolVersion() = 0; virtual std::string eth_hashrate() = 0; virtual std::string eth_coinbase() = 0; @@ -505,6 +523,9 @@ class EthFace : public ServerInterface< EthFace > { virtual std::string eth_chainId() = 0; virtual Json::Value eth_createAccessList( const Json::Value& param1, const std::string& param2 ) = 0; + virtual Json::Value eth_feeHistory( + int64_t param1, const std::string& param2, const Json::Value& param3 ) = 0; + virtual std::string eth_maxPriorityFeePerGas() = 0; }; } // namespace rpc From 09ecc84b25583552b88a5275b55840bcc223478a Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 27 Mar 2024 20:39:09 +0000 Subject: [PATCH 10/53] #1719 add unittests for txn serialization --- libethcore/TransactionBase.cpp | 4 +- test/unittests/libethereum/Transaction.cpp | 180 ++++++++++++++++++++- test/unittests/libweb3jsonrpc/jsonrpc.cpp | 3 + 3 files changed, 185 insertions(+), 2 deletions(-) diff --git a/libethcore/TransactionBase.cpp b/libethcore/TransactionBase.cpp index 66308d5ca..b9f2e9b20 100644 --- a/libethcore/TransactionBase.cpp +++ b/libethcore/TransactionBase.cpp @@ -41,9 +41,11 @@ RLPs validateAccessListRLP( const RLP& data ) { BOOST_THROW_EXCEPTION( InvalidTransactionFormat() << errinfo_comment( "transaction accessList RLP must be a list" ) ); auto rlpList = data.toList(); - if ( rlpList.empty() ) + if ( rlpList.empty() ) { // empty accessList, ignore it + std::cout << "HERE\n"; return rlpList; + } for ( const auto& d : rlpList ) { if ( !d.isList() ) diff --git a/test/unittests/libethereum/Transaction.cpp b/test/unittests/libethereum/Transaction.cpp index 14e53d159..e21ecb1d9 100644 --- a/test/unittests/libethereum/Transaction.cpp +++ b/test/unittests/libethereum/Transaction.cpp @@ -43,6 +43,28 @@ BOOST_AUTO_TEST_CASE( TransactionGasRequired, CheckTransaction::None ); BOOST_CHECK_EQUAL( tr.baseGasRequired( FrontierSchedule ), 14 * 68 + 21000 ); BOOST_CHECK_EQUAL( tr.baseGasRequired( IstanbulSchedule ), 14 * 16 + 21000 ); + + tr = Transaction ( + fromHex( "0x01f8d18197808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b018" + "e0358ac39584bc98a7c979f984b03f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697b" + "aef842a00000000000000000000000000000000000000000000000000000000000000003a0000" + "000000000000000000000000000000000000000000000000000000000000780a08ae3a721ee02" + "cf52d85ecec934c6f46ea3e96d6355eb8ccde261e1e419885761a0234565f6d227d8eba0937b0" + "f03cb25f83aeb24c13b7a39a9ef6e80c1ea272a3c" ), + CheckTransaction::None ); + BOOST_CHECK_EQUAL( tr.baseGasRequired( FrontierSchedule ), 14 * 68 + 21000 ); + BOOST_CHECK_EQUAL( tr.baseGasRequired( IstanbulSchedule ), 14 * 16 + 21000 ); + + tr = Transaction ( + fromHex( "0x02f8d78197808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9a63" + "b9ab3c12b018e0358ac39584bc98a7c979f984b03f85bf85994de0b295669a9fd93d5f28d9ec8" + "5e40f4cb697baef842a0000000000000000000000000000000000000000000000000000000000" + "0000003a0000000000000000000000000000000000000000000000000000000000000000780a0" + "23927f0e208494bd1fd8876597899d72025167fed902e9c1c417ddd8639bb7b4a02a63ea48f7e" + "94df3a40c4a840ba98da02f13817acb5fe137d40f632e6c8ed367" ), + CheckTransaction::None ); + BOOST_CHECK_EQUAL( tr.baseGasRequired( FrontierSchedule ), 14 * 68 + 21000 ); + BOOST_CHECK_EQUAL( tr.baseGasRequired( IstanbulSchedule ), 14 * 16 + 21000 ); } BOOST_AUTO_TEST_CASE( TransactionWithEmptyRecepient ) { @@ -57,6 +79,40 @@ BOOST_AUTO_TEST_CASE( TransactionWithEmptyRecepient ) { "0xf84c8014830493e0c0808026a02f23977c68f851bbec8619510a4acdd34805270d97f5714b003efe7274914c" "a2a05874022b26e0d88807bdcc59438f86f5a82e24afefad5b6a67ae853896fe2b37" ); BOOST_REQUIRE_THROW( Transaction( txRlp, CheckTransaction::None ), InvalidTransactionFormat ); + + txRlp = fromHex( + "0x01f8bd8197808504a817c80082753080018e0358ac39584bc98a7c979f984b03f85bf85994de0b295669a9fd" + "93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000" + "000003a0000000000000000000000000000000000000000000000000000000000000000780a08d795591e0eb53" + "fb374a804ba3f73cf291069549d62316219811c3f7fb8cfad0a07e9d0bd7fabc8f74475624c912b5334dc49224" + "b1dede6c802d52a35254bfc457" ); + tx = Transaction( txRlp, CheckTransaction::None ); // shouldn't throw + + // recipient RLP is 0xc0 (empty list) + txRlp = fromHex( + "0x01f8bd8197808504a817c800827530c0018e0358ac39584bc98a7c979f984b03f85bf85994de0b295669a9fd" + "93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000" + "000003a0000000000000000000000000000000000000000000000000000000000000000780a08d795591e0eb53" + "fb374a804ba3f73cf291069549d62316219811c3f7fb8cfad0a07e9d0bd7fabc8f74475624c912b5334dc49224" + "b1dede6c802d52a35254bfc457" ); + BOOST_REQUIRE_THROW( Transaction( txRlp, CheckTransaction::None ), InvalidTransactionFormat ); + + txRlp = fromHex( + "0x02f8c38197808504a817c8008504a817c80082753080018e0358ac39584bc98a7c979f984b03f85bf85994de" + "0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000" + "000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0c8" + "029a8b702d54c79ef18b557e755a1bfd8a4afcfcf31813790df34a6f740a95a00ceb8fdf611b4c9ff8d007d2a5" + "44bc4bfae0e97a03e32b1c8b8208c82cebcafb" ); + tx = Transaction( txRlp, CheckTransaction::None ); // shouldn't throw + + // recipient RLP is 0xc0 (empty list) + txRlp = fromHex( + "0x02f8c38197808504a817c8008504a817c800827530c0018e0358ac39584bc98a7c979f984b03f85bf85994de" + "0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000" + "000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0c8" + "029a8b702d54c79ef18b557e755a1bfd8a4afcfcf31813790df34a6f740a95a00ceb8fdf611b4c9ff8d007d2a5" + "44bc4bfae0e97a03e32b1c8b8208c82cebcafb" ); + BOOST_REQUIRE_THROW( Transaction( txRlp, CheckTransaction::None ), InvalidTransactionFormat ); } BOOST_AUTO_TEST_CASE( TransactionNotReplayProtected, @@ -66,11 +122,28 @@ BOOST_AUTO_TEST_CASE( TransactionNotReplayProtected, "1ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3" "b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804" ); Transaction tx( txRlp, CheckTransaction::None ); - tx.checkChainId( 1234, false ); // any chain ID is accepted for not replay protected tx + tx.checkChainId( 1234, true ); // any chain ID is accepted for not replay protected tx RLPStream txRlpStream; tx.streamRLP( txRlpStream ); BOOST_REQUIRE( txRlpStream.out() == txRlp ); + + txRlp = fromHex( + "0x01f8ce8504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b018e0358ac3958" + "4bc98a7c979f984b03f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a0000000000000" + "0000000000000000000000000000000000000000000000000003a000000000000000000000000000000000" + "0000000000000000000000000000000701a0a3b1de6f2958e1e34db86438bba310637f2e799fe9768a143a" + "d87e47c33d1e6ca00e04ef9fe6bb01176c5a4c5bf4a070662478a320eaaff2895d17451c8d61d472" ); + BOOST_REQUIRE_THROW( Transaction( txRlp, CheckTransaction::None, false ), dev::BadCast ); + + txRlp = fromHex( + "0x02f8d5808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b" + "018e0358ac39584bc98a7c979f984b03f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842" + "a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000" + "000000000000000000000000000000000000000000000780a023927f0e208494bd1fd8876597899d720251" + "67fed902e9c1c417ddd8639bb7b4a02a63ea48f7e94df3a40c4a840ba98da02f13817acb5fe137d40f632e" + "6c8ed367" ); + BOOST_REQUIRE_THROW( Transaction( txRlp, CheckTransaction::None, false ), dev::BadCast ); } BOOST_AUTO_TEST_CASE( TransactionChainIDMax64Bit, @@ -90,6 +163,25 @@ BOOST_AUTO_TEST_CASE( TransactionChainIDMax64Bit, "789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3" ); Transaction tx2{txRlp2, CheckTransaction::None}; tx2.checkChainId( std::numeric_limits< uint64_t >::max(), false ); + + txRlp1 = fromHex( + "0x01f8d888ffffffffffffffff808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b01" + "8e0358ac39584bc98a7c979f984b03f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000" + "000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000" + "00000000000000000000000000000000000701a0e236de02b843139aebfce593d680c06ce79cfd2f2e7f9dcac9" + "fe23b38060591aa0734952245446ad42e47ec996c9a7b02973cbc8dd944c9622714416b2bef122f4" ); + tx1 = Transaction{txRlp1, CheckTransaction::None}; + tx1.checkChainId( std::numeric_limits< uint64_t >::max(), false ); + + txRlp1 = fromHex( + "0x02f8de88ffffffffffffffff808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9a6" + "3b9ab3c12b018e0358ac39584bc98a7c979f984b03f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697b" + "aef842a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000" + "00000000000000000000000000000000000000000000000780a0b62465e633b565f2f3632125b452d8df66d4f6" + "b48b58f59da6201234e3f9ce75a0467f18ca2b64f3642cb37e7d5470bbac5fbc62c66b23a0ff955b994803fcf3" + "74" ); + tx1 = Transaction{txRlp1, CheckTransaction::None}; + tx1.checkChainId( std::numeric_limits< uint64_t >::max(), false ); } BOOST_AUTO_TEST_CASE( TransactionChainIDBiggerThan64Bit ) { @@ -106,6 +198,31 @@ BOOST_AUTO_TEST_CASE( TransactionChainIDBiggerThan64Bit ) { "ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa08887321be575c8095f789dd4c7" "43dfe42c1820f9231f98a962b210e3ac2452a3" ); BOOST_REQUIRE_THROW( Transaction( txRlp2, CheckTransaction::None ), InvalidSignature ); + + txRlp1 = fromHex( + "0x01f8d9890a0000000000000117808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b" + "018e0358ac39584bc98a7c979f984b03f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a000" + "00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000" + "0000000000000000000000000000000000000780a0e108b83ed5e1b701b249970e61d9ae409eb6870af96f1a9d" + "8827f497375ae5c8a0795eb0b4f36fe712af5e6a8447802c9eb0913a2add86174552bf2e4b0e183feb" ); + RLPStream rlpStream; + auto tx = Transaction( txRlp1, CheckTransaction::None ); + tx.streamRLP( rlpStream, IncludeSignature::WithSignature ); + auto txRlp = rlpStream.out(); + BOOST_REQUIRE( txRlp != txRlp1 ); + + txRlp1 = fromHex( + "0x02f8df890a0000000000000117808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9" + "a63b9ab3c12b018e0358ac39584bc98a7c979f984b03f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb69" + "7baef842a00000000000000000000000000000000000000000000000000000000000000003a000000000000000" + "0000000000000000000000000000000000000000000000000780a0912e3aad5af05008d3a282d2a76dc975d234" + "4eb34e2500c924a58ccfdc9dbeb4a04afcffcb5d1897df030d45a7eeb3ceb7c7e6fe368fc47865156b4899de32" + "01c7" ); + RLPStream rlpStream1; + tx = Transaction( txRlp1, CheckTransaction::None ); + tx.streamRLP( rlpStream1, IncludeSignature::WithSignature ); + txRlp = rlpStream.out(); + BOOST_REQUIRE( txRlp != txRlp1 ); } BOOST_AUTO_TEST_CASE( TransactionReplayProtected ) { @@ -120,6 +237,67 @@ BOOST_AUTO_TEST_CASE( TransactionReplayProtected ) { RLPStream txRlpStream; tx.streamRLP( txRlpStream ); BOOST_REQUIRE( txRlpStream.out() == txRlp ); + + txRlp = fromHex( + "0x01f8c38197018504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de" + "0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000" + "000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0b0" + "3eaf481958e22fc39bd1d526eb9255be1e6625614f02ca939e51c3d7e64bcaa05f675640c04bb050d27bd1f39c" + "07b6ff742311b04dab760bb3bc206054332879" ); + tx = Transaction( txRlp, CheckTransaction::None ); + tx.checkChainId( 151, false ); + BOOST_REQUIRE_THROW( tx.checkChainId( 123, false ), InvalidSignature ); + + BOOST_REQUIRE( tx.rlp() == txRlp ); + + txRlp = fromHex( + "0x02f8c98197808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180" + "f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000" + "000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000" + "00000780a0f1a407dfc1a9f782001d89f617e9b3a2f295378533784fb39960dea60beea2d0a05ac3da2946554b" + "a3d5721850f4f89ee7a0c38e4acab7130908e7904d13174388" ); + tx = Transaction( txRlp, CheckTransaction::None ); + tx.checkChainId( 151, false ); + BOOST_REQUIRE_THROW( tx.checkChainId( 123, false ), InvalidSignature ); + + BOOST_REQUIRE( tx.rlp() == txRlp ); +} + +BOOST_AUTO_TEST_CASE( accessList ) { + // [ { 'address': HexBytes( "0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae" ), + // 'storageKeys': ( "0x0000000000000000000000000000000000000000000000000000000000000003", "0x0000000000000000000000000000000000000000000000000000000000000007" ) } ] + auto txRlp = fromHex( + "0x01f8c38197018504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de" + "0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000" + "000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0b0" + "3eaf481958e22fc39bd1d526eb9255be1e6625614f02ca939e51c3d7e64bcaa05f675640c04bb050d27bd1f39c" + "07b6ff742311b04dab760bb3bc206054332879" ); + Transaction tx; + BOOST_REQUIRE_NO_THROW( tx = Transaction( txRlp, CheckTransaction::None ) ); + BOOST_REQUIRE( tx.accessList().size() == 1 ); + + // empty accessList + txRlp = fromHex( + "0x01f8678197808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180c001a01ebdc5" + "46c8b85511b7ba831f47c4981069d7af972d10b7dce2c57225cb5df6a7a055ae1e84fea41d37589eb740a0a930" + "17a5cd0e9f10ee50f165bf4b1b4c78ddae" ); + BOOST_REQUIRE_NO_THROW( tx = Transaction( txRlp, CheckTransaction::None ) ); + BOOST_REQUIRE( tx.accessList().size() == 0 ); + + // no accessList + txRlp = fromHex( + "0x01f8678197808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180c080a025fffe" + "aafed61a15aefd1be5ccbd19e3fe07d0088b06ab6ad960d0f6c382d8cea02e255bf1a7de0a75ccec6d00bcc367" + "1af06ca9641fc02024a9d6b28f9b01307b" ); + BOOST_REQUIRE_NO_THROW( tx = Transaction( txRlp, CheckTransaction::None ) ); + BOOST_REQUIRE( tx.accessList().size() == 0 ); + + // change empty accessList 0xc0 to empty array 0x80 + txRlp = fromHex( + "0x01f8678197808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b01808001a01ebdc5" + "46c8b85511b7ba831f47c4981069d7af972d10b7dce2c57225cb5df6a7a055ae1e84fea41d37589eb740a0a930" + "17a5cd0e9f10ee50f165bf4b1b4c78ddae" ); + BOOST_REQUIRE_THROW( Transaction( txRlp, CheckTransaction::None ), InvalidTransactionFormat ); } BOOST_AUTO_TEST_CASE( ExecutionResultOutput, diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index f5c85157c..654339c05 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -2659,6 +2659,7 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { BOOST_REQUIRE( block["transactions"][0]["type"] == "0x1" ); BOOST_REQUIRE( block["transactions"][0]["yParity"] == block["transactions"][0]["v"] ); BOOST_REQUIRE( block["transactions"][0]["accessList"].isArray() ); + BOOST_REQUIRE( block["transactions"][0]["accessList"].size() == 0 ); std::string blockHash = block["hash"].asString(); @@ -2671,6 +2672,7 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { BOOST_REQUIRE( result["type"] == "0x1" ); BOOST_REQUIRE( result["yParity"] == result["v"] ); BOOST_REQUIRE( result["accessList"].isArray() ); + BOOST_REQUIRE( result["accessList"].size() == 0 ); result = fixture.rpcClient->eth_getTransactionByBlockHashAndIndex( blockHash, "0x0" ); BOOST_REQUIRE( result["hash"].asString() == txHash ); @@ -2683,6 +2685,7 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { BOOST_REQUIRE( result["type"] == "0x1" ); BOOST_REQUIRE( result["yParity"] == result["v"] ); BOOST_REQUIRE( result["accessList"].isArray() ); + BOOST_REQUIRE( result["accessList"].size() == 0 ); // now the same txn with accessList and increased nonce // [ { 'address': HexBytes( "0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae" ), 'storageKeys': ( "0x0000000000000000000000000000000000000000000000000000000000000003", "0x0000000000000000000000000000000000000000000000000000000000000007" ) } ] From 6a84e6f7cf23e02f3dc0a71af9172f72a5eda86b Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 1 Apr 2024 12:32:41 +0100 Subject: [PATCH 11/53] #1719 cleanup --- libethcore/TransactionBase.cpp | 1 - libweb3jsonrpc/JsonHelper.cpp | 19 +++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/libethcore/TransactionBase.cpp b/libethcore/TransactionBase.cpp index b9f2e9b20..ccd009462 100644 --- a/libethcore/TransactionBase.cpp +++ b/libethcore/TransactionBase.cpp @@ -43,7 +43,6 @@ RLPs validateAccessListRLP( const RLP& data ) { auto rlpList = data.toList(); if ( rlpList.empty() ) { // empty accessList, ignore it - std::cout << "HERE\n"; return rlpList; } diff --git a/libweb3jsonrpc/JsonHelper.cpp b/libweb3jsonrpc/JsonHelper.cpp index 3d928b3a9..fbe35bfdc 100644 --- a/libweb3jsonrpc/JsonHelper.cpp +++ b/libweb3jsonrpc/JsonHelper.cpp @@ -181,7 +181,7 @@ Json::Value toJson( dev::eth::TransactionReceipt const& _t ) { res["gasUsed"] = toJS( _t.cumulativeGasUsed() ); res["bloom"] = toJS( _t.bloom() ); res["log"] = dev::toJson( _t.log() ); - // + std::string strRevertReason = _t.getRevertReason(); if ( !strRevertReason.empty() ) res["revertReason"] = strRevertReason; @@ -200,29 +200,27 @@ Json::Value toJson( dev::eth::LocalisedTransactionReceipt const& _t ) { res["blockNumber"] = toJS( _t.blockNumber() ); res["cumulativeGasUsed"] = toJS( _t.cumulativeGasUsed() ); res["gasUsed"] = toJS( _t.gasUsed() ); - // + // The "contractAddress" field must be null for all types of trasactions but contract deployment // ones. The contract deployment transaction is special because it's the only type of // transaction with "to" filed set to null. - // dev::Address contractAddress = _t.contractAddress(); if ( contractAddress == dev::Address( 0 ) ) res["contractAddress"] = Json::Value::nullRef; else res["contractAddress"] = toJS( contractAddress ); - // - // + res["logs"] = dev::toJson( _t.localisedLogs() ); res["logsBloom"] = toJS( _t.bloom() ); if ( _t.hasStatusCode() ) res["status"] = toString0x< uint8_t >( _t.statusCode() ); // toString( _t.statusCode() ); else res["stateRoot"] = toJS( _t.stateRoot() ); - // + std::string strRevertReason = _t.getRevertReason(); if ( !strRevertReason.empty() ) res["revertReason"] = strRevertReason; - // + res["type"] = toJS( _t.txType() ); return res; } @@ -304,18 +302,16 @@ rapidjson::Document toRapidJson( dev::eth::LocalisedTransactionReceipt const& _t ADD_FIELD_TO_RAPIDJSON( res, "blockNumber", toJS( _t.blockNumber() ), allocator ); ADD_FIELD_TO_RAPIDJSON( res, "cumulativeGasUsed", toJS( _t.cumulativeGasUsed() ), allocator ); ADD_FIELD_TO_RAPIDJSON( res, "gasUsed", toJS( _t.gasUsed() ), allocator ); - // + // The "contractAddress" field must be null for all types of trasactions but contract deployment // ones. The contract deployment transaction is special because it's the only type of // transaction with "to" filed set to null. - // dev::Address contractAddress = _t.contractAddress(); if ( contractAddress == dev::Address( 0 ) ) res.AddMember( "contractAddress", rapidjson::Value(), allocator ); else ADD_FIELD_TO_RAPIDJSON( res, "contractAddress", toJS( contractAddress ), allocator ); - // - // + res.AddMember( "logs", dev::toRapidJson( _t.localisedLogs(), allocator ), allocator ); ADD_FIELD_TO_RAPIDJSON( res, "logsBloom", toJS( _t.bloom() ), allocator ); if ( _t.hasStatusCode() ) { @@ -324,7 +320,6 @@ rapidjson::Document toRapidJson( dev::eth::LocalisedTransactionReceipt const& _t } else { ADD_FIELD_TO_RAPIDJSON( res, "stateRoot", toJS( _t.stateRoot() ), allocator ); } - // std::string strRevertReason = _t.getRevertReason(); if ( !strRevertReason.empty() ) { From 93c214693cc9f05ecd920ffd1e16d265ba2e40b6 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 1 Apr 2024 13:36:39 +0100 Subject: [PATCH 12/53] #1719 add baseFeePerGas in eth_getBlock calls --- libethereum/BasicGasPricer.h | 3 ++- libethereum/Client.h | 4 +++- libethereum/ClientBase.h | 2 +- libethereum/GasPricer.h | 8 ++++++-- libethereum/Interface.h | 2 +- libethereum/SkaleHost.cpp | 6 ++++-- libethereum/SkaleHost.h | 2 +- libskale/ConsensusGasPricer.cpp | 5 +++-- libskale/ConsensusGasPricer.h | 2 +- libweb3jsonrpc/Eth.cpp | 11 +++++++---- libweb3jsonrpc/JsonHelper.cpp | 8 ++++++-- libweb3jsonrpc/JsonHelper.h | 4 ++-- test/tools/libtesteth/TestHelper.h | 2 +- test/unittests/libethereum/GasPricer.cpp | 4 ++-- 14 files changed, 40 insertions(+), 23 deletions(-) diff --git a/libethereum/BasicGasPricer.h b/libethereum/BasicGasPricer.h index 49555aac9..9585c85c7 100644 --- a/libethereum/BasicGasPricer.h +++ b/libethereum/BasicGasPricer.h @@ -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 ); } diff --git a/libethereum/Client.h b/libethereum/Client.h index d62af01b1..d54c9d537 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -135,7 +135,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. diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index ab4b7a812..4537aaef3 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -160,7 +160,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; diff --git a/libethereum/GasPricer.h b/libethereum/GasPricer.h index 4542861d0..237ddba80 100644 --- a/libethereum/GasPricer.h +++ b/libethereum/GasPricer.h @@ -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& ) {} }; @@ -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; diff --git a/libethereum/Interface.h b/libethereum/Interface.h index a6c1c874f..57931ed3b 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -242,7 +242,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; diff --git a/libethereum/SkaleHost.cpp b/libethereum/SkaleHost.cpp index 01434a060..4645cfee5 100644 --- a/libethereum/SkaleHost.cpp +++ b/libethereum/SkaleHost.cpp @@ -933,8 +933,10 @@ void SkaleHost::broadcastFunc() { m_broadcaster->stopService(); } -u256 SkaleHost::getGasPrice() const { - return m_consensus->getPriceForBlockId( m_client.number() ); +u256 SkaleHost::getGasPrice( unsigned _blockNumber ) const { + if ( _blockNumber == dev::eth::LatestBlock ) + _blockNumber = m_client.number(); + return m_consensus->getPriceForBlockId( _blockNumber ); } u256 SkaleHost::getBlockRandom() const { diff --git a/libethereum/SkaleHost.h b/libethereum/SkaleHost.h index 8ffce7aca..598bf47ad 100644 --- a/libethereum/SkaleHost.h +++ b/libethereum/SkaleHost.h @@ -122,7 +122,7 @@ class SkaleHost { dev::h256 receiveTransaction( std::string ); - dev::u256 getGasPrice() const; + dev::u256 getGasPrice( unsigned _blockNumber = dev::eth::LatestBlock ) const; dev::u256 getBlockRandom() const; dev::eth::SyncStatus syncStatus() const; std::map< std::string, uint64_t > getConsensusDbUsage() const; diff --git a/libskale/ConsensusGasPricer.cpp b/libskale/ConsensusGasPricer.cpp index 5412cb4c3..930c1d2b4 100644 --- a/libskale/ConsensusGasPricer.cpp +++ b/libskale/ConsensusGasPricer.cpp @@ -9,6 +9,7 @@ dev::u256 ConsensusGasPricer::ask( dev::eth::Block const& ) const { return bid(); } -dev::u256 ConsensusGasPricer::bid( dev::eth::TransactionPriority /*_p*/ ) const { - return m_skaleHost.getGasPrice(); +dev::u256 ConsensusGasPricer::bid( + unsigned _blockNumber, dev::eth::TransactionPriority /*_p*/ ) const { + return m_skaleHost.getGasPrice( _blockNumber ); } diff --git a/libskale/ConsensusGasPricer.h b/libskale/ConsensusGasPricer.h index 93f351b31..181667b54 100644 --- a/libskale/ConsensusGasPricer.h +++ b/libskale/ConsensusGasPricer.h @@ -10,7 +10,7 @@ class ConsensusGasPricer : public dev::eth::GasPricer { ConsensusGasPricer( const SkaleHost& _host ); virtual dev::u256 ask( dev::eth::Block const& ) const override; - virtual dev::u256 bid( + virtual dev::u256 bid( unsigned _blockNumber = dev::eth::LatestBlock, dev::eth::TransactionPriority _p = dev::eth::TransactionPriority::Medium ) const override; private: diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index 11b1e9ea2..58229596a 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -567,7 +567,8 @@ Json::Value Eth::eth_getBlockByHash( string const& _blockHash, bool _includeTran } #endif return toJson( client()->blockInfo( h ), client()->blockDetails( h ), - client()->uncleHashes( h ), transactions, client()->sealEngine() ); + client()->uncleHashes( h ), transactions, client()->sealEngine(), + client()->gasBidPrice( client()->numberFromHash( h ) ) ); } else { h256s transactions = client()->transactionHashes( h ); @@ -584,7 +585,8 @@ Json::Value Eth::eth_getBlockByHash( string const& _blockHash, bool _includeTran } #endif return toJson( client()->blockInfo( h ), client()->blockDetails( h ), - client()->uncleHashes( h ), transactions, client()->sealEngine() ); + client()->uncleHashes( h ), transactions, client()->sealEngine(), + client()->gasBidPrice( client()->numberFromHash( h ) ) ); } } catch ( ... ) { BOOST_THROW_EXCEPTION( JsonRpcException( Errors::ERROR_RPC_INVALID_PARAMS ) ); @@ -606,11 +608,12 @@ Json::Value Eth::eth_getBlockByNumber( string const& _blockNumber, bool _include if ( _includeTransactions ) return toJson( client()->blockInfo( h ), client()->blockDetails( h ), - client()->uncleHashes( h ), client()->transactions( h ), client()->sealEngine() ); + client()->uncleHashes( h ), client()->transactions( h ), client()->sealEngine(), + client()->gasBidPrice( h ) ); else return toJson( client()->blockInfo( h ), client()->blockDetails( h ), client()->uncleHashes( h ), client()->transactionHashes( h ), - client()->sealEngine() ); + client()->sealEngine(), client()->gasBidPrice( h ) ); #endif } catch ( ... ) { BOOST_THROW_EXCEPTION( JsonRpcException( Errors::ERROR_RPC_INVALID_PARAMS ) ); diff --git a/libweb3jsonrpc/JsonHelper.cpp b/libweb3jsonrpc/JsonHelper.cpp index fbe35bfdc..012352a8e 100644 --- a/libweb3jsonrpc/JsonHelper.cpp +++ b/libweb3jsonrpc/JsonHelper.cpp @@ -129,12 +129,14 @@ Json::Value toJson( dev::eth::Transaction const& _t, std::pair< h256, unsigned > } Json::Value toJson( dev::eth::BlockHeader const& _bi, BlockDetails const& _bd, - UncleHashes const& _us, Transactions const& _ts, SealEngineFace* _face ) { + UncleHashes const& _us, Transactions const& _ts, SealEngineFace* _face, u256 _gasPrice ) { Json::Value res = toJson( _bi, _face ); if ( _bi ) { res["totalDifficulty"] = toJS( _bd.totalDifficulty ); res["size"] = toJS( _bd.blockSizeBytes ); res["uncles"] = Json::Value( Json::arrayValue ); + if ( _gasPrice > 0 ) + res["baseFeePerGas"] = toJS( _gasPrice ); for ( h256 h : _us ) res["uncles"].append( toJS( h ) ); res["transactions"] = Json::Value( Json::arrayValue ); @@ -146,12 +148,14 @@ Json::Value toJson( dev::eth::BlockHeader const& _bi, BlockDetails const& _bd, } Json::Value toJson( dev::eth::BlockHeader const& _bi, BlockDetails const& _bd, - UncleHashes const& _us, TransactionHashes const& _ts, SealEngineFace* _face ) { + UncleHashes const& _us, TransactionHashes const& _ts, SealEngineFace* _face, u256 _gasPrice ) { Json::Value res = toJson( _bi, _face ); if ( _bi ) { res["totalDifficulty"] = toJS( _bd.totalDifficulty ); res["size"] = toJS( _bd.blockSizeBytes ); res["uncles"] = Json::Value( Json::arrayValue ); + if ( _gasPrice > 0 ) + res["baseFeePerGas"] = toJS( _gasPrice ); for ( h256 h : _us ) res["uncles"].append( toJS( h ) ); res["transactions"] = Json::Value( Json::arrayValue ); diff --git a/libweb3jsonrpc/JsonHelper.h b/libweb3jsonrpc/JsonHelper.h index 9f66e5c00..f5cb095fa 100644 --- a/libweb3jsonrpc/JsonHelper.h +++ b/libweb3jsonrpc/JsonHelper.h @@ -60,9 +60,9 @@ Json::Value toJson( BlockHeader const& _bi, SealEngineFace* _face = nullptr ); Json::Value toJson( Transaction const& _t, std::pair< h256, unsigned > _location, BlockNumber _blockNumber ); Json::Value toJson( BlockHeader const& _bi, BlockDetails const& _bd, UncleHashes const& _us, - Transactions const& _ts, SealEngineFace* _face = nullptr ); + Transactions const& _ts, SealEngineFace* _face = nullptr, u256 _gasPrice = 0 ); Json::Value toJson( BlockHeader const& _bi, BlockDetails const& _bd, UncleHashes const& _us, - TransactionHashes const& _ts, SealEngineFace* _face = nullptr ); + TransactionHashes const& _ts, SealEngineFace* _face = nullptr, u256 _gasPrice = 0 ); Json::Value toJson( TransactionSkeleton const& _t ); Json::Value toJson( Transaction const& _t ); Json::Value toJson( Transaction const& _t, bytes const& _rlp ); diff --git a/test/tools/libtesteth/TestHelper.h b/test/tools/libtesteth/TestHelper.h index 4976ae4c5..aa9a730d1 100644 --- a/test/tools/libtesteth/TestHelper.h +++ b/test/tools/libtesteth/TestHelper.h @@ -84,7 +84,7 @@ typedef json_spirit::Value_type jsonVType; class ZeroGasPricer : public eth::GasPricer { protected: u256 ask( eth::Block const& ) const override { return 0; } - u256 bid( eth::TransactionPriority = eth::TransactionPriority::Medium ) const override { + u256 bid( unsigned = dev::eth::LatestBlock, eth::TransactionPriority = eth::TransactionPriority::Medium ) const override { return 0; } }; diff --git a/test/unittests/libethereum/GasPricer.cpp b/test/unittests/libethereum/GasPricer.cpp index 929b64bc5..70bae8380 100644 --- a/test/unittests/libethereum/GasPricer.cpp +++ b/test/unittests/libethereum/GasPricer.cpp @@ -53,8 +53,8 @@ void executeGasPricerTest( string const& name, double _etherPrice, double _block BOOST_CHECK_MESSAGE( abs( gp.ask( Block( Block::Null ) ) - _expectedAsk ) < 100000000, "ASK Got: " + toString( gp.ask( Block( Block::Null ) ) ) + " Expected: " + toString( _expectedAsk ) ); - BOOST_CHECK_MESSAGE( abs( gp.bid( _txPrio ) - _expectedBid ) < 100000000, - "BID Got: " + toString( gp.bid( _txPrio ) ) + " Expected: " + toString( _expectedBid ) ); + BOOST_CHECK_MESSAGE( abs( gp.bid( dev::eth::LatestBlock, _txPrio ) - _expectedBid ) < 100000000, + "BID Got: " + toString( gp.bid( dev::eth::LatestBlock, _txPrio ) ) + " Expected: " + toString( _expectedBid ) ); } } // namespace test } // namespace dev From 92bd60f0a37fe555cf68fbb9576b4db2f653e913 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 1 Apr 2024 19:30:22 +0100 Subject: [PATCH 13/53] #1719 add extra checks --- test/unittests/libweb3jsonrpc/jsonrpc.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index 654339c05..912eca96d 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -2647,6 +2647,8 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { // compare with txn hash from geth BOOST_REQUIRE( txHash == "0xc843560015a655b8f81f65a458be9019bdb5cd8e416b6329ca18f36de0b8244d" ); + BOOST_REQUIRE( dev::toHexPrefixed( fixture.client->transactions( 3 )[0].rlp() ) == "0x01f8678197808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180c001a01ebdc546c8b85511b7ba831f47c4981069d7af972d10b7dce2c57225cb5df6a7a055ae1e84fea41d37589eb740a0a93017a5cd0e9f10ee50f165bf4b1b4c78ddae" ); + BOOST_REQUIRE( fixture.rpcClient->eth_getBalance( "0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b", "latest" ) == "0x1" ); auto block = fixture.rpcClient->eth_getBlockByNumber( "3", false ); @@ -2694,6 +2696,7 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { // compare with txn hash from geth BOOST_REQUIRE( txHash == "0xa6d3541e06dff71fb8344a4db2a4ad4e0b45024eb23a8f568982b70a5f50f94d" ); + BOOST_REQUIRE( dev::toHexPrefixed( fixture.client->transactions( 4 )[0].rlp() ) == "0x01f8c38197018504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0b03eaf481958e22fc39bd1d526eb9255be1e6625614f02ca939e51c3d7e64bcaa05f675640c04bb050d27bd1f39c07b6ff742311b04dab760bb3bc206054332879" ); result = fixture.rpcClient->eth_getTransactionByHash( txHash ); BOOST_REQUIRE( result["type"] == "0x1" ); @@ -2761,6 +2764,7 @@ BOOST_AUTO_TEST_CASE( eip1559Transactions ) { // compare with txn hash from geth BOOST_REQUIRE( txHash == "0x7bd586e93e3012577de4ba33e3b887baf520cbb92c5dd10996b262f9c5c8f747" ); + BOOST_REQUIRE( dev::toHexPrefixed( fixture.client->transactions( 3 )[0].rlp() ) == "0x02f8c98197808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0f1a407dfc1a9f782001d89f617e9b3a2f295378533784fb39960dea60beea2d0a05ac3da2946554ba3d5721850f4f89ee7a0c38e4acab7130908e7904d13174388" ); BOOST_REQUIRE( fixture.rpcClient->eth_getBalance( "0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b", "latest" ) == "0x1" ); From 8243d5cb07132434e7a803e3f37ef3df0a045471 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 2 Apr 2024 12:35:59 +0100 Subject: [PATCH 14/53] #1719 add extra checks in test --- test/unittests/libweb3jsonrpc/jsonrpc.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index 912eca96d..51ee10603 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -2664,6 +2664,7 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { BOOST_REQUIRE( block["transactions"][0]["accessList"].size() == 0 ); std::string blockHash = block["hash"].asString(); + BOOST_REQUIRE( fixture.client->transactionHashes( dev::h256( blockHash ) )[0] == dev::h256( "0xc843560015a655b8f81f65a458be9019bdb5cd8e416b6329ca18f36de0b8244d") ); receipt = fixture.rpcClient->eth_getTransactionReceipt( txHash ); BOOST_REQUIRE( receipt["status"] == string( "0x1" ) ); @@ -2773,7 +2774,7 @@ BOOST_AUTO_TEST_CASE( eip1559Transactions ) { BOOST_REQUIRE( block["transactions"][0].asString() == txHash ); block = fixture.rpcClient->eth_getBlockByNumber( "3", true ); -// BOOST_REQUIRE( !block["baseGasFee"].asString().empty() ); + BOOST_REQUIRE( !block["baseGasFee"].asString().empty() ); BOOST_REQUIRE( block["transactions"].size() == 1 ); BOOST_REQUIRE( block["transactions"][0]["hash"].asString() == txHash ); BOOST_REQUIRE( block["transactions"][0]["type"] == "0x2" ); From 1d2b710cb0ae77cda9c0048bd2453911ec7a10fc Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 2 Apr 2024 17:42:54 +0100 Subject: [PATCH 15/53] #1719 cleanup --- libethereum/ClientBase.cpp | 12 +++++------- test/unittests/libweb3jsonrpc/jsonrpc.cpp | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index 0a27211e0..de711e0d3 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -447,14 +447,12 @@ Transactions ClientBase::transactions( h256 _blockHash ) const { RLP b( bl ); Transactions res; for ( unsigned i = 0; i < b[1].itemCount(); i++ ) { - auto tx = b[1][i].data(); - if ( RLP( tx ).isList() ) + auto txRlp = b[1][i]; + if ( txRlp.isList() ) // means Legacy transaction - res.emplace_back( tx, CheckTransaction::Cheap, true ); - else { - tx = RLP( tx ).payload(); - res.emplace_back( tx, CheckTransaction::Cheap, true ); - } + res.emplace_back( txRlp.data(), CheckTransaction::Cheap, true ); + else + res.emplace_back( txRlp.payload(), CheckTransaction::Cheap, true ); } return res; } diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index 51ee10603..5568849e5 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -2774,7 +2774,7 @@ BOOST_AUTO_TEST_CASE( eip1559Transactions ) { BOOST_REQUIRE( block["transactions"][0].asString() == txHash ); block = fixture.rpcClient->eth_getBlockByNumber( "3", true ); - BOOST_REQUIRE( !block["baseGasFee"].asString().empty() ); + BOOST_REQUIRE( !block["baseFeePerGas"].asString().empty() ); BOOST_REQUIRE( block["transactions"].size() == 1 ); BOOST_REQUIRE( block["transactions"][0]["hash"].asString() == txHash ); BOOST_REQUIRE( block["transactions"][0]["type"] == "0x2" ); From 058908123edc10f469ec4989431b583b0ed52e77 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 8 Apr 2024 13:47:05 +0100 Subject: [PATCH 16/53] #1719 fix sha3 hash calculation for invalid transactions --- libethcore/TransactionBase.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/libethcore/TransactionBase.cpp b/libethcore/TransactionBase.cpp index ccd009462..cf50ea140 100644 --- a/libethcore/TransactionBase.cpp +++ b/libethcore/TransactionBase.cpp @@ -500,12 +500,18 @@ h256 TransactionBase::sha3( IncludeSignature _sig ) const { MICROPROFILE_SCOPEI( "TransactionBase", "sha3", MP_KHAKI2 ); - RLPStream s; - streamRLP( s, _sig, !isInvalid() && isReplayProtected() && _sig == WithoutSignature ); + dev::bytes input; + if ( !isInvalid() ) { + RLPStream s; + streamRLP( s, _sig, !isInvalid() && isReplayProtected() && _sig == WithoutSignature ); - dev::bytes input = s.out(); - if ( m_txType != TransactionType::Legacy ) - input.insert( input.begin(), m_txType ); + input = s.out(); + if ( m_txType != TransactionType::Legacy ) + input.insert( input.begin(), m_txType ); + } else { + RLP data( m_rawData ); + input = dev::bytes( data.payload().begin(), data.payload().end() ); + } auto ret = dev::sha3( input ); if ( _sig == WithSignature ) From dc7a567d873f5bbe46ed3a50ccaae9a903fde7eb Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 8 Apr 2024 15:17:36 +0100 Subject: [PATCH 17/53] #1719 fix getTransactionReceipt for HISTORIC STATE --- libweb3jsonrpc/Eth.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index 58229596a..4fe715a6b 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -737,7 +737,7 @@ LocalisedTransactionReceipt Eth::eth_getTransactionReceipt( string const& _trans size_t newIndex = m_gapCache->gappedIndexFromReal( rcp.blockNumber(), rcp.transactionIndex() ); rcp = LocalisedTransactionReceipt( rcp, rcp.hash(), rcp.blockHash(), rcp.blockNumber(), - newIndex, rcp.from(), rcp.to(), rcp.gasUsed(), rcp.contractAddress() ); + newIndex, rcp.from(), rcp.to(), rcp.gasUsed(), rcp.contractAddress(), rcp.txType() ); } #endif From 49aa2131117550130de9e7585f71d24cc2fd5e0f Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 10 Apr 2024 18:59:17 +0100 Subject: [PATCH 18/53] #1719 add tests for new json-rpc methods --- libweb3jsonrpc/Eth.cpp | 59 ++++++++++++- libweb3jsonrpc/Eth.h | 2 +- libweb3jsonrpc/EthFace.h | 13 +-- .../libweb3jsonrpc/WebThreeStubClient.cpp | 35 ++++++++ .../libweb3jsonrpc/WebThreeStubClient.h | 3 + test/unittests/libweb3jsonrpc/jsonrpc.cpp | 88 +++++++++++++++++++ 6 files changed, 189 insertions(+), 11 deletions(-) diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index 4fe715a6b..0bd42958e 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -916,13 +916,64 @@ Json::Value Eth::eth_createAccessList( return result; } -Json::Value Eth::eth_feeHistory( - int64_t /*param1*/, const std::string& /*param2*/, const Json::Value& /*param3*/ ) { - return Json::Value( Json::objectValue ); +Json::Value Eth::eth_feeHistory( const std::string& _blockCount, const std::string& _newestBlock, + const Json::Value& _rewardPercentiles ) { + try { + if ( !_rewardPercentiles.isArray() ) + throw std::runtime_error( "Reward percentiles must be a list" ); + + for ( auto p : _rewardPercentiles ) { + if ( !p.isUInt() || p > 100 ) { + throw std::runtime_error( "Percentiles must be positive integers less then 100" ); + } + } + + auto blockCount = jsToU256( _blockCount ); + auto newestBlock = jsToBlockNumber( _newestBlock ); + if ( newestBlock == dev::eth::LatestBlock ) + newestBlock = client()->number(); + + auto result = Json::Value( Json::objectValue ); + dev::u256 oldestBlock; + if ( blockCount > newestBlock ) + oldestBlock = 0; + else + oldestBlock = dev::u256( newestBlock ) - blockCount + 1; + result["oldestBlock"] = toJS( oldestBlock ); + + result["baseFeePerGas"] = Json::Value( Json::arrayValue ); + result["gasUsedRatio"] = Json::Value( Json::arrayValue ); + result["reward"] = Json::Value( Json::arrayValue ); + for ( auto bn = newestBlock; bn > oldestBlock - 1; --bn ) { + auto blockInfo = client()->blockInfo( client()->hashFromNumber( bn ) ); + + if ( blockInfo.timestamp() ) + result["baseFeePerGas"].append( toJS( client()->gasBidPrice( bn ) ) ); + else + result["baseFeePerGas"].append( toJS( 0 ) ); + + double gasUsedRatio = blockInfo.gasUsed().convert_to< double >() / + blockInfo.gasLimit().convert_to< double >(); + Json::Value gasUsedRatioObj = Json::Value( Json::realValue ); + gasUsedRatioObj = gasUsedRatio; + result["gasUsedRatio"].append( gasUsedRatioObj ); + + Json::Value reward = Json::Value( Json::arrayValue ); + reward.resize( _rewardPercentiles.size() ); + for ( Json::Value::ArrayIndex i = 0; i < reward.size(); ++i ) { + reward[i] = toJS( 0 ); + } + result["reward"].append( reward ); + } + + return result; + } catch ( ... ) { + BOOST_THROW_EXCEPTION( JsonRpcException( Errors::ERROR_RPC_INVALID_PARAMS ) ); + } } std::string Eth::eth_maxPriorityFeePerGas() { - return "0x1"; + return "0x0"; } bool Eth::eth_submitWork( string const& _nonce, string const&, string const& _mixHash ) { diff --git a/libweb3jsonrpc/Eth.h b/libweb3jsonrpc/Eth.h index 3e9e0d3d3..57538fbd6 100644 --- a/libweb3jsonrpc/Eth.h +++ b/libweb3jsonrpc/Eth.h @@ -219,7 +219,7 @@ class Eth : public dev::rpc::EthFace, public skutils::json_config_file_accessor virtual Json::Value eth_createAccessList( const Json::Value& param1, const std::string& param2 ) override; virtual Json::Value eth_feeHistory( - int64_t param1, const std::string& param2, const Json::Value& param3 ) override; + const std::string& param1, const std::string& param2, const Json::Value& param3 ) override; virtual std::string eth_maxPriorityFeePerGas() override; void setTransactionDefaults( eth::TransactionSkeleton& _t ); diff --git a/libweb3jsonrpc/EthFace.h b/libweb3jsonrpc/EthFace.h index 7d213e966..c87edf57b 100644 --- a/libweb3jsonrpc/EthFace.h +++ b/libweb3jsonrpc/EthFace.h @@ -217,12 +217,13 @@ class EthFace : public ServerInterface< EthFace > { this->bindAndAddMethod( jsonrpc::Procedure( "eth_chainId", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL ), &dev::rpc::EthFace::eth_chainIdI ); - this->bindAndAddMethod( - jsonrpc::Procedure( "eth_createAccessList", jsonrpc::PARAMS_BY_POSITION, - jsonrpc::JSON_OBJECT, "param1", jsonrpc::JSON_STRING, NULL ), + this->bindAndAddMethod( jsonrpc::Procedure( "eth_createAccessList", + jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1", + jsonrpc::JSON_OBJECT, "param2", jsonrpc::JSON_STRING, NULL ), &dev::rpc::EthFace::eth_createAccessListI ); this->bindAndAddMethod( jsonrpc::Procedure( "eth_feeHistory", jsonrpc::PARAMS_BY_POSITION, - jsonrpc::JSON_ARRAY, "param1", jsonrpc::JSON_OBJECT, NULL ), + jsonrpc::JSON_OBJECT, "param1", jsonrpc::JSON_STRING, "param2", + jsonrpc::JSON_STRING, "param3", jsonrpc::JSON_ARRAY, NULL ), &dev::rpc::EthFace::eth_feeHistoryI ); this->bindAndAddMethod( jsonrpc::Procedure( "eth_maxPriorityFeePerGas", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL ), @@ -449,7 +450,7 @@ class EthFace : public ServerInterface< EthFace > { BOOST_THROW_EXCEPTION( jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ) ); response = - this->eth_feeHistory( request[0u].asInt64(), request[1u].asString(), request[2u] ); + this->eth_feeHistory( request[0u].asString(), request[1u].asString(), request[2u] ); } inline virtual void eth_maxPriorityFeePerGasI( const Json::Value& request, Json::Value& response ) { @@ -524,7 +525,7 @@ class EthFace : public ServerInterface< EthFace > { virtual Json::Value eth_createAccessList( const Json::Value& param1, const std::string& param2 ) = 0; virtual Json::Value eth_feeHistory( - int64_t param1, const std::string& param2, const Json::Value& param3 ) = 0; + const std::string& param1, const std::string& param2, const Json::Value& param3 ) = 0; virtual std::string eth_maxPriorityFeePerGas() = 0; }; diff --git a/test/unittests/libweb3jsonrpc/WebThreeStubClient.cpp b/test/unittests/libweb3jsonrpc/WebThreeStubClient.cpp index 680bdb57e..d41d85927 100644 --- a/test/unittests/libweb3jsonrpc/WebThreeStubClient.cpp +++ b/test/unittests/libweb3jsonrpc/WebThreeStubClient.cpp @@ -810,6 +810,41 @@ bool WebThreeStubClient::eth_notePassword( const std::string& param1 ) { jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString() ); } +std::string WebThreeStubClient::eth_maxPriorityFeePerGas() { + Json::Value p; + Json::Value result = this->CallMethod( "eth_maxPriorityFeePerGas", p ); + if ( result.isString() ) + return result.asString(); + else + throw jsonrpc::JsonRpcException( + jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString() ); +} + +Json::Value WebThreeStubClient::eth_createAccessList( const Json::Value& param1, const std::string& param2 ) { + Json::Value p; + p.append( param1 ); + p.append( param2 ); + Json::Value result = this->CallMethod( "eth_createAccessList", p ); + if ( result.isObject() ) + return result; + else + throw jsonrpc::JsonRpcException( + jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString() ); +} + +Json::Value WebThreeStubClient::eth_feeHistory( const std::string& param1, const std::string& param2, const Json::Value& param3 ) { + Json::Value p; + p.append( param1 ); + p.append( param2 ); + p.append( param3 ); + Json::Value result = this->CallMethod( "eth_feeHistory", p ); + if ( result.isObject() ) + return result; + else + throw jsonrpc::JsonRpcException( + jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString() ); +} + bool WebThreeStubClient::db_put( const std::string& param1, const std::string& param2, const std::string& param3 ) { Json::Value p; diff --git a/test/unittests/libweb3jsonrpc/WebThreeStubClient.h b/test/unittests/libweb3jsonrpc/WebThreeStubClient.h index 6385a340d..b23fb20ab 100644 --- a/test/unittests/libweb3jsonrpc/WebThreeStubClient.h +++ b/test/unittests/libweb3jsonrpc/WebThreeStubClient.h @@ -95,6 +95,9 @@ class WebThreeStubClient : public jsonrpc::Client { Json::Value setSchainExitTime( const Json::Value& param1 ) noexcept( false ); Json::Value eth_inspectTransaction( const std::string& param1 ) noexcept( false ); std::string eth_sendRawTransaction( const std::string& param1 ) noexcept( false ); + std::string eth_maxPriorityFeePerGas() noexcept( false ); + Json::Value eth_createAccessList( const Json::Value& param1, const std::string& param2 ) noexcept( false ); + Json::Value eth_feeHistory( const std::string& param1, const std::string& param2, const Json::Value& param3 ) noexcept( false ); bool eth_notePassword( const std::string& param1 ) noexcept( false ); bool db_put( const std::string& param1, const std::string& param2, const std::string& param3 ) noexcept( false ); diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index 5568849e5..503657be0 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -2812,6 +2812,94 @@ BOOST_AUTO_TEST_CASE( eip1559Transactions ) { BOOST_REQUIRE( result["maxFeePerGas"] == "0x4a817c800" ); } +BOOST_AUTO_TEST_CASE( eip2930RpcMethods ) { + std::string _config = c_genesisConfigString; + Json::Value ret; + Json::Reader().parse( _config, ret ); + + // Set chainID = 151 + ret["params"]["chainID"] = "0x97"; + + Json::FastWriter fastWriter; + std::string config = fastWriter.write( ret ); + JsonRpcFixture fixture( config ); + + dev::eth::simulateMining( *( fixture.client ), 20 ); + string senderAddress = toJS(fixture.coinbase.address()); + + Json::Value txRefill; + txRefill["to"] = "0x5EdF1e852fdD1B0Bc47C0307EF755C76f4B9c251"; + txRefill["from"] = senderAddress; + txRefill["gas"] = "100000"; + txRefill["gasPrice"] = fixture.rpcClient->eth_gasPrice(); + txRefill["value"] = 1000000; + string txHash = fixture.rpcClient->eth_sendTransaction( txRefill ); + dev::eth::mineTransaction( *( fixture.client ), 1 ); + + Json::Value receipt = fixture.rpcClient->eth_getTransactionReceipt( txHash ); + BOOST_REQUIRE( receipt["status"] == string( "0x1" ) ); + BOOST_REQUIRE( receipt["type"] == "0x0" ); + + auto accessList = fixture.rpcClient->eth_createAccessList( txRefill, "latest" ); + BOOST_REQUIRE( accessList.isMember( "accessList" ) && accessList.isMember( "gasUsed" ) ); + BOOST_REQUIRE( accessList["accessList"].isArray() && accessList["accessList"].size() == 0 ); + BOOST_REQUIRE( accessList["gasUsed"].isString() ); +} + +BOOST_AUTO_TEST_CASE( eip1559RpcMethods ) { + std::string _config = c_genesisConfigString; + Json::Value ret; + Json::Reader().parse( _config, ret ); + + // Set chainID = 151 + ret["params"]["chainID"] = "0x97"; + + Json::FastWriter fastWriter; + std::string config = fastWriter.write( ret ); + JsonRpcFixture fixture( config ); + + dev::eth::simulateMining( *( fixture.client ), 20 ); + string senderAddress = toJS(fixture.coinbase.address()); + + Json::Value txRefill; + txRefill["to"] = "0x5EdF1e852fdD1B0Bc47C0307EF755C76f4B9c251"; + txRefill["from"] = senderAddress; + txRefill["gas"] = "100000"; + txRefill["gasPrice"] = fixture.rpcClient->eth_gasPrice(); + txRefill["value"] = 100000000000000000; + for (size_t i = 0; i < 10; ++i) { + // mine 10 blocks + string txHash = fixture.rpcClient->eth_sendTransaction( txRefill ); + dev::eth::mineTransaction( *( fixture.client ), 1 ); + } + + BOOST_REQUIRE( fixture.rpcClient->eth_maxPriorityFeePerGas() == "0x0" ); + + auto bn = fixture.client->number(); + + Json::Value percentiles = Json::Value( Json::arrayValue ); + percentiles.resize( 2 ); + percentiles[0] = 20; + percentiles[1] = 80; + + size_t blockCnt = 3; + auto feeHistory = fixture.rpcClient->eth_feeHistory( toJS( blockCnt ), "latest", percentiles ); + + BOOST_REQUIRE( feeHistory["oldestBlock"] == toJS( bn - blockCnt + 1 ) ); + + BOOST_REQUIRE( feeHistory.isMember( "baseFeePerGas" ) ); + BOOST_REQUIRE( feeHistory["baseFeePerGas"].isArray() ); + + for (Json::Value::ArrayIndex i = 0; i < blockCnt; ++i) { + BOOST_REQUIRE( feeHistory["baseFeePerGas"][i].isString() ); + BOOST_REQUIRE_GT( feeHistory["gasUsedRatio"][i].asDouble(), 0 ); + BOOST_REQUIRE_GT( 1, feeHistory["gasUsedRatio"][i].asDouble() ); + for ( Json::Value::ArrayIndex j = 0; j < percentiles.size(); ++j ) { + BOOST_REQUIRE_EQUAL( feeHistory["reward"][i][j].asString(), toJS( 0 ) ); + } + } +} + BOOST_AUTO_TEST_CASE( etherbase_generation2 ) { JsonRpcFixture fixture(c_genesisGeneration2ConfigString, false, false, true); string etherbase = fixture.rpcClient->eth_coinbase(); From 5233f5f475dea44101e9c0a7b1380bbe1f895a61 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 15 Apr 2024 17:22:19 +0100 Subject: [PATCH 19/53] #1719 add more tests --- libethcore/TransactionBase.cpp | 8 ++++---- libweb3jsonrpc/JsonHelper.cpp | 19 +++++++++++++++++++ .../libweb3jsonrpc/WebThreeStubClient.cpp | 10 ++++++++++ .../libweb3jsonrpc/WebThreeStubClient.h | 1 + test/unittests/libweb3jsonrpc/jsonrpc.cpp | 16 +++++++++++++++- 5 files changed, 49 insertions(+), 5 deletions(-) diff --git a/libethcore/TransactionBase.cpp b/libethcore/TransactionBase.cpp index cf50ea140..33bfd709e 100644 --- a/libethcore/TransactionBase.cpp +++ b/libethcore/TransactionBase.cpp @@ -202,12 +202,12 @@ TransactionBase TransactionBase::makeType1Transaction( if ( _checkSig == CheckTransaction::Everything ) m_sender = sender(); - m_txType = TransactionType::Type1; - if ( rlp.itemCount() > 11 ) BOOST_THROW_EXCEPTION( InvalidTransactionFormat() << errinfo_comment( "too many fields in the transaction RLP" ) ); + m_txType = TransactionType::Type1; + TransactionBase t( *this ); return t; } catch ( Exception& _e ) { @@ -271,12 +271,12 @@ TransactionBase TransactionBase::makeType2Transaction( if ( _checkSig == CheckTransaction::Everything ) m_sender = sender(); - m_txType = TransactionType::Type2; - if ( rlp.itemCount() > 12 ) BOOST_THROW_EXCEPTION( InvalidTransactionFormat() << errinfo_comment( "too many fields in the transaction RLP" ) ); + m_txType = TransactionType::Type2; + TransactionBase t( *this ); return t; } catch ( Exception& _e ) { diff --git a/libweb3jsonrpc/JsonHelper.cpp b/libweb3jsonrpc/JsonHelper.cpp index 012352a8e..844a1ffec 100644 --- a/libweb3jsonrpc/JsonHelper.cpp +++ b/libweb3jsonrpc/JsonHelper.cpp @@ -348,6 +348,25 @@ Json::Value toJson( dev::eth::Transaction const& _t ) { res["r"] = toJS( _t.signature().r ); res["s"] = toJS( _t.signature().s ); res["v"] = toJS( _t.signature().v ); + res["type"] = toJS( int( _t.txType() ) ); + if ( _t.txType() != dev::eth::TransactionType::Legacy ) { + res["yParity"] = res["v"].asString(); + res["accessList"] = Json::Value( Json::arrayValue ); + for ( const auto& d : _t.accessList() ) { + auto list = d.toList(); + Json::Value accessList; + accessList["address"] = dev::toHexPrefixed( list[0].toBytes() ); + accessList["storageKeys"] = Json::Value( Json::arrayValue ); + for ( const auto& k : list[1].toList() ) { + accessList["storageKeys"].append( dev::toHexPrefixed( k.toBytes() ) ); + } + res["accessList"].append( accessList ); + } + if ( _t.txType() != dev::eth::TransactionType::Type1 ) { + res["maxPriorityFeePerGas"] = toJS( _t.maxPriorityFeePerGas() ); + res["maxFeePerGas"] = toJS( _t.maxPriorityFeePerGas() ); + } + } } res["hash"] = toJS( _t.sha3( WithSignature ) ); diff --git a/test/unittests/libweb3jsonrpc/WebThreeStubClient.cpp b/test/unittests/libweb3jsonrpc/WebThreeStubClient.cpp index d41d85927..046a67e90 100644 --- a/test/unittests/libweb3jsonrpc/WebThreeStubClient.cpp +++ b/test/unittests/libweb3jsonrpc/WebThreeStubClient.cpp @@ -810,6 +810,16 @@ bool WebThreeStubClient::eth_notePassword( const std::string& param1 ) { jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString() ); } +Json::Value WebThreeStubClient::eth_pendingTransactions() { + Json::Value p; + Json::Value result = this->CallMethod( "eth_pendingTransactions", p ); + if ( result.isArray() ) + return result; + else + throw jsonrpc::JsonRpcException( + jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString() ); +} + std::string WebThreeStubClient::eth_maxPriorityFeePerGas() { Json::Value p; Json::Value result = this->CallMethod( "eth_maxPriorityFeePerGas", p ); diff --git a/test/unittests/libweb3jsonrpc/WebThreeStubClient.h b/test/unittests/libweb3jsonrpc/WebThreeStubClient.h index b23fb20ab..2f144a25e 100644 --- a/test/unittests/libweb3jsonrpc/WebThreeStubClient.h +++ b/test/unittests/libweb3jsonrpc/WebThreeStubClient.h @@ -94,6 +94,7 @@ class WebThreeStubClient : public jsonrpc::Client { Json::Value eth_unsubscribe( const Json::Value& param1 ) noexcept( false ); Json::Value setSchainExitTime( const Json::Value& param1 ) noexcept( false ); Json::Value eth_inspectTransaction( const std::string& param1 ) noexcept( false ); + Json::Value eth_pendingTransactions() noexcept( false ); std::string eth_sendRawTransaction( const std::string& param1 ) noexcept( false ); std::string eth_maxPriorityFeePerGas() noexcept( false ); Json::Value eth_createAccessList( const Json::Value& param1, const std::string& param2 ) noexcept( false ); diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index 503657be0..771c1faf7 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -2642,6 +2642,10 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { // send 1 WEI from 0xc868AF52a6549c773082A334E5AE232e0Ea3B513 to 0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b // encoded type 1 txn txHash = fixture.rpcClient->eth_sendRawTransaction( "0x01f8678197808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180c001a01ebdc546c8b85511b7ba831f47c4981069d7af972d10b7dce2c57225cb5df6a7a055ae1e84fea41d37589eb740a0a93017a5cd0e9f10ee50f165bf4b1b4c78ddae" ); + auto pendingTransactions = fixture.rpcClient->eth_pendingTransactions(); + BOOST_REQUIRE( pendingTransactions.isArray() && pendingTransactions.size() == 1); + BOOST_REQUIRE( pendingTransactions[0]["type"] == "0x1" ); + BOOST_REQUIRE( pendingTransactions[0].isMember( "yParity" ) && pendingTransactions[0].isMember( "accessList" ) ); dev::eth::mineTransaction( *( fixture.client ), 1 ); // compare with txn hash from geth @@ -2693,6 +2697,10 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { // now the same txn with accessList and increased nonce // [ { 'address': HexBytes( "0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae" ), 'storageKeys': ( "0x0000000000000000000000000000000000000000000000000000000000000003", "0x0000000000000000000000000000000000000000000000000000000000000007" ) } ] txHash = fixture.rpcClient->eth_sendRawTransaction( "0x01f8c38197018504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0b03eaf481958e22fc39bd1d526eb9255be1e6625614f02ca939e51c3d7e64bcaa05f675640c04bb050d27bd1f39c07b6ff742311b04dab760bb3bc206054332879" ); + pendingTransactions = fixture.rpcClient->eth_pendingTransactions(); + BOOST_REQUIRE( pendingTransactions.isArray() && pendingTransactions.size() == 1); + BOOST_REQUIRE( pendingTransactions[0]["type"] == "0x1" ); + BOOST_REQUIRE( pendingTransactions[0].isMember( "yParity" ) && pendingTransactions[0].isMember( "accessList" ) ); dev::eth::mineTransaction( *( fixture.client ), 1 ); // compare with txn hash from geth @@ -2759,12 +2767,18 @@ BOOST_AUTO_TEST_CASE( eip1559Transactions ) { BOOST_REQUIRE( fixture.rpcClient->eth_getBalance( "0x5EdF1e852fdD1B0Bc47C0307EF755C76f4B9c251", "latest" ) == "0x16345785d8a0000" ); // send 1 WEI from 0x5EdF1e852fdD1B0Bc47C0307EF755C76f4B9c251 to 0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b - // encoded type 1 txn + // encoded type 2 txn txHash = fixture.rpcClient->eth_sendRawTransaction( "0x02f8c98197808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0f1a407dfc1a9f782001d89f617e9b3a2f295378533784fb39960dea60beea2d0a05ac3da2946554ba3d5721850f4f89ee7a0c38e4acab7130908e7904d13174388" ); + auto pendingTransactions = fixture.rpcClient->eth_pendingTransactions(); + BOOST_REQUIRE( pendingTransactions.isArray() && pendingTransactions.size() == 1); + BOOST_REQUIRE( pendingTransactions[0]["type"] == "0x2" ); + BOOST_REQUIRE( pendingTransactions[0].isMember( "yParity" ) && pendingTransactions[0].isMember( "accessList" ) ); + BOOST_REQUIRE( pendingTransactions[0].isMember( "maxFeePerGas" ) && pendingTransactions[0].isMember( "maxPriorityFeePerGas" ) ); dev::eth::mineTransaction( *( fixture.client ), 1 ); // compare with txn hash from geth BOOST_REQUIRE( txHash == "0x7bd586e93e3012577de4ba33e3b887baf520cbb92c5dd10996b262f9c5c8f747" ); + std::cout << dev::toHexPrefixed( fixture.client->transactions( 3 )[0].rlp() ) << '\n'; BOOST_REQUIRE( dev::toHexPrefixed( fixture.client->transactions( 3 )[0].rlp() ) == "0x02f8c98197808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0f1a407dfc1a9f782001d89f617e9b3a2f295378533784fb39960dea60beea2d0a05ac3da2946554ba3d5721850f4f89ee7a0c38e4acab7130908e7904d13174388" ); BOOST_REQUIRE( fixture.rpcClient->eth_getBalance( "0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b", "latest" ) == "0x1" ); From fcd17363b7d0cf134b622999e9c0a3539110aad5 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 15 Apr 2024 19:24:38 +0100 Subject: [PATCH 20/53] #1719 fix accessList in transaction object --- libethcore/TransactionBase.cpp | 24 +++++++++++++++++++----- libethcore/TransactionBase.h | 7 ++++--- libweb3jsonrpc/JsonHelper.cpp | 6 +++--- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/libethcore/TransactionBase.cpp b/libethcore/TransactionBase.cpp index 33bfd709e..a89eaf110 100644 --- a/libethcore/TransactionBase.cpp +++ b/libethcore/TransactionBase.cpp @@ -36,16 +36,17 @@ using namespace std; using namespace dev; using namespace dev::eth; -RLPs validateAccessListRLP( const RLP& data ) { +std::vector< bytes > validateAccessListRLP( const RLP& data ) { if ( !data.isList() ) BOOST_THROW_EXCEPTION( InvalidTransactionFormat() << errinfo_comment( "transaction accessList RLP must be a list" ) ); auto rlpList = data.toList(); if ( rlpList.empty() ) { // empty accessList, ignore it - return rlpList; + return {}; } + for ( const auto& d : rlpList ) { if ( !d.isList() ) BOOST_THROW_EXCEPTION( InvalidTransactionFormat() << errinfo_comment( @@ -65,7 +66,12 @@ RLPs validateAccessListRLP( const RLP& data ) { "transaction storageKeys RLP must be a list of byte array" ) ); } - return rlpList; + std::vector< bytes > accessList( rlpList.size() ); + for ( size_t i = 0; i < rlpList.size(); ++i ) { + accessList[i] = rlpList.at( i ).data().toBytes(); + } + + return accessList; } TransactionBase::TransactionBase( TransactionSkeleton const& _ts, Secret const& _s ) @@ -416,7 +422,11 @@ void TransactionBase::streamType1Transaction( RLPStream& _s, IncludeSignature _s _s << ""; _s << m_value << m_data; - _s << m_accessList; + dev::RLPs accessList( m_accessList.size() ); + for ( size_t i = 0; i < m_accessList.size(); ++i ) { + accessList[i] = RLP( m_accessList[i] ); + } + _s << accessList; if ( _sig ) _s << ( u256 ) m_vrs->v << ( u256 ) m_vrs->r << ( u256 ) m_vrs->s; @@ -431,7 +441,11 @@ void TransactionBase::streamType2Transaction( RLPStream& _s, IncludeSignature _s _s << ""; _s << m_value << m_data; - _s << m_accessList; + dev::RLPs accessList( m_accessList.size() ); + for ( size_t i = 0; i < m_accessList.size(); ++i ) { + accessList[i] = RLP( m_accessList[i] ); + } + _s << accessList; if ( _sig ) _s << ( u256 ) m_vrs->v << ( u256 ) m_vrs->r << ( u256 ) m_vrs->s; diff --git a/libethcore/TransactionBase.h b/libethcore/TransactionBase.h index 0f262fac6..55968a8e2 100644 --- a/libethcore/TransactionBase.h +++ b/libethcore/TransactionBase.h @@ -260,7 +260,7 @@ class TransactionBase { TransactionType txType() const { return m_txType; } - RLPs accessList() const { return m_accessList; } + std::vector< bytes > accessList() const { return m_accessList; } u256 maxPriorityFeePerGas() const { return m_maxPriorityFeePerGas; } @@ -302,8 +302,9 @@ class TransactionBase { bytes m_data; ///< The data associated with the transaction, or the initialiser if it's a ///< creation transaction. bytes m_rawData; - RLPs m_accessList; ///< The access list. see more https://eips.ethereum.org/EIPS/eip-2930. Not - ///< valid for legacy txns + 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 diff --git a/libweb3jsonrpc/JsonHelper.cpp b/libweb3jsonrpc/JsonHelper.cpp index 844a1ffec..ef97db47e 100644 --- a/libweb3jsonrpc/JsonHelper.cpp +++ b/libweb3jsonrpc/JsonHelper.cpp @@ -110,7 +110,7 @@ Json::Value toJson( dev::eth::Transaction const& _t, std::pair< h256, unsigned > res["yParity"] = res["v"].asString(); res["accessList"] = Json::Value( Json::arrayValue ); for ( const auto& d : _t.accessList() ) { - auto list = d.toList(); + auto list = RLP( d ); Json::Value accessList; accessList["address"] = dev::toHexPrefixed( list[0].toBytes() ); accessList["storageKeys"] = Json::Value( Json::arrayValue ); @@ -353,7 +353,7 @@ Json::Value toJson( dev::eth::Transaction const& _t ) { res["yParity"] = res["v"].asString(); res["accessList"] = Json::Value( Json::arrayValue ); for ( const auto& d : _t.accessList() ) { - auto list = d.toList(); + auto list = RLP( d ); Json::Value accessList; accessList["address"] = dev::toHexPrefixed( list[0].toBytes() ); accessList["storageKeys"] = Json::Value( Json::arrayValue ); @@ -405,7 +405,7 @@ Json::Value toJson( dev::eth::LocalisedTransaction const& _t ) { res["yParity"] = res["v"].asString(); res["accessList"] = Json::Value( Json::arrayValue ); for ( const auto& d : _t.accessList() ) { - auto list = d.toList(); + auto list = RLP( d ); Json::Value accessList; accessList["address"] = dev::toHexPrefixed( list[0].toBytes() ); accessList["storageKeys"] = Json::Value( Json::arrayValue ); From 45bac482070e0dc30ee4f2a17ec32ec20b5e41b4 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 15 Apr 2024 19:30:13 +0100 Subject: [PATCH 21/53] #1719 fix accessList in transaction object --- libethcore/TransactionBase.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libethcore/TransactionBase.cpp b/libethcore/TransactionBase.cpp index a89eaf110..ffb0a2350 100644 --- a/libethcore/TransactionBase.cpp +++ b/libethcore/TransactionBase.cpp @@ -74,6 +74,14 @@ std::vector< bytes > validateAccessListRLP( const RLP& data ) { return accessList; } +dev::RLPs accessListToRLPs( const std::vector< bytes >& _accessList ) { + dev::RLPs accessList( _accessList.size() ); + for ( size_t i = 0; i < _accessList.size(); ++i ) { + accessList[i] = RLP( _accessList[i] ); + } + return accessList; +} + TransactionBase::TransactionBase( TransactionSkeleton const& _ts, Secret const& _s ) : m_nonce( _ts.nonce ), m_value( _ts.value ), @@ -422,11 +430,7 @@ void TransactionBase::streamType1Transaction( RLPStream& _s, IncludeSignature _s _s << ""; _s << m_value << m_data; - dev::RLPs accessList( m_accessList.size() ); - for ( size_t i = 0; i < m_accessList.size(); ++i ) { - accessList[i] = RLP( m_accessList[i] ); - } - _s << accessList; + _s << accessListToRLPs( m_accessList ); if ( _sig ) _s << ( u256 ) m_vrs->v << ( u256 ) m_vrs->r << ( u256 ) m_vrs->s; @@ -441,11 +445,7 @@ void TransactionBase::streamType2Transaction( RLPStream& _s, IncludeSignature _s _s << ""; _s << m_value << m_data; - dev::RLPs accessList( m_accessList.size() ); - for ( size_t i = 0; i < m_accessList.size(); ++i ) { - accessList[i] = RLP( m_accessList[i] ); - } - _s << accessList; + _s << accessListToRLPs( m_accessList ); if ( _sig ) _s << ( u256 ) m_vrs->v << ( u256 ) m_vrs->r << ( u256 ) m_vrs->s; From 057d494ca12c182ab23af6d68c1cb8e87722756b Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Mon, 15 Apr 2024 20:05:31 +0100 Subject: [PATCH 22/53] SKALED-1719 Some code rearrangement --- libethcore/TransactionBase.cpp | 31 ++++++++----------------------- libethcore/TransactionBase.h | 15 ++++++--------- 2 files changed, 14 insertions(+), 32 deletions(-) diff --git a/libethcore/TransactionBase.cpp b/libethcore/TransactionBase.cpp index 33bfd709e..cdbe872b9 100644 --- a/libethcore/TransactionBase.cpp +++ b/libethcore/TransactionBase.cpp @@ -81,7 +81,7 @@ TransactionBase::TransactionBase( TransactionSkeleton const& _ts, Secret const& sign( _s ); } -TransactionBase TransactionBase::makeLegacyTransaction( +void TransactionBase::fillFromRlpLegacy( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ) { RLP const rlp( _rlpData ); try { @@ -141,9 +141,6 @@ TransactionBase TransactionBase::makeLegacyTransaction( BOOST_THROW_EXCEPTION( InvalidTransactionFormat() << errinfo_comment( "too many fields in the transaction RLP" ) ); // XXX Strange "catch"-s %) - - TransactionBase t( *this ); - return t; } catch ( Exception& _e ) { _e << errinfo_name( "invalid transaction format: " + toString( rlp ) + " RLP: " + toHex( rlp.data() ) ); @@ -154,13 +151,11 @@ TransactionBase TransactionBase::makeLegacyTransaction( throw; else { cwarn << _e.what(); - TransactionBase t( *this ); - return t; } } } -TransactionBase TransactionBase::makeType1Transaction( +void TransactionBase::fillFromRlpType1( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ) { bytes croppedRlp( _rlpData.begin() + 1, _rlpData.end() ); RLP const rlp( croppedRlp ); @@ -207,9 +202,6 @@ TransactionBase TransactionBase::makeType1Transaction( << errinfo_comment( "too many fields in the transaction RLP" ) ); m_txType = TransactionType::Type1; - - TransactionBase t( *this ); - return t; } catch ( Exception& _e ) { _e << errinfo_name( "invalid transaction format: " + toString( rlp ) + " RLP: " + toHex( rlp.data() ) ); @@ -220,13 +212,11 @@ TransactionBase TransactionBase::makeType1Transaction( throw; else { cwarn << _e.what(); - TransactionBase t( *this ); - return t; } } } -TransactionBase TransactionBase::makeType2Transaction( +void TransactionBase::fillFromRlpType2( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ) { bytes croppedRlp( _rlpData.begin() + 1, _rlpData.end() ); RLP const rlp( croppedRlp ); @@ -276,9 +266,6 @@ TransactionBase TransactionBase::makeType2Transaction( << errinfo_comment( "too many fields in the transaction RLP" ) ); m_txType = TransactionType::Type2; - - TransactionBase t( *this ); - return t; } catch ( Exception& _e ) { _e << errinfo_name( "invalid transaction format: " + toString( rlp ) + " RLP: " + toHex( rlp.data() ) ); @@ -289,23 +276,21 @@ TransactionBase TransactionBase::makeType2Transaction( throw; else { cwarn << _e.what(); - TransactionBase t( *this ); - return t; } } } -TransactionBase::TransactionBase( +void TransactionBase::fillFromRlpByType( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid, TransactionType type ) { switch ( type ) { case TransactionType::Legacy: - *this = makeLegacyTransaction( _rlpData, _checkSig, _allowInvalid ); + fillFromRlpLegacy( _rlpData, _checkSig, _allowInvalid ); break; case TransactionType::Type1: - *this = makeType1Transaction( _rlpData, _checkSig, _allowInvalid ); + fillFromRlpType1( _rlpData, _checkSig, _allowInvalid ); break; case TransactionType::Type2: - *this = makeType2Transaction( _rlpData, _checkSig, _allowInvalid ); + fillFromRlpType2( _rlpData, _checkSig, _allowInvalid ); break; default: BOOST_THROW_EXCEPTION( @@ -327,7 +312,7 @@ TransactionBase::TransactionBase( MICROPROFILE_SCOPEI( "TransactionBase", "ctor", MP_GOLD2 ); try { TransactionType txnType = getTransactionType( _rlpData ); - *this = TransactionBase( _rlpData, _checkSig, _allowInvalid, txnType ); + fillFromRlpByType( _rlpData, _checkSig, _allowInvalid, txnType ); } catch ( ... ) { m_type = Type::Invalid; RLPStream s; diff --git a/libethcore/TransactionBase.h b/libethcore/TransactionBase.h index 0f262fac6..accdeb2ae 100644 --- a/libethcore/TransactionBase.h +++ b/libethcore/TransactionBase.h @@ -106,10 +106,6 @@ class TransactionBase { bytes const& _rlp, CheckTransaction _checkSig, bool _allowInvalid = false ) : TransactionBase( &_rlp, _checkSig, _allowInvalid ) {} - /// Constructs a transaction from the given RLP and transaction type. - TransactionBase( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid, - TransactionType type ); - TransactionBase( TransactionBase const& ) = default; /// Checks equality of transactions. @@ -313,12 +309,13 @@ class TransactionBase { private: static TransactionType getTransactionType( bytesConstRef _rlp ); - TransactionBase makeLegacyTransaction( - bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ); - TransactionBase makeType1Transaction( - bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ); - TransactionBase makeType2Transaction( + /// Constructs a transaction from the given RLP and transaction type. + void fillFromRlpByType( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid, + TransactionType type ); + void fillFromRlpLegacy( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ); + void fillFromRlpType1( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ); + void fillFromRlpType2( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ); void streamLegacyTransaction( RLPStream& _s, IncludeSignature _sig, bool _forEip155hash ) const; void streamType1Transaction( RLPStream& _s, IncludeSignature _sig ) const; From f86098f203341163d81f22059b664aabf78a5901 Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Tue, 16 Apr 2024 18:50:58 +0100 Subject: [PATCH 23/53] SKALED-1719 Hide streamRlp() --- libethcore/TransactionBase.h | 13 +++++++------ libethereum/Block.cpp | 4 +--- libweb3jsonrpc/Eth.cpp | 4 +--- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/libethcore/TransactionBase.h b/libethcore/TransactionBase.h index accdeb2ae..1aedf89b0 100644 --- a/libethcore/TransactionBase.h +++ b/libethcore/TransactionBase.h @@ -147,12 +147,6 @@ 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 { RLPStream s; @@ -308,7 +302,14 @@ class TransactionBase { 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 fillFromRlpByType( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid, TransactionType type ); diff --git a/libethereum/Block.cpp b/libethereum/Block.cpp index 05f0e77b3..176657f1e 100644 --- a/libethereum/Block.cpp +++ b/libethereum/Block.cpp @@ -973,9 +973,7 @@ void Block::commitToSeal( receipt( i ).streamRLP( receiptrlp ); receiptsMap.insert( std::make_pair( k.out(), receiptrlp.out() ) ); - RLPStream txrlp; - m_transactions[i].streamRLP( txrlp ); - dev::bytes txOutput = txrlp.out(); + dev::bytes txOutput = m_transactions[i].rlp(); if ( m_transactions[i].txType() != dev::eth::TransactionType::Legacy ) { txOutput.insert( txOutput.begin(), m_transactions[i].txType() ); RLPStream s; diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index 0bd42958e..fa249b3fc 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -391,9 +391,7 @@ Json::Value Eth::eth_signTransaction( Json::Value const& _json ) { ts = client()->populateTransactionWithDefaults( ts ); pair< bool, Secret > ar = m_ethAccounts.authenticate( ts ); Transaction t( ts, ar.second ); - RLPStream s; - t.streamRLP( s ); - return toJson( t, s.out() ); + return toJson( t, t.rlp() ); } catch ( Exception const& ) { throw JsonRpcException( exceptionToErrorMessage() ); } From e19191c96b52ce7daa6da8e5231c6156574d37ab Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Tue, 16 Apr 2024 19:06:29 +0100 Subject: [PATCH 24/53] SKALED-1719 Fix if --- libethereum/Block.cpp | 1 - libweb3jsonrpc/Eth.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libethereum/Block.cpp b/libethereum/Block.cpp index 176657f1e..491297a51 100644 --- a/libethereum/Block.cpp +++ b/libethereum/Block.cpp @@ -975,7 +975,6 @@ void Block::commitToSeal( dev::bytes txOutput = m_transactions[i].rlp(); if ( m_transactions[i].txType() != dev::eth::TransactionType::Legacy ) { - txOutput.insert( txOutput.begin(), m_transactions[i].txType() ); RLPStream s; s.append( txOutput ); txOutput = s.out(); diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index fa249b3fc..f6fe2a06d 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -390,7 +390,7 @@ Json::Value Eth::eth_signTransaction( Json::Value const& _json ) { setTransactionDefaults( ts ); ts = client()->populateTransactionWithDefaults( ts ); pair< bool, Secret > ar = m_ethAccounts.authenticate( ts ); - Transaction t( ts, ar.second ); + Transaction t( ts, ar.second ); // always legacy, no prefix byte return toJson( t, t.rlp() ); } catch ( Exception const& ) { throw JsonRpcException( exceptionToErrorMessage() ); From 58aa4640f09358ae546fdd6e06d4bcfbbd0d0606 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 17 Apr 2024 13:33:38 +0100 Subject: [PATCH 25/53] #1719 add gasPrice check for type2 transactions --- libethcore/TransactionBase.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libethcore/TransactionBase.cpp b/libethcore/TransactionBase.cpp index ffb0a2350..904e00a8d 100644 --- a/libethcore/TransactionBase.cpp +++ b/libethcore/TransactionBase.cpp @@ -253,6 +253,10 @@ TransactionBase TransactionBase::makeType2Transaction( m_nonce = rlp[1].toInt< u256 >(); m_maxPriorityFeePerGas = rlp[2].toInt< u256 >(); m_maxFeePerGas = rlp[3].toInt< u256 >(); + if ( m_maxPriorityFeePerGas > m_maxPriorityFeePerGas ) + BOOST_THROW_EXCEPTION( InvalidTransactionFormat() << errinfo_comment( + "maxFeePerGas cannot be less than maxPriorityFeePerGas (The " + "total must be the larger of the two)" ) ); // set m_gasPrice as SKALE ignores priority fees m_gasPrice = m_maxFeePerGas; m_gas = rlp[4].toInt< u256 >(); From bc9cd391c21b283f7361604dd2302406aeb179f5 Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Wed, 17 Apr 2024 16:35:45 +0100 Subject: [PATCH 26/53] SKALED-1719 More prettifying --- libethcore/TransactionBase.h | 4 +- libethereum/Block.cpp | 2 +- libethereum/SkaleHost.cpp | 6 +- libethereum/TransactionQueue.cpp | 16 +-- libweb3jsonrpc/Eth.cpp | 2 +- skale-key/KeyAux.h | 4 +- test/tools/jsontests/BlockChainTests.cpp | 2 +- test/tools/libtesteth/BlockChainHelper.cpp | 13 +- test/unittests/libdevcrypto/crypto.cpp | 4 +- test/unittests/libethereum/SkaleHost.cpp | 121 ++++-------------- test/unittests/libethereum/Transaction.cpp | 31 ++--- .../libethereum/TransactionQueue.cpp | 66 +++++----- test/unittests/libweb3jsonrpc/jsonrpc.cpp | 32 ++--- .../mapreduce_consensus/ConsensusEngine.cpp | 2 +- 14 files changed, 108 insertions(+), 197 deletions(-) diff --git a/libethcore/TransactionBase.h b/libethcore/TransactionBase.h index 2394f3edc..d316e3e01 100644 --- a/libethcore/TransactionBase.h +++ b/libethcore/TransactionBase.h @@ -148,9 +148,9 @@ class TransactionBase { bool isCreation() const { return m_type == ContractCreation; } /// @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 ); + streamRLP( s, _sig, _forEip155hash ); bytes output = s.out(); if ( m_txType != TransactionType::Legacy ) output.insert( output.begin(), m_txType ); diff --git a/libethereum/Block.cpp b/libethereum/Block.cpp index 491297a51..f3a7d9bc1 100644 --- a/libethereum/Block.cpp +++ b/libethereum/Block.cpp @@ -973,7 +973,7 @@ void Block::commitToSeal( receipt( i ).streamRLP( receiptrlp ); receiptsMap.insert( std::make_pair( k.out(), receiptrlp.out() ) ); - dev::bytes txOutput = m_transactions[i].rlp(); + dev::bytes txOutput = m_transactions[i].toBytes(); if ( m_transactions[i].txType() != dev::eth::TransactionType::Legacy ) { RLPStream s; s.append( txOutput ); diff --git a/libethereum/SkaleHost.cpp b/libethereum/SkaleHost.cpp index 4645cfee5..67c006b09 100644 --- a/libethereum/SkaleHost.cpp +++ b/libethereum/SkaleHost.cpp @@ -526,7 +526,7 @@ ConsensusExtFace::transactions_vector SkaleHost::pendingTransactions( m_m_transaction_cache[sha.asArray()] = txn; } - out_vector.push_back( txn.rlp() ); + out_vector.push_back( txn.toBytes() ); ++total_sent; @@ -892,7 +892,7 @@ void SkaleHost::broadcastFunc() { if ( !m_broadcastPauseFlag ) { MICROPROFILE_SCOPEI( "SkaleHost", "broadcastFunc.broadcast", MP_CHARTREUSE1 ); - std::string rlp = toJS( txn.rlp() ); + std::string rlp = toJS( txn.toBytes() ); std::string h = toJS( txn.sha3() ); // std::string strPerformanceQueueName = "bc/broadcast"; @@ -995,7 +995,7 @@ void SkaleHost::forceEmptyBlock() { } void SkaleHost::forcedBroadcast( const Transaction& _txn ) { - m_broadcaster->broadcast( toJS( _txn.rlp() ) ); + m_broadcaster->broadcast( toJS( _txn.toBytes() ) ); } void SkaleHost::noteNewTransactions() {} diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 6a075bf84..284e5c648 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -134,7 +134,7 @@ ImportResult TransactionQueue::import( // if( t == fs->second.begin() ){ UpgradeGuard ul( l ); --m_futureSize; - m_futureSizeBytes -= t->second.transaction.rlp().size(); + m_futureSizeBytes -= t->second.transaction.toBytes().size(); auto erasedHash = t->second.transaction.sha3(); LOG( m_loggerDetail ) << "Re-inserting future transaction " << erasedHash; m_known.erase( erasedHash ); @@ -327,7 +327,7 @@ void TransactionQueue::insertCurrent_WITH_LOCK( std::pair< h256, Transaction > c inserted.first->second = handle; m_currentByHash[_p.first] = handle; #pragma GCC diagnostic pop - m_currentSizeBytes += t.rlp().size(); + m_currentSizeBytes += t.toBytes().size(); // Move following transactions from future to current makeCurrent_WITH_LOCK( t ); @@ -345,7 +345,7 @@ bool TransactionQueue::remove_WITH_LOCK( h256 const& _txHash ) { auto it = m_currentByAddressAndNonce.find( from ); assert( it != m_currentByAddressAndNonce.end() ); it->second.erase( ( *t->second ).transaction.nonce() ); - m_currentSizeBytes -= ( *t->second ).transaction.rlp().size(); + m_currentSizeBytes -= ( *t->second ).transaction.toBytes().size(); m_current.erase( t->second ); m_currentByHash.erase( t ); if ( it->second.empty() ) @@ -382,8 +382,8 @@ void TransactionQueue::setFuture_WITH_LOCK( h256 const& _txHash ) { *( m->second ) ); // set has only const iterators. Since we are moving out of container // that's fine m_currentByHash.erase( t.transaction.sha3() ); - m_currentSizeBytes -= t.transaction.rlp().size(); - m_futureSizeBytes += t.transaction.rlp().size(); + m_currentSizeBytes -= t.transaction.toBytes().size(); + m_futureSizeBytes += t.transaction.toBytes().size(); target.emplace( t.transaction.nonce(), move( t ) ); m_current.erase( m->second ); ++m_futureSize; @@ -396,7 +396,7 @@ void TransactionQueue::setFuture_WITH_LOCK( h256 const& _txHash ) { // TODO: priority queue for future transactions // For now just drop random chain end --m_futureSize; - m_futureSizeBytes -= m_future.begin()->second.rbegin()->second.transaction.rlp().size(); + m_futureSizeBytes -= m_future.begin()->second.rbegin()->second.transaction.toBytes().size(); auto erasedHash = m_future.begin()->second.rbegin()->second.transaction.sha3(); LOG( m_loggerDetail ) << "Dropping out of bounds future transaction " << erasedHash; m_known.erase( erasedHash ); @@ -430,8 +430,8 @@ void TransactionQueue::makeCurrent_WITH_LOCK( Transaction const& _t ) { inserted.first->second = handle; m_currentByHash[( *handle ).transaction.sha3()] = handle; #pragma GCC diagnostic pop - m_futureSizeBytes -= ( *handle ).transaction.rlp().size(); - m_currentSizeBytes += ( *handle ).transaction.rlp().size(); + m_futureSizeBytes -= ( *handle ).transaction.toBytes().size(); + m_currentSizeBytes += ( *handle ).transaction.toBytes().size(); --m_futureSize; ++ft; ++nonce; diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index f6fe2a06d..241816098 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -391,7 +391,7 @@ Json::Value Eth::eth_signTransaction( Json::Value const& _json ) { ts = client()->populateTransactionWithDefaults( ts ); pair< bool, Secret > ar = m_ethAccounts.authenticate( ts ); Transaction t( ts, ar.second ); // always legacy, no prefix byte - return toJson( t, t.rlp() ); + return toJson( t, t.toBytes() ); } catch ( Exception const& ) { throw JsonRpcException( exceptionToErrorMessage() ); } diff --git a/skale-key/KeyAux.h b/skale-key/KeyAux.h index 980ba64c9..3ce52128a 100644 --- a/skale-key/KeyAux.h +++ b/skale-key/KeyAux.h @@ -347,10 +347,10 @@ class KeyCLI { t.sign( s ); cout << t.sha3() << ": "; if ( isFile ) { - writeFile( i + ".signed", toHex( t.rlp() ) ); + writeFile( i + ".signed", toHex( t.toBytes() ) ); cout << i + ".signed" << endl; } else - cout << toHex( t.rlp() ) << endl; + cout << toHex( t.toBytes() ) << endl; } catch ( Exception& ex ) { cerr << "Invalid transaction: " << ex.what() << endl; } diff --git a/test/tools/jsontests/BlockChainTests.cpp b/test/tools/jsontests/BlockChainTests.cpp index ac9dc294f..100b46e52 100644 --- a/test/tools/jsontests/BlockChainTests.cpp +++ b/test/tools/jsontests/BlockChainTests.cpp @@ -958,7 +958,7 @@ void checkBlocks( BOOST_CHECK_MESSAGE( trField == trRlp, _testname + "transactions from rlp and transaction from field do not match" ); BOOST_CHECK_MESSAGE( - trField.rlp() == trRlp.rlp(), _testname + "transactions rlp do not match" ); + trField.toBytes() == trRlp.toBytes(), _testname + "transactions rlp do not match" ); } vector< TestBlock > const& unclesFromField = _blockFromFields.uncles(); diff --git a/test/tools/libtesteth/BlockChainHelper.cpp b/test/tools/libtesteth/BlockChainHelper.cpp index 757ac6169..3bd1de9da 100644 --- a/test/tools/libtesteth/BlockChainHelper.cpp +++ b/test/tools/libtesteth/BlockChainHelper.cpp @@ -72,7 +72,7 @@ TestBlock::TestBlock( std::string const& _blockRLP ) : TestBlock() { for ( auto const& tr : root[1] ) { Transaction tx( tr.data(), CheckTransaction::Everything ); TestTransaction testTx( tx ); - m_transactionQueue.import( tx.rlp() ); + m_transactionQueue.import( tx.toBytes() ); m_testTransactions.push_back( testTx ); } @@ -121,7 +121,7 @@ void TestBlock::setState( State const& _state ) { void TestBlock::addTransaction( TestTransaction const& _tr ) { m_testTransactions.push_back( _tr ); - if ( m_transactionQueue.import( _tr.transaction().rlp() ) != ImportResult::Success ) + if ( m_transactionQueue.import( _tr.transaction().toBytes() ) != ImportResult::Success ) cnote << TestOutputHelper::get().testName() + " Test block failed importing transaction\n"; recalcBlockHeaderBytes(); } @@ -383,11 +383,8 @@ void TestBlock::recalcBlockHeaderBytes() { txList.push_back( txi ); RLPStream txStream; txStream.appendList( txList.size() ); - for ( unsigned i = 0; i < txList.size(); ++i ) { - RLPStream txrlp; - txList[i].streamRLP( txrlp ); - txStream.appendRaw( txrlp.out() ); - } + for ( unsigned i = 0; i < txList.size(); ++i ) + txStream.appendRaw( txList[i].toBytes() ); RLPStream uncleStream; uncleStream.appendList( m_uncles.size() ); @@ -444,7 +441,7 @@ void TestBlock::populateFrom( TestBlock const& _original ) { m_transactionQueue.clear(); TransactionQueue const& trQueue = _original.transactionQueue(); for ( auto const& txi : trQueue.topTransactions( std::numeric_limits< unsigned >::max() ) ) - m_transactionQueue.import( txi.rlp() ); + m_transactionQueue.import( txi.toBytes() ); m_uncles = _original.uncles(); m_blockHeader = _original.blockHeader(); diff --git a/test/unittests/libdevcrypto/crypto.cpp b/test/unittests/libdevcrypto/crypto.cpp index f8a85c56f..0fd4ab8c5 100644 --- a/test/unittests/libdevcrypto/crypto.cpp +++ b/test/unittests/libdevcrypto/crypto.cpp @@ -119,10 +119,10 @@ BOOST_AUTO_TEST_CASE( keypairs ) { p.address() == Address( fromHex( "8a40bfaa73256b60764c1bf40675a99083efb075" ) ) ); eth::Transaction t( 1000, 0, 0, h160( fromHex( "944400f4b88ac9589a0f17ed4671da26bddb668b" ) ), {}, 0, p.secret() ); - auto rlp = t.rlp( eth::WithoutSignature ); + auto rlp = t.toBytes( eth::WithoutSignature ); auto expectedRlp = "dc80808094944400f4b88ac9589a0f17ed4671da26bddb668b8203e880"; BOOST_CHECK_EQUAL( toHex( rlp ), expectedRlp ); - rlp = t.rlp( eth::WithSignature ); + rlp = t.toBytes( eth::WithSignature ); auto expectedRlp2 = "f85f80808094944400f4b88ac9589a0f17ed4671da26bddb668b8203e8801ca0bd2402a510c9c9afddf2a3f63c" "869573bd257475bea91d6f164638134a3386d6a0609ad9775fd2715e6a359c627e9338478e4adba65dd0dc6ef2" diff --git a/test/unittests/libethereum/SkaleHost.cpp b/test/unittests/libethereum/SkaleHost.cpp index 930339da0..2fd249013 100644 --- a/test/unittests/libethereum/SkaleHost.cpp +++ b/test/unittests/libethereum/SkaleHost.cpp @@ -177,9 +177,7 @@ struct SkaleHostFixture : public TestOutputHelperFixture { bytes bytes_from_json( const Json::Value& json ) { Transaction tx = tx_from_json( json ); - RLPStream stream; - tx.streamRLP( stream ); - return stream.out(); + return tx.toBytes(); } TransactionQueue* tq; @@ -259,9 +257,6 @@ BOOST_DATA_TEST_CASE( validTransaction, skipInvalidTransactionsVariants, skipInv pair< bool, Secret > ar = accountHolder->authenticate( ts ); Transaction tx( ts, ar.second ); - RLPStream stream; - tx.streamRLP( stream ); - h256 txHash = tx.sha3(); CHECK_NONCE_BEGIN( senderAddress ); @@ -269,7 +264,7 @@ BOOST_DATA_TEST_CASE( validTransaction, skipInvalidTransactionsVariants, skipInv CHECK_BLOCK_BEGIN; BOOST_REQUIRE_NO_THROW( - stub->createBlock( ConsensusExtFace::transactions_vector{stream.out()}, utcTime(), 1U ) ); + stub->createBlock( ConsensusExtFace::transactions_vector{tx.toBytes()}, utcTime(), 1U ) ); REQUIRE_BLOCK_INCREASE( 1 ); REQUIRE_BLOCK_SIZE( 1, 1 ); @@ -397,15 +392,12 @@ BOOST_DATA_TEST_CASE( transactionSigZero, skipInvalidTransactionsVariants, skipI VrsHackedTransaction* hacked_tx = reinterpret_cast< VrsHackedTransaction* >( &tx ); hacked_tx->resetSignature(); - RLPStream stream; - tx.streamRLP( stream, WithSignature ); - CHECK_NONCE_BEGIN( senderAddress ); CHECK_BALANCE_BEGIN( senderAddress ); CHECK_BLOCK_BEGIN; BOOST_REQUIRE_NO_THROW( - stub->createBlock( ConsensusExtFace::transactions_vector{stream.out()}, utcTime(), 1U ) ); + stub->createBlock( ConsensusExtFace::transactions_vector{tx.toBytes()}, utcTime(), 1U ) ); REQUIRE_BLOCK_INCREASE( 1 ); @@ -414,7 +406,7 @@ BOOST_DATA_TEST_CASE( transactionSigZero, skipInvalidTransactionsVariants, skipI } else { REQUIRE_BLOCK_SIZE( 1, 1 ); - h256 txHash = sha3( stream.out() ); + h256 txHash = sha3( tx.toBytes() ); REQUIRE_BLOCK_TRANSACTION( 1, 0, txHash ); } @@ -447,9 +439,7 @@ BOOST_DATA_TEST_CASE( transactionSigBad, skipInvalidTransactionsVariants, skipIn pair< bool, Secret > ar = accountHolder->authenticate( ts ); Transaction tx( ts, ar.second ); - RLPStream stream; - tx.streamRLP( stream ); - bytes data = stream.out(); + bytes data = tx.toBytes(); // TODO try to spoil other fields data[43] = 0x7f; // spoil v @@ -503,9 +493,6 @@ BOOST_DATA_TEST_CASE( transactionGasIncorrect, skipInvalidTransactionsVariants, pair< bool, Secret > ar = accountHolder->authenticate( ts ); Transaction tx( ts, ar.second ); - RLPStream stream; - tx.streamRLP( stream ); - h256 txHash = tx.sha3(); CHECK_NONCE_BEGIN( senderAddress ); @@ -513,7 +500,7 @@ BOOST_DATA_TEST_CASE( transactionGasIncorrect, skipInvalidTransactionsVariants, CHECK_BLOCK_BEGIN; BOOST_REQUIRE_NO_THROW( - stub->createBlock( ConsensusExtFace::transactions_vector{stream.out()}, utcTime(), 1U ) ); + stub->createBlock( ConsensusExtFace::transactions_vector{tx.toBytes()}, utcTime(), 1U ) ); REQUIRE_BLOCK_INCREASE( 1 ); @@ -572,9 +559,6 @@ BOOST_DATA_TEST_CASE( transactionGasNotEnough, skipInvalidTransactionsVariants, pair< bool, Secret > ar = accountHolder->authenticate( ts ); Transaction tx( ts, ar.second ); - RLPStream stream; - tx.streamRLP( stream ); - h256 txHash = tx.sha3(); CHECK_NONCE_BEGIN( senderAddress ); @@ -582,7 +566,7 @@ BOOST_DATA_TEST_CASE( transactionGasNotEnough, skipInvalidTransactionsVariants, CHECK_BLOCK_BEGIN; BOOST_REQUIRE_NO_THROW( - stub->createBlock( ConsensusExtFace::transactions_vector{stream.out()}, utcTime(), 1U ) ); + stub->createBlock( ConsensusExtFace::transactions_vector{tx.toBytes()}, utcTime(), 1U ) ); REQUIRE_BLOCK_INCREASE( 1 ); REQUIRE_BLOCK_SIZE( 1, 1 ); @@ -617,9 +601,6 @@ BOOST_DATA_TEST_CASE( transactionNonceBig, skipInvalidTransactionsVariants, skip pair< bool, Secret > ar = accountHolder->authenticate( ts ); Transaction tx( ts, ar.second ); - RLPStream stream; - tx.streamRLP( stream ); - h256 txHash = tx.sha3(); CHECK_NONCE_BEGIN( senderAddress ); @@ -627,7 +608,7 @@ BOOST_DATA_TEST_CASE( transactionNonceBig, skipInvalidTransactionsVariants, skip CHECK_BLOCK_BEGIN; BOOST_REQUIRE_NO_THROW( - stub->createBlock( ConsensusExtFace::transactions_vector{stream.out()}, utcTime(), 1U ) ); + stub->createBlock( ConsensusExtFace::transactions_vector{tx.toBytes()}, utcTime(), 1U ) ); REQUIRE_BLOCK_INCREASE( 1 ); @@ -669,12 +650,9 @@ BOOST_DATA_TEST_CASE( transactionNonceSmall, skipInvalidTransactionsVariants, sk pair< bool, Secret > ar = accountHolder->authenticate( ts ); Transaction tx1( ts, ar.second ); - RLPStream stream1; - tx1.streamRLP( stream1 ); - // create 1 txns in 1 block BOOST_REQUIRE_NO_THROW( - stub->createBlock( ConsensusExtFace::transactions_vector{stream1.out()}, utcTime(), 1U ) ); + stub->createBlock( ConsensusExtFace::transactions_vector{tx1.toBytes()}, utcTime(), 1U ) ); // now our test txn json["value"] = jsToDecimal( toJS( 9000 * dev::eth::szabo ) ); @@ -683,9 +661,6 @@ BOOST_DATA_TEST_CASE( transactionNonceSmall, skipInvalidTransactionsVariants, sk ar = accountHolder->authenticate( ts ); Transaction tx2( ts, ar.second ); - RLPStream stream2; - tx2.streamRLP( stream2 ); - h256 txHash = tx2.sha3(); CHECK_NONCE_BEGIN( senderAddress ); @@ -693,7 +668,7 @@ BOOST_DATA_TEST_CASE( transactionNonceSmall, skipInvalidTransactionsVariants, sk CHECK_BLOCK_BEGIN; BOOST_REQUIRE_NO_THROW( - stub->createBlock( ConsensusExtFace::transactions_vector{stream2.out()}, utcTime(), 2U ) ); + stub->createBlock( ConsensusExtFace::transactions_vector{tx2.toBytes()}, utcTime(), 2U ) ); REQUIRE_BLOCK_INCREASE( 1 ); @@ -733,9 +708,6 @@ BOOST_DATA_TEST_CASE( transactionBalanceBad, skipInvalidTransactionsVariants, sk pair< bool, Secret > ar = accountHolder->authenticate( ts ); Transaction tx( ts, ar.second ); - RLPStream stream; - tx.streamRLP( stream ); - h256 txHash = tx.sha3(); CHECK_NONCE_BEGIN( senderAddress ); @@ -743,7 +715,7 @@ BOOST_DATA_TEST_CASE( transactionBalanceBad, skipInvalidTransactionsVariants, sk CHECK_BLOCK_BEGIN; BOOST_REQUIRE_NO_THROW( - stub->createBlock( ConsensusExtFace::transactions_vector{stream.out()}, utcTime(), 1U ) ); + stub->createBlock( ConsensusExtFace::transactions_vector{tx.toBytes()}, utcTime(), 1U ) ); REQUIRE_BLOCK_INCREASE( 1 ); @@ -771,7 +743,7 @@ BOOST_DATA_TEST_CASE( transactionBalanceBad, skipInvalidTransactionsVariants, sk // make money dev::eth::simulateMining( *client, 1, senderAddress ); - stub->createBlock( ConsensusExtFace::transactions_vector{stream.out()}, utcTime(), 2U ); + stub->createBlock( ConsensusExtFace::transactions_vector{tx.toBytes()}, utcTime(), 2U ); REQUIRE_BLOCK_SIZE( 2, 1 ); REQUIRE_BLOCK_TRANSACTION( 2, 0, txHash ); @@ -810,9 +782,6 @@ BOOST_DATA_TEST_CASE( transactionGasBlockLimitExceeded, skipInvalidTransactionsV Transaction tx1 = tx_from_json( json ); - RLPStream stream1; - tx1.streamRLP( stream1 ); - h256 txHash1 = tx1.sha3(); // 2 txn @@ -822,9 +791,6 @@ BOOST_DATA_TEST_CASE( transactionGasBlockLimitExceeded, skipInvalidTransactionsV Transaction tx2 = tx_from_json( json ); - RLPStream stream2; - tx2.streamRLP( stream2 ); - h256 txHash2 = tx2.sha3(); CHECK_NONCE_BEGIN( senderAddress ); @@ -832,7 +798,7 @@ BOOST_DATA_TEST_CASE( transactionGasBlockLimitExceeded, skipInvalidTransactionsV CHECK_BLOCK_BEGIN; BOOST_REQUIRE_NO_THROW( stub->createBlock( - ConsensusExtFace::transactions_vector{stream1.out(), stream2.out()}, utcTime(), 1U ) ); + ConsensusExtFace::transactions_vector{tx1.toBytes(), tx2.toBytes()}, utcTime(), 1U ) ); BOOST_REQUIRE_EQUAL( client->number(), 1 ); REQUIRE_BLOCK_INCREASE( 1 ); @@ -873,28 +839,22 @@ BOOST_AUTO_TEST_CASE( gasLimitInBlockProposal ) { Transaction tx1 = tx_from_json( json ); - RLPStream stream1; - tx1.streamRLP( stream1 ); - // 2 txn json["from"] = toJS( account2.address() ); json["gas"] = jsToDecimal( toJS( client->chainParams().gasLimit - 21000 + 1 ) ); Transaction tx2 = tx_from_json( json ); - RLPStream stream2; - tx2.streamRLP( stream2 ); - // put already broadcasted txns - skaleHost->receiveTransaction( toJS( stream1.out() ) ); - skaleHost->receiveTransaction( toJS( stream2.out() ) ); + skaleHost->receiveTransaction( toJS( tx1.toBytes() ) ); + skaleHost->receiveTransaction( toJS( tx2.toBytes() ) ); sleep( 1 ); // allow broadcast thread to move them ConsensusExtFace::transactions_vector proposal = stub->pendingTransactions( 100 ); BOOST_REQUIRE_EQUAL( proposal.size(), 1 ); - BOOST_REQUIRE( proposal[0] == stream1.out() ); + BOOST_REQUIRE( proposal[0] == tx1.toBytes() ); } // positive test for 4 next ones @@ -985,9 +945,6 @@ BOOST_AUTO_TEST_CASE( transactionDropQueue, Transaction tx2 = tx_from_json( json ); - RLPStream stream2; - tx2.streamRLP( stream2 ); - h256 txHash2 = tx2.sha3(); // return it from consensus! @@ -996,7 +953,7 @@ BOOST_AUTO_TEST_CASE( transactionDropQueue, CHECK_BLOCK_BEGIN; BOOST_REQUIRE_NO_THROW( - stub->createBlock( ConsensusExtFace::transactions_vector{stream2.out()}, utcTime(), 1U ) ); + stub->createBlock( ConsensusExtFace::transactions_vector{tx2.toBytes()}, utcTime(), 1U ) ); stub->setPriceForBlockId( 1, 1000 ); REQUIRE_BLOCK_INCREASE( 1 ); @@ -1042,9 +999,6 @@ BOOST_AUTO_TEST_CASE( transactionDropByGasPrice Transaction tx2 = tx_from_json( json ); - RLPStream stream2; - tx2.streamRLP( stream2 ); - h256 txHash2 = tx2.sha3(); // return it from consensus! @@ -1053,7 +1007,7 @@ BOOST_AUTO_TEST_CASE( transactionDropByGasPrice CHECK_BLOCK_BEGIN; BOOST_REQUIRE_NO_THROW( stub->createBlock( - ConsensusExtFace::transactions_vector{stream2.out()}, utcTime(), 1U, 1000 ) ); + ConsensusExtFace::transactions_vector{tx2.toBytes()}, utcTime(), 1U, 1000 ) ); stub->setPriceForBlockId( 1, 1100 ); REQUIRE_BLOCK_INCREASE( 1 ); @@ -1092,11 +1046,8 @@ BOOST_AUTO_TEST_CASE( transactionDropByGasPriceReceive Transaction tx1 = tx_from_json( json ); tx1.checkOutExternalGas( client->chainParams(), client->number() ); - RLPStream stream1; - tx1.streamRLP( stream1 ); - // receive it! - skaleHost->receiveTransaction( toJS( stream1.out() ) ); + skaleHost->receiveTransaction( toJS( tx1.toBytes() ) ); sleep( 1 ); BOOST_REQUIRE_EQUAL( tq->knownTransactions().size(), 1 ); @@ -1109,9 +1060,6 @@ BOOST_AUTO_TEST_CASE( transactionDropByGasPriceReceive Transaction tx2 = tx_from_json( json ); - RLPStream stream2; - tx2.streamRLP( stream2 ); - h256 txHash2 = tx2.sha3(); // return it from consensus! @@ -1120,7 +1068,7 @@ BOOST_AUTO_TEST_CASE( transactionDropByGasPriceReceive CHECK_BLOCK_BEGIN; BOOST_REQUIRE_NO_THROW( stub->createBlock( - ConsensusExtFace::transactions_vector{stream2.out()}, utcTime(), 1U, 1000 ) ); + ConsensusExtFace::transactions_vector{tx2.toBytes()}, utcTime(), 1U, 1000 ) ); stub->setPriceForBlockId( 1, 1100 ); REQUIRE_BLOCK_INCREASE( 1 ); @@ -1151,9 +1099,6 @@ BOOST_AUTO_TEST_CASE( transactionRace Transaction tx = tx_from_json( json ); - RLPStream stream; - tx.streamRLP( stream ); - h256 txHash = tx.sha3(); // 1 add tx as normal @@ -1165,7 +1110,7 @@ BOOST_AUTO_TEST_CASE( transactionRace // 2 get it from consensus BOOST_REQUIRE_NO_THROW( - stub->createBlock( ConsensusExtFace::transactions_vector{stream.out()}, utcTime(), 1U ) ); + stub->createBlock( ConsensusExtFace::transactions_vector{tx.toBytes()}, utcTime(), 1U ) ); stub->setPriceForBlockId( 1, 1000 ); REQUIRE_BLOCK_INCREASE( 1 ); @@ -1204,12 +1149,9 @@ BOOST_AUTO_TEST_CASE( partialCatchUp pair< bool, Secret > ar = accountHolder->authenticate( ts ); Transaction tx1( ts, ar.second ); - RLPStream stream1; - tx1.streamRLP( stream1 ); - // create 1 txns in 1 block BOOST_REQUIRE_NO_THROW( - stub->createBlock( ConsensusExtFace::transactions_vector{stream1.out()}, utcTime(), 1U ) ); + stub->createBlock( ConsensusExtFace::transactions_vector{tx1.toBytes()}, utcTime(), 1U ) ); // now 2 txns json["value"] = jsToDecimal( toJS( 9000 * dev::eth::szabo ) ); @@ -1218,9 +1160,6 @@ BOOST_AUTO_TEST_CASE( partialCatchUp ar = accountHolder->authenticate( ts ); Transaction tx2( ts, ar.second ); - RLPStream stream2; - tx2.streamRLP( stream2 ); - h256 txHash = tx2.sha3(); CHECK_NONCE_BEGIN( senderAddress ); @@ -1228,7 +1167,7 @@ BOOST_AUTO_TEST_CASE( partialCatchUp CHECK_BLOCK_BEGIN; BOOST_REQUIRE_NO_THROW( - stub->createBlock( ConsensusExtFace::transactions_vector{stream1.out(), stream2.out()}, utcTime(), 2U ) ); + stub->createBlock( ConsensusExtFace::transactions_vector{tx1.toBytes(), tx2.toBytes()}, utcTime(), 2U ) ); REQUIRE_BLOCK_INCREASE( 1 ); REQUIRE_BLOCK_SIZE( 2, 2 ); @@ -1284,13 +1223,10 @@ BOOST_FIXTURE_TEST_CASE( mtmAfterBigNonceMined, dummy, pair< bool, Secret > ar = accountHolder->authenticate( ts ); Transaction tx1( ts, ar.second ); - RLPStream stream1; - tx1.streamRLP( stream1 ); - h256 tx1Hash = tx1.sha3(); // it will be put to "future" queue - skaleHost->receiveTransaction( toJS( stream1.out() ) ); + skaleHost->receiveTransaction( toJS( tx1.toBytes() ) ); sleep( 1 ); ConsensusExtFace::transactions_vector proposal = stub->pendingTransactions( 100 ); // and not proposed @@ -1301,7 +1237,7 @@ BOOST_FIXTURE_TEST_CASE( mtmAfterBigNonceMined, dummy, // simulate it coming from another node BOOST_REQUIRE_NO_THROW( - stub->createBlock( ConsensusExtFace::transactions_vector{stream1.out()}, utcTime(), 1U ) ); + stub->createBlock( ConsensusExtFace::transactions_vector{tx1.toBytes()}, utcTime(), 1U ) ); REQUIRE_BLOCK_SIZE( 1, 1 ); REQUIRE_BLOCK_TRANSACTION( 1, 0, tx1Hash ); @@ -1314,13 +1250,10 @@ BOOST_FIXTURE_TEST_CASE( mtmAfterBigNonceMined, dummy, ar = accountHolder->authenticate( ts ); Transaction tx2( ts, ar.second ); - RLPStream stream2; - tx2.streamRLP( stream2 ); - h256 tx2Hash = tx2.sha3(); // post it to queue for "realism" - skaleHost->receiveTransaction( toJS( stream2.out() ) ); + skaleHost->receiveTransaction( toJS( tx2.toBytes() ) ); sleep( 1 ); proposal = stub->pendingTransactions( 100 ); BOOST_REQUIRE_EQUAL(proposal.size(), 2); @@ -1337,7 +1270,7 @@ BOOST_FIXTURE_TEST_CASE( mtmAfterBigNonceMined, dummy, // 3 submit nonce = 1 again! // it should go to proposal BOOST_REQUIRE_THROW( - skaleHost->receiveTransaction( toJS( stream1.out() ) ), + skaleHost->receiveTransaction( toJS( tx1.toBytes() ) ), dev::eth::PendingTransactionAlreadyExists ); sleep( 1 ); diff --git a/test/unittests/libethereum/Transaction.cpp b/test/unittests/libethereum/Transaction.cpp index e21ecb1d9..db27b5650 100644 --- a/test/unittests/libethereum/Transaction.cpp +++ b/test/unittests/libethereum/Transaction.cpp @@ -124,9 +124,7 @@ BOOST_AUTO_TEST_CASE( TransactionNotReplayProtected, Transaction tx( txRlp, CheckTransaction::None ); tx.checkChainId( 1234, true ); // any chain ID is accepted for not replay protected tx - RLPStream txRlpStream; - tx.streamRLP( txRlpStream ); - BOOST_REQUIRE( txRlpStream.out() == txRlp ); + BOOST_REQUIRE( tx.toBytes() == txRlp ); txRlp = fromHex( "0x01f8ce8504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b018e0358ac3958" @@ -207,9 +205,8 @@ BOOST_AUTO_TEST_CASE( TransactionChainIDBiggerThan64Bit ) { "8827f497375ae5c8a0795eb0b4f36fe712af5e6a8447802c9eb0913a2add86174552bf2e4b0e183feb" ); RLPStream rlpStream; auto tx = Transaction( txRlp1, CheckTransaction::None ); - tx.streamRLP( rlpStream, IncludeSignature::WithSignature ); - auto txRlp = rlpStream.out(); - BOOST_REQUIRE( txRlp != txRlp1 ); + auto txBytes = tx.toBytes(IncludeSignature::WithSignature); + BOOST_REQUIRE( txBytes != txRlp1 ); txRlp1 = fromHex( "0x02f8df890a0000000000000117808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9" @@ -218,11 +215,9 @@ BOOST_AUTO_TEST_CASE( TransactionChainIDBiggerThan64Bit ) { "0000000000000000000000000000000000000000000000000780a0912e3aad5af05008d3a282d2a76dc975d234" "4eb34e2500c924a58ccfdc9dbeb4a04afcffcb5d1897df030d45a7eeb3ceb7c7e6fe368fc47865156b4899de32" "01c7" ); - RLPStream rlpStream1; tx = Transaction( txRlp1, CheckTransaction::None ); - tx.streamRLP( rlpStream1, IncludeSignature::WithSignature ); - txRlp = rlpStream.out(); - BOOST_REQUIRE( txRlp != txRlp1 ); + txBytes = tx.toBytes(IncludeSignature::WithSignature); + BOOST_REQUIRE( txBytes != txRlp1 ); } BOOST_AUTO_TEST_CASE( TransactionReplayProtected ) { @@ -234,9 +229,8 @@ BOOST_AUTO_TEST_CASE( TransactionReplayProtected ) { tx.checkChainId( 1, false ); BOOST_REQUIRE_THROW( tx.checkChainId( 123, false ), InvalidSignature ); - RLPStream txRlpStream; - tx.streamRLP( txRlpStream ); - BOOST_REQUIRE( txRlpStream.out() == txRlp ); + auto txBytes = tx.toBytes(IncludeSignature::WithSignature); + BOOST_REQUIRE( txBytes == txRlp ); txRlp = fromHex( "0x01f8c38197018504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de" @@ -247,8 +241,8 @@ BOOST_AUTO_TEST_CASE( TransactionReplayProtected ) { tx = Transaction( txRlp, CheckTransaction::None ); tx.checkChainId( 151, false ); BOOST_REQUIRE_THROW( tx.checkChainId( 123, false ), InvalidSignature ); - - BOOST_REQUIRE( tx.rlp() == txRlp ); + + BOOST_REQUIRE( tx.toBytes() == txRlp ); txRlp = fromHex( "0x02f8c98197808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180" @@ -259,8 +253,8 @@ BOOST_AUTO_TEST_CASE( TransactionReplayProtected ) { tx = Transaction( txRlp, CheckTransaction::None ); tx.checkChainId( 151, false ); BOOST_REQUIRE_THROW( tx.checkChainId( 123, false ), InvalidSignature ); - - BOOST_REQUIRE( tx.rlp() == txRlp ); + + BOOST_REQUIRE( tx.toBytes() == txRlp ); } BOOST_AUTO_TEST_CASE( accessList ) { @@ -468,9 +462,8 @@ BOOST_AUTO_TEST_CASE( GettingSignatureForUnsignedTransactionThrows, BOOST_AUTO_TEST_CASE( StreamRLPWithSignatureForUnsignedTransactionThrows ) { Transaction tx( 0, 0, 10000, Address( "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" ), bytes(), 0 ); - RLPStream s; BOOST_REQUIRE_THROW( - tx.streamRLP( s, IncludeSignature::WithSignature, false ), TransactionIsUnsigned ); + tx.toBytes( IncludeSignature::WithSignature ), TransactionIsUnsigned ); } BOOST_AUTO_TEST_CASE( CheckLowSForUnsignedTransactionThrows, diff --git a/test/unittests/libethereum/TransactionQueue.cpp b/test/unittests/libethereum/TransactionQueue.cpp index 2036e9520..ee0dd8762 100644 --- a/test/unittests/libethereum/TransactionQueue.cpp +++ b/test/unittests/libethereum/TransactionQueue.cpp @@ -234,16 +234,16 @@ BOOST_AUTO_TEST_CASE( tqImport ) { TransactionQueue tq; h256Hash known = tq.knownTransactions(); BOOST_REQUIRE( known.size() == 0 ); - - ImportResult ir = tq.import( testTransaction.transaction().rlp() ); + + ImportResult ir = tq.import( testTransaction.transaction().toBytes() ); BOOST_REQUIRE( ir == ImportResult::Success ); known = tq.knownTransactions(); BOOST_REQUIRE( known.size() == 1 ); - - ir = tq.import( testTransaction.transaction().rlp() ); + + ir = tq.import( testTransaction.transaction().toBytes() ); BOOST_REQUIRE( ir == ImportResult::AlreadyKnown ); - - bytes rlp = testTransaction.transaction().rlp(); + + bytes rlp = testTransaction.transaction().toBytes(); rlp.at( 0 ) = 03; ir = tq.import( rlp ); BOOST_REQUIRE( ir == ImportResult::Malformed ); @@ -254,14 +254,14 @@ BOOST_AUTO_TEST_CASE( tqImport ) { TestTransaction testTransaction2 = TestTransaction::defaultTransaction( 1, 2 ); TestTransaction testTransaction3 = TestTransaction::defaultTransaction( 1, 1 ); TestTransaction testTransaction4 = TestTransaction::defaultTransaction( 1, 4 ); - - ir = tq.import( testTransaction2.transaction().rlp() ); + + ir = tq.import( testTransaction2.transaction().toBytes() ); BOOST_REQUIRE( ir == ImportResult::SameNonceAlreadyInQueue ); - - ir = tq.import( testTransaction3.transaction().rlp() ); + + ir = tq.import( testTransaction3.transaction().toBytes() ); BOOST_REQUIRE( ir == ImportResult::AlreadyKnown ); - - ir = tq.import( testTransaction4.transaction().rlp() ); + + ir = tq.import( testTransaction4.transaction().toBytes() ); known = tq.knownTransactions(); BOOST_REQUIRE( known.size() == 1 ); Transactions ts = tq.topTransactions( 4 ); @@ -289,8 +289,8 @@ BOOST_AUTO_TEST_CASE( tqImportFuture ) { BOOST_REQUIRE( maxNonce == 0 ); u256 waiting = tq.waiting(sender); BOOST_REQUIRE( waiting == 0 ); - - ImportResult ir1 = tq.import( tx1.transaction().rlp(), IfDropped::Ignore, true ); + + ImportResult ir1 = tq.import( tx1.transaction().toBytes(), IfDropped::Ignore, true ); BOOST_REQUIRE( ir1 == ImportResult::Success ); known = tq.knownTransactions(); BOOST_REQUIRE( known.size() == 1 ); @@ -302,7 +302,7 @@ BOOST_AUTO_TEST_CASE( tqImportFuture ) { BOOST_REQUIRE( waiting == 1 ); // HACK it's now allowed to repeat future transaction (can put it to current) - ir1 = tq.import( tx1.transaction().rlp(), IfDropped::Ignore, true ); + ir1 = tq.import( tx1.transaction().toBytes(), IfDropped::Ignore, true ); BOOST_REQUIRE( ir1 == ImportResult::Success ); known = tq.knownTransactions(); BOOST_REQUIRE( known.size() == 1 ); @@ -312,14 +312,14 @@ BOOST_AUTO_TEST_CASE( tqImportFuture ) { BOOST_REQUIRE( maxNonce == 5 ); waiting = tq.waiting(sender); BOOST_REQUIRE( waiting == 1 ); - - bytes rlp = tx1.transaction().rlp(); + + bytes rlp = tx1.transaction().toBytes(); rlp.at( 0 ) = 03; ir1 = tq.import( rlp, IfDropped::Ignore, true ); BOOST_REQUIRE( ir1 == ImportResult::Malformed ); TestTransaction tx2 = TestTransaction::defaultTransaction(2); - ImportResult ir2 = tq.import( tx2.transaction().rlp(), IfDropped::Ignore, true ); + ImportResult ir2 = tq.import( tx2.transaction().toBytes(), IfDropped::Ignore, true ); BOOST_REQUIRE( ir2 == ImportResult::Success ); known = tq.knownTransactions(); BOOST_REQUIRE( known.size() == 2 ); @@ -330,7 +330,7 @@ BOOST_AUTO_TEST_CASE( tqImportFuture ) { BOOST_CHECK( ( Transactions{} ) == tq.topTransactions( 256 ) ); TestTransaction tx3 = TestTransaction::defaultTransaction(1); - ImportResult ir3 = tq.import( tx3.transaction().rlp(), IfDropped::Ignore, true ); + ImportResult ir3 = tq.import( tx3.transaction().toBytes(), IfDropped::Ignore, true ); BOOST_REQUIRE( ir3 == ImportResult::Success ); known = tq.knownTransactions(); BOOST_REQUIRE( known.size() == 3 ); @@ -341,7 +341,7 @@ BOOST_AUTO_TEST_CASE( tqImportFuture ) { BOOST_CHECK( ( Transactions{} ) == tq.topTransactions( 256 ) ); TestTransaction tx4 = TestTransaction::defaultTransaction(0); - ImportResult ir4 = tq.import( tx4.transaction().rlp(), IfDropped::Ignore ); + ImportResult ir4 = tq.import( tx4.transaction().toBytes(), IfDropped::Ignore ); BOOST_REQUIRE( ir4 == ImportResult::Success ); known = tq.knownTransactions(); BOOST_REQUIRE( known.size() == 4 ); @@ -355,7 +355,7 @@ BOOST_AUTO_TEST_CASE( tqImportFuture ) { BOOST_CHECK( ( Transactions{ tx4.transaction(), tx3.transaction(), tx2.transaction() } ) == tq.topTransactions( 256 ) ); TestTransaction tx5 = TestTransaction::defaultTransaction(3); - ImportResult ir5 = tq.import( tx5.transaction().rlp(), IfDropped::Ignore ); + ImportResult ir5 = tq.import( tx5.transaction().toBytes(), IfDropped::Ignore ); BOOST_REQUIRE( ir5 == ImportResult::Success ); known = tq.knownTransactions(); BOOST_REQUIRE( known.size() == 5 ); @@ -387,13 +387,13 @@ BOOST_AUTO_TEST_CASE( dropFromFutureToCurrent ) { TestTransaction tx1 = TestTransaction::defaultTransaction(1); // put transaction to future - ImportResult ir1 = tq.import( tx1.transaction().rlp(), IfDropped::Ignore, true ); + ImportResult ir1 = tq.import( tx1.transaction().toBytes(), IfDropped::Ignore, true ); BOOST_REQUIRE( ir1 == ImportResult::Success ); TransactionQueue::Status status = tq.status(); BOOST_REQUIRE( status.current == 0 && status.future == 1 ); // push it to current and see it fall back from future to current - ir1 = tq.import( tx1.transaction().rlp(), IfDropped::Ignore, false ); + ir1 = tq.import( tx1.transaction().toBytes(), IfDropped::Ignore, false ); BOOST_REQUIRE( ir1 == ImportResult::Success ); status = tq.status(); BOOST_REQUIRE( status.current == 1 && status.future == 0 ); @@ -402,10 +402,10 @@ BOOST_AUTO_TEST_CASE( dropFromFutureToCurrent ) { BOOST_AUTO_TEST_CASE( tqImportFutureLimits ) { dev::eth::TransactionQueue tq( 1024, 2 ); TestTransaction tx1 = TestTransaction::defaultTransaction(3); - tq.import( tx1.transaction().rlp(), IfDropped::Ignore, true ); + tq.import( tx1.transaction().toBytes(), IfDropped::Ignore, true ); TestTransaction tx2 = TestTransaction::defaultTransaction(2); - tq.import( tx2.transaction().rlp(), IfDropped::Ignore, true ); + tq.import( tx2.transaction().toBytes(), IfDropped::Ignore, true ); auto waiting = tq.waiting(tx1.transaction().sender()); BOOST_REQUIRE( waiting == 2 ); @@ -413,7 +413,7 @@ BOOST_AUTO_TEST_CASE( tqImportFutureLimits ) { BOOST_REQUIRE( known.size() == 2 ); TestTransaction tx3 = TestTransaction::defaultTransaction(1); - ImportResult ir = tq.import( tx3.transaction().rlp(), IfDropped::Ignore, true ); + ImportResult ir = tq.import( tx3.transaction().toBytes(), IfDropped::Ignore, true ); BOOST_REQUIRE( ir == ImportResult::Success ); waiting = tq.waiting(tx1.transaction().sender()); @@ -427,7 +427,7 @@ BOOST_AUTO_TEST_CASE( tqImportFutureLimits2 ) { dev::eth::TransactionQueue tq( 1024, 2 ); TestTransaction tx1 = TestTransaction::defaultTransaction(3); - tq.import( tx1.transaction().rlp(), IfDropped::Ignore, true ); + tq.import( tx1.transaction().toBytes(), IfDropped::Ignore, true ); auto waiting = tq.waiting(tx1.transaction().sender()); BOOST_REQUIRE( waiting == 1 ); @@ -454,7 +454,7 @@ BOOST_AUTO_TEST_CASE( tqImportFutureLimits2 ) { BOOST_REQUIRE( status.future == 2 ); TestTransaction tx2 = TestTransaction::defaultTransaction(2); - tq.import( tx2.transaction().rlp(), IfDropped::Ignore, true ); + tq.import( tx2.transaction().toBytes(), IfDropped::Ignore, true ); waiting = tq.waiting(tx1.transaction().sender()); BOOST_REQUIRE( waiting == 1 ); @@ -472,7 +472,7 @@ BOOST_AUTO_TEST_CASE( tqDrop ) { TransactionQueue tq; TestTransaction testTransaction = TestTransaction::defaultTransaction(); tq.dropGood( testTransaction.transaction() ); - tq.import( testTransaction.transaction().rlp() ); + tq.import( testTransaction.transaction().toBytes() ); BOOST_REQUIRE( tq.topTransactions( 4 ).size() == 1 ); tq.dropGood( testTransaction.transaction() ); BOOST_REQUIRE( tq.topTransactions( 4 ).size() == 0 ); @@ -516,8 +516,8 @@ BOOST_AUTO_TEST_CASE( tqLimit ) { BOOST_AUTO_TEST_CASE( tqLimitBytes ) { TransactionQueue tq( 100, 100, 250, 250 ); - - unsigned maxTxCount = 250 / TestTransaction::defaultTransaction( 1 ).transaction().rlp().size(); + + unsigned maxTxCount = 250 / TestTransaction::defaultTransaction( 1 ).transaction().toBytes().size(); TestTransaction testTransaction = TestTransaction::defaultTransaction( 2 ); ImportResult res = tq.import( testTransaction.transaction(), IfDropped::Ignore, true ); @@ -554,8 +554,8 @@ BOOST_AUTO_TEST_CASE( tqLimitBytes ) { BOOST_AUTO_TEST_CASE( tqEqueue ) { TransactionQueue tq; TestTransaction testTransaction = TestTransaction::defaultTransaction(); - - bytes payloadToDecode = testTransaction.transaction().rlp(); + + bytes payloadToDecode = testTransaction.transaction().toBytes(); RLPStream rlpStream( 2 ); rlpStream.appendRaw( payloadToDecode ); diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index 771c1faf7..d8b166580 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -2651,7 +2651,7 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { // compare with txn hash from geth BOOST_REQUIRE( txHash == "0xc843560015a655b8f81f65a458be9019bdb5cd8e416b6329ca18f36de0b8244d" ); - BOOST_REQUIRE( dev::toHexPrefixed( fixture.client->transactions( 3 )[0].rlp() ) == "0x01f8678197808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180c001a01ebdc546c8b85511b7ba831f47c4981069d7af972d10b7dce2c57225cb5df6a7a055ae1e84fea41d37589eb740a0a93017a5cd0e9f10ee50f165bf4b1b4c78ddae" ); + BOOST_REQUIRE( dev::toHexPrefixed( fixture.client->transactions( 3 )[0].toBytes() ) == "0x01f8678197808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180c001a01ebdc546c8b85511b7ba831f47c4981069d7af972d10b7dce2c57225cb5df6a7a055ae1e84fea41d37589eb740a0a93017a5cd0e9f10ee50f165bf4b1b4c78ddae" ); BOOST_REQUIRE( fixture.rpcClient->eth_getBalance( "0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b", "latest" ) == "0x1" ); @@ -2705,7 +2705,7 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { // compare with txn hash from geth BOOST_REQUIRE( txHash == "0xa6d3541e06dff71fb8344a4db2a4ad4e0b45024eb23a8f568982b70a5f50f94d" ); - BOOST_REQUIRE( dev::toHexPrefixed( fixture.client->transactions( 4 )[0].rlp() ) == "0x01f8c38197018504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0b03eaf481958e22fc39bd1d526eb9255be1e6625614f02ca939e51c3d7e64bcaa05f675640c04bb050d27bd1f39c07b6ff742311b04dab760bb3bc206054332879" ); + BOOST_REQUIRE( dev::toHexPrefixed( fixture.client->transactions( 4 )[0].toBytes() ) == "0x01f8c38197018504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0b03eaf481958e22fc39bd1d526eb9255be1e6625614f02ca939e51c3d7e64bcaa05f675640c04bb050d27bd1f39c07b6ff742311b04dab760bb3bc206054332879" ); result = fixture.rpcClient->eth_getTransactionByHash( txHash ); BOOST_REQUIRE( result["type"] == "0x1" ); @@ -2778,8 +2778,8 @@ BOOST_AUTO_TEST_CASE( eip1559Transactions ) { // compare with txn hash from geth BOOST_REQUIRE( txHash == "0x7bd586e93e3012577de4ba33e3b887baf520cbb92c5dd10996b262f9c5c8f747" ); - std::cout << dev::toHexPrefixed( fixture.client->transactions( 3 )[0].rlp() ) << '\n'; - BOOST_REQUIRE( dev::toHexPrefixed( fixture.client->transactions( 3 )[0].rlp() ) == "0x02f8c98197808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0f1a407dfc1a9f782001d89f617e9b3a2f295378533784fb39960dea60beea2d0a05ac3da2946554ba3d5721850f4f89ee7a0c38e4acab7130908e7904d13174388" ); + std::cout << dev::toHexPrefixed( fixture.client->transactions( 3 )[0].toBytes() ) << '\n'; + BOOST_REQUIRE( dev::toHexPrefixed( fixture.client->transactions( 3 )[0].toBytes() ) == "0x02f8c98197808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0f1a407dfc1a9f782001d89f617e9b3a2f295378533784fb39960dea60beea2d0a05ac3da2946554ba3d5721850f4f89ee7a0c38e4acab7130908e7904d13174388" ); BOOST_REQUIRE( fixture.rpcClient->eth_getBalance( "0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b", "latest" ) == "0x1" ); @@ -3168,9 +3168,7 @@ BOOST_AUTO_TEST_CASE( PrecompiledPrintFakeEth, *boost::unit_test::precondition( pair< bool, Secret > ar = fixture.accountHolder->authenticate( ts ); Transaction tx( ts, ar.second ); - RLPStream stream; - tx.streamRLP( stream ); - auto txHash = fixture.rpcClient->eth_sendRawTransaction( toJS( stream.out() ) ); + auto txHash = fixture.rpcClient->eth_sendRawTransaction( toJS( tx.toBytes() ) ); dev::eth::mineTransaction( *( fixture.client ), 1 ); Json::Value receipt = fixture.rpcClient->eth_getTransactionReceipt( txHash ); @@ -3547,9 +3545,7 @@ BOOST_AUTO_TEST_CASE( transaction_from_restricted_address ) { pair< bool, Secret > ar = accountHolder->authenticate( ts ); Transaction tx( ts, ar.second ); - RLPStream stream; - tx.streamRLP( stream ); - auto txHash = rpcClient->eth_sendRawTransaction( toJS( stream.out() ) ); + auto txHash = rpcClient->eth_sendRawTransaction( toJS( tx.toBytes() ) ); dev::eth::mineTransaction( *( client ), 1 ); BOOST_REQUIRE( !boost::filesystem::exists( path ) ); @@ -3570,9 +3566,7 @@ BOOST_AUTO_TEST_CASE( transaction_from_allowed_address ) { pair< bool, Secret > ar = accountHolder->authenticate( ts ); Transaction tx( ts, ar.second ); - RLPStream stream; - tx.streamRLP( stream ); - auto txHash = rpcClient->eth_sendRawTransaction( toJS( stream.out() ) ); + auto txHash = rpcClient->eth_sendRawTransaction( toJS( tx.toBytes() ) ); dev::eth::mineTransaction( *( client ), 1 ); BOOST_REQUIRE( boost::filesystem::exists( path ) ); @@ -3621,9 +3615,7 @@ BOOST_AUTO_TEST_CASE( delegate_call ) { pair< bool, Secret > ar = accountHolder->authenticate( ts ); Transaction tx( ts, ar.second ); - RLPStream stream; - tx.streamRLP( stream ); - auto txHash = rpcClient->eth_sendRawTransaction( toJS( stream.out() ) ); + auto txHash = rpcClient->eth_sendRawTransaction( toJS( tx.toBytes() ) ); dev::eth::mineTransaction( *( client ), 1 ); Json::Value receipt = rpcClient->eth_getTransactionReceipt( txHash ); @@ -3673,9 +3665,7 @@ BOOST_AUTO_TEST_CASE( cached_filestorage ) { pair< bool, Secret > ar = fixture.accountHolder->authenticate( ts ); Transaction tx( ts, ar.second ); - RLPStream stream; - tx.streamRLP( stream ); - auto txHash = fixture.rpcClient->eth_sendRawTransaction( toJS( stream.out() ) ); + auto txHash = fixture.rpcClient->eth_sendRawTransaction( toJS( tx.toBytes() ) ); dev::eth::mineTransaction( *( fixture.client ), 1 ); BOOST_REQUIRE( !boost::filesystem::exists( fixture.path ) ); @@ -3705,9 +3695,7 @@ BOOST_AUTO_TEST_CASE( uncached_filestorage ) { pair< bool, Secret > ar = fixture.accountHolder->authenticate( ts ); Transaction tx( ts, ar.second ); - RLPStream stream; - tx.streamRLP( stream ); - auto txHash = fixture.rpcClient->eth_sendRawTransaction( toJS( stream.out() ) ); + auto txHash = fixture.rpcClient->eth_sendRawTransaction( toJS( tx.toBytes() ) ); dev::eth::mineTransaction( *( fixture.client ), 1 ); BOOST_REQUIRE( boost::filesystem::exists( fixture.path ) ); diff --git a/test/unittests/mapreduce_consensus/ConsensusEngine.cpp b/test/unittests/mapreduce_consensus/ConsensusEngine.cpp index 8b78e0bd1..8c6932c1d 100644 --- a/test/unittests/mapreduce_consensus/ConsensusEngine.cpp +++ b/test/unittests/mapreduce_consensus/ConsensusEngine.cpp @@ -305,7 +305,7 @@ class ConsensusExtFaceFixture : public ConsensusExtFace { assert( buffer.empty() ); for ( const Transaction& txn : txns ) { - buffer.push_back( txn.rlp() ); + buffer.push_back( txn.toBytes() ); } // for m_transactionsCond.notify_one(); From 1f3026748da402aee8bd92202daa2300b2d4e435 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 17 Apr 2024 18:26:08 +0100 Subject: [PATCH 27/53] #1719 fix yParity field in json-rpc responses --- libweb3jsonrpc/JsonHelper.cpp | 6 +++--- test/unittests/libweb3jsonrpc/jsonrpc.cpp | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libweb3jsonrpc/JsonHelper.cpp b/libweb3jsonrpc/JsonHelper.cpp index ef97db47e..80dcf8e3b 100644 --- a/libweb3jsonrpc/JsonHelper.cpp +++ b/libweb3jsonrpc/JsonHelper.cpp @@ -107,7 +107,7 @@ Json::Value toJson( dev::eth::Transaction const& _t, std::pair< h256, unsigned > res["s"] = toJS( _t.signature().s ); res["type"] = toJS( int( _t.txType() ) ); if ( _t.txType() != dev::eth::TransactionType::Legacy ) { - res["yParity"] = res["v"].asString(); + res["yParity"] = toJS( _t.signature().v ); res["accessList"] = Json::Value( Json::arrayValue ); for ( const auto& d : _t.accessList() ) { auto list = RLP( d ); @@ -350,7 +350,7 @@ Json::Value toJson( dev::eth::Transaction const& _t ) { res["v"] = toJS( _t.signature().v ); res["type"] = toJS( int( _t.txType() ) ); if ( _t.txType() != dev::eth::TransactionType::Legacy ) { - res["yParity"] = res["v"].asString(); + res["yParity"] = toJS( _t.signature().v ); res["accessList"] = Json::Value( Json::arrayValue ); for ( const auto& d : _t.accessList() ) { auto list = RLP( d ); @@ -402,7 +402,7 @@ Json::Value toJson( dev::eth::LocalisedTransaction const& _t ) { res["s"] = toJS( _t.signature().s.hex() ); res["type"] = toJS( int( _t.txType() ) ); if ( _t.txType() != dev::eth::TransactionType::Legacy ) { - res["yParity"] = res["v"].asString(); + res["yParity"] = toJS( _t.signature().v ); res["accessList"] = Json::Value( Json::arrayValue ); for ( const auto& d : _t.accessList() ) { auto list = RLP( d ); diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index 771c1faf7..39e30f551 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -2663,7 +2663,7 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { BOOST_REQUIRE( block["transactions"].size() == 1 ); BOOST_REQUIRE( block["transactions"][0]["hash"].asString() == txHash ); BOOST_REQUIRE( block["transactions"][0]["type"] == "0x1" ); - BOOST_REQUIRE( block["transactions"][0]["yParity"] == block["transactions"][0]["v"] ); + BOOST_REQUIRE( toJS( jsToInt( block["transactions"][0]["yParity"].asString() ) + 35 + 2 * fixture.client->chainParams().chainID ) == block["transactions"][0]["v"].asString() ); BOOST_REQUIRE( block["transactions"][0]["accessList"].isArray() ); BOOST_REQUIRE( block["transactions"][0]["accessList"].size() == 0 ); @@ -2677,20 +2677,20 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { result = fixture.rpcClient->eth_getTransactionByHash( txHash ); BOOST_REQUIRE( result["hash"].asString() == txHash ); BOOST_REQUIRE( result["type"] == "0x1" ); - BOOST_REQUIRE( result["yParity"] == result["v"] ); + BOOST_REQUIRE( toJS( jsToInt( result["yParity"].asString() ) + 35 + 2 * fixture.client->chainParams().chainID ) == result["v"].asString() ); BOOST_REQUIRE( result["accessList"].isArray() ); BOOST_REQUIRE( result["accessList"].size() == 0 ); result = fixture.rpcClient->eth_getTransactionByBlockHashAndIndex( blockHash, "0x0" ); BOOST_REQUIRE( result["hash"].asString() == txHash ); BOOST_REQUIRE( result["type"] == "0x1" ); - BOOST_REQUIRE( result["yParity"] == result["v"] ); + BOOST_REQUIRE( toJS( jsToInt( result["yParity"].asString() ) + 35 + 2 * fixture.client->chainParams().chainID ) == result["v"].asString() ); BOOST_REQUIRE( result["accessList"].isArray() ); result = fixture.rpcClient->eth_getTransactionByBlockNumberAndIndex( "0x3", "0x0" ); BOOST_REQUIRE( result["hash"].asString() == txHash ); BOOST_REQUIRE( result["type"] == "0x1" ); - BOOST_REQUIRE( result["yParity"] == result["v"] ); + BOOST_REQUIRE( toJS( jsToInt( result["yParity"].asString() ) + 35 + 2 * fixture.client->chainParams().chainID ) == result["v"].asString() ); BOOST_REQUIRE( result["accessList"].isArray() ); BOOST_REQUIRE( result["accessList"].size() == 0 ); @@ -2792,7 +2792,7 @@ BOOST_AUTO_TEST_CASE( eip1559Transactions ) { BOOST_REQUIRE( block["transactions"].size() == 1 ); BOOST_REQUIRE( block["transactions"][0]["hash"].asString() == txHash ); BOOST_REQUIRE( block["transactions"][0]["type"] == "0x2" ); - BOOST_REQUIRE( block["transactions"][0]["yParity"] == block["transactions"][0]["v"] ); + BOOST_REQUIRE( toJS( jsToInt( block["transactions"][0]["yParity"].asString() ) + 35 + 2 * fixture.client->chainParams().chainID ) == block["transactions"][0]["v"].asString() ); BOOST_REQUIRE( block["transactions"][0]["accessList"].isArray() ); std::string blockHash = block["hash"].asString(); @@ -2804,7 +2804,7 @@ BOOST_AUTO_TEST_CASE( eip1559Transactions ) { result = fixture.rpcClient->eth_getTransactionByHash( txHash ); BOOST_REQUIRE( result["hash"].asString() == txHash ); BOOST_REQUIRE( result["type"] == "0x2" ); - BOOST_REQUIRE( result["yParity"] == result["v"] ); + BOOST_REQUIRE( toJS( jsToInt( result["yParity"].asString() ) + 35 + 2 * fixture.client->chainParams().chainID ) == result["v"].asString() ); BOOST_REQUIRE( result["accessList"].isArray() ); BOOST_REQUIRE( result.isMember( "maxPriorityFeePerGas" ) && result["maxPriorityFeePerGas"].isString() ); BOOST_REQUIRE( result.isMember( "maxFeePerGas" ) && result["maxFeePerGas"].isString() ); @@ -2812,7 +2812,7 @@ BOOST_AUTO_TEST_CASE( eip1559Transactions ) { result = fixture.rpcClient->eth_getTransactionByBlockHashAndIndex( blockHash, "0x0" ); BOOST_REQUIRE( result["hash"].asString() == txHash ); BOOST_REQUIRE( result["type"] == "0x2" ); - BOOST_REQUIRE( result["yParity"] == result["v"] ); + BOOST_REQUIRE( toJS( jsToInt( result["yParity"].asString() ) + 35 + 2 * fixture.client->chainParams().chainID ) == result["v"].asString() ); BOOST_REQUIRE( result["accessList"].isArray() ); BOOST_REQUIRE( result["maxPriorityFeePerGas"] == "0x4a817c800" ); BOOST_REQUIRE( result["maxFeePerGas"] == "0x4a817c800" ); @@ -2820,7 +2820,7 @@ BOOST_AUTO_TEST_CASE( eip1559Transactions ) { result = fixture.rpcClient->eth_getTransactionByBlockNumberAndIndex( "0x3", "0x0" ); BOOST_REQUIRE( result["hash"].asString() == txHash ); BOOST_REQUIRE( result["type"] == "0x2" ); - BOOST_REQUIRE( result["yParity"] == result["v"] ); + BOOST_REQUIRE( toJS( jsToInt( result["yParity"].asString() ) + 35 + 2 * fixture.client->chainParams().chainID ) == result["v"].asString() ); BOOST_REQUIRE( result["accessList"].isArray() ); BOOST_REQUIRE( result["maxPriorityFeePerGas"] == "0x4a817c800" ); BOOST_REQUIRE( result["maxFeePerGas"] == "0x4a817c800" ); From 1815ebf4fe22783fe9954b9e1055a5ed9f23f3f6 Mon Sep 17 00:00:00 2001 From: Dima Litvinov Date: Wed, 17 Apr 2024 19:41:43 +0100 Subject: [PATCH 28/53] SKALED-1719 Use separate function to extract transaction bytes --- libethcore/TransactionBase.cpp | 23 +++++++++++++++-------- libethcore/TransactionBase.h | 14 +++++++++----- libethereum/BlockChain.cpp | 22 +++++++--------------- libethereum/BlockChain.h | 20 ++++---------------- libethereum/ClientBase.cpp | 6 +----- 5 files changed, 36 insertions(+), 49 deletions(-) diff --git a/libethcore/TransactionBase.cpp b/libethcore/TransactionBase.cpp index d6e8cef33..3567c4f3e 100644 --- a/libethcore/TransactionBase.cpp +++ b/libethcore/TransactionBase.cpp @@ -95,7 +95,7 @@ TransactionBase::TransactionBase( TransactionSkeleton const& _ts, Secret const& sign( _s ); } -void TransactionBase::fillFromRlpLegacy( +void TransactionBase::fillFromBytesLegacy( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ) { RLP const rlp( _rlpData ); try { @@ -169,7 +169,7 @@ void TransactionBase::fillFromRlpLegacy( } } -void TransactionBase::fillFromRlpType1( +void TransactionBase::fillFromBytesType1( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ) { bytes croppedRlp( _rlpData.begin() + 1, _rlpData.end() ); RLP const rlp( croppedRlp ); @@ -230,7 +230,7 @@ void TransactionBase::fillFromRlpType1( } } -void TransactionBase::fillFromRlpType2( +void TransactionBase::fillFromBytesType2( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ) { bytes croppedRlp( _rlpData.begin() + 1, _rlpData.end() ); RLP const rlp( croppedRlp ); @@ -294,17 +294,17 @@ void TransactionBase::fillFromRlpType2( } } -void TransactionBase::fillFromRlpByType( +void TransactionBase::fillFromBytesByType( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid, TransactionType type ) { switch ( type ) { case TransactionType::Legacy: - fillFromRlpLegacy( _rlpData, _checkSig, _allowInvalid ); + fillFromBytesLegacy( _rlpData, _checkSig, _allowInvalid ); break; case TransactionType::Type1: - fillFromRlpType1( _rlpData, _checkSig, _allowInvalid ); + fillFromBytesType1( _rlpData, _checkSig, _allowInvalid ); break; case TransactionType::Type2: - fillFromRlpType2( _rlpData, _checkSig, _allowInvalid ); + fillFromBytesType2( _rlpData, _checkSig, _allowInvalid ); break; default: BOOST_THROW_EXCEPTION( @@ -326,7 +326,7 @@ TransactionBase::TransactionBase( MICROPROFILE_SCOPEI( "TransactionBase", "ctor", MP_GOLD2 ); try { TransactionType txnType = getTransactionType( _rlpData ); - fillFromRlpByType( _rlpData, _checkSig, _allowInvalid, txnType ); + fillFromBytesByType( _rlpData, _checkSig, _allowInvalid, txnType ); } catch ( ... ) { m_type = Type::Invalid; RLPStream s; @@ -539,3 +539,10 @@ u256 TransactionBase::gas() const { u256 TransactionBase::nonPowGas() const { return m_gas; } + +bytesConstRef dev::eth::bytesRefFromTransactionRlp( const RLP& _rlp ) { + if ( _rlp.isList() ) + return _rlp.data(); + else + return _rlp.payload(); +} diff --git a/libethcore/TransactionBase.h b/libethcore/TransactionBase.h index d316e3e01..431f0dd8c 100644 --- a/libethcore/TransactionBase.h +++ b/libethcore/TransactionBase.h @@ -312,12 +312,14 @@ class TransactionBase { static TransactionType getTransactionType( bytesConstRef _rlp ); /// Constructs a transaction from the given RLP and transaction type. - void fillFromRlpByType( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid, - TransactionType type ); - void fillFromRlpLegacy( + 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 fillFromRlpType1( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ); - void fillFromRlpType2( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ); void streamLegacyTransaction( RLPStream& _s, IncludeSignature _sig, bool _forEip155hash ) const; void streamType1Transaction( RLPStream& _s, IncludeSignature _sig ) const; @@ -356,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 diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index a6452f497..6a09fb506 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -64,6 +64,8 @@ using skale::BaseState; using skale::State; using namespace skale::error; +extern bytesConstRef bytesRefFromTransactionRlp( const RLP& _rlp ); + #define ETH_TIMED_IMPORTS 1 namespace { @@ -777,15 +779,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 ); - if ( RLP( *it ).isList() ) - // means Legacy transaction - extrasWriteBatch.insert( toSlice( sha3( ( *it ).data() ), ExtraTransactionAddress ), - ( db::Slice ) dev::ref( ta.rlp() ) ); - else { - auto payload = ( *it ).payload(); - extrasWriteBatch.insert( toSlice( sha3( payload ), ExtraTransactionAddress ), - ( db::Slice ) dev::ref( ta.rlp() ) ); - } + auto txBytes = bytesRefFromTransactionRlp( *it ); + extrasWriteBatch.insert( toSlice( sha3( txBytes ), ExtraTransactionAddress ), + ( db::Slice ) dev::ref( ta.rlp() ) ); + ++ta.index; } } @@ -1754,12 +1751,7 @@ VerifiedBlockRef BlockChain::verifyBlock( bytesConstRef _block, ( ImportRequirements::TransactionBasic | ImportRequirements::TransactionSignatures ) ) { MICROPROFILE_SCOPEI( "BlockChain", "check txns", MP_ROSYBROWN ); for ( RLP const& tr : r[1] ) { - bytesConstRef d; - if ( tr.isList() ) - // means Legacy transaction - d = tr.data(); - else - d = tr.payload(); + bytesConstRef d = bytesRefFromTransactionRlp( tr ); try { Transaction t( d, ( _ir & ImportRequirements::TransactionSignatures ) ? CheckTransaction::Everything : diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index 2cfe2658f..1d7a152bd 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -231,13 +231,8 @@ class BlockChain { auto b = block( _hash ); RLP rlp( b ); h256s ret; - for ( auto d : rlp[1] ) { - if ( d.isList() ) - // means Legacy transaction - ret.push_back( sha3( d.data() ) ); - else - ret.push_back( sha3( d.payload() ) ); - } + for ( auto d : rlp[1] ) + ret.push_back( sha3( bytesRefFromTransactionRlp( d ) ) ); return ret; } TransactionHashes transactionHashes() const { return transactionHashes( currentHash() ); } @@ -324,10 +319,7 @@ class BlockChain { /// none given) & index. Thread-safe. bytes transaction( h256 const& _blockHash, unsigned _i ) const { bytes b = block( _blockHash ); - if ( RLP( b )[1][_i].isList() ) - // means Legacy transaction - return RLP( b )[1][_i].data().toBytes(); - return RLP( b )[1][_i].payload().toBytes(); + return bytesRefFromTransactionRlp( RLP( b )[1][_i] ).toBytes(); } bytes transaction( unsigned _i ) const { return transaction( currentHash(), _i ); } @@ -336,11 +328,7 @@ class BlockChain { bytes b = block( _blockHash ); std::vector< bytes > ret; for ( auto const& i : RLP( b )[1] ) - if ( i.isList() ) - // means Legacy transaction - ret.push_back( i.data().toBytes() ); - else - ret.push_back( i.payload().toBytes() ); + ret.push_back( bytesRefFromTransactionRlp( i ).toBytes() ); return ret; } std::vector< bytes > transactions() const { return transactions( currentHash() ); } diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index de711e0d3..7537a697e 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -448,11 +448,7 @@ Transactions ClientBase::transactions( h256 _blockHash ) const { Transactions res; for ( unsigned i = 0; i < b[1].itemCount(); i++ ) { auto txRlp = b[1][i]; - if ( txRlp.isList() ) - // means Legacy transaction - res.emplace_back( txRlp.data(), CheckTransaction::Cheap, true ); - else - res.emplace_back( txRlp.payload(), CheckTransaction::Cheap, true ); + res.emplace_back( bytesRefFromTransactionRlp( txRlp ), CheckTransaction::Cheap, true ); } return res; } From a35280aea91c5813a8c9efbd70d66f591e39c77d Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Thu, 18 Apr 2024 11:21:25 +0100 Subject: [PATCH 29/53] #1719 handle price absence in the db --- libweb3jsonrpc/Eth.cpp | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index 0bd42958e..5690372f8 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -551,6 +551,17 @@ Json::Value Eth::eth_getBlockByHash( string const& _blockHash, bool _includeTran if ( !client()->isKnown( h ) ) return Json::Value( Json::nullValue ); + u256 baseFeePerGas; + try { + baseFeePerGas = client()->gasBidPrice( client()->numberFromHash( h ) ); + } catch ( std::invalid_argument& _e ) { + cdebug << "Cannot get gas price for block " << _blockHash; + cdebug << _e.what(); + // set default gasPrice + // probably the price was rotated out as we are asking the price for the old block + baseFeePerGas = client()->gasBidPrice(); + } + if ( _includeTransactions ) { Transactions transactions = client()->transactions( h ); @@ -567,8 +578,7 @@ Json::Value Eth::eth_getBlockByHash( string const& _blockHash, bool _includeTran } #endif return toJson( client()->blockInfo( h ), client()->blockDetails( h ), - client()->uncleHashes( h ), transactions, client()->sealEngine(), - client()->gasBidPrice( client()->numberFromHash( h ) ) ); + client()->uncleHashes( h ), transactions, client()->sealEngine(), baseFeePerGas ); } else { h256s transactions = client()->transactionHashes( h ); @@ -585,8 +595,7 @@ Json::Value Eth::eth_getBlockByHash( string const& _blockHash, bool _includeTran } #endif return toJson( client()->blockInfo( h ), client()->blockDetails( h ), - client()->uncleHashes( h ), transactions, client()->sealEngine(), - client()->gasBidPrice( client()->numberFromHash( h ) ) ); + client()->uncleHashes( h ), transactions, client()->sealEngine(), baseFeePerGas ); } } catch ( ... ) { BOOST_THROW_EXCEPTION( JsonRpcException( Errors::ERROR_RPC_INVALID_PARAMS ) ); @@ -599,6 +608,17 @@ Json::Value Eth::eth_getBlockByNumber( string const& _blockNumber, bool _include if ( !client()->isKnown( h ) ) return Json::Value( Json::nullValue ); + u256 baseFeePerGas; + try { + baseFeePerGas = client()->gasBidPrice( h ); + } catch ( std::invalid_argument& _e ) { + cdebug << "Cannot get gas price for block " << h; + cdebug << _e.what(); + // set default gasPrice + // probably the price was rotated out as we are asking the price for the old block + baseFeePerGas = client()->gasBidPrice(); + } + #ifdef HISTORIC_STATE h256 bh = client()->hashFromNumber( h ); return eth_getBlockByHash( "0x" + bh.hex(), _includeTransactions ); @@ -609,11 +629,11 @@ Json::Value Eth::eth_getBlockByNumber( string const& _blockNumber, bool _include if ( _includeTransactions ) return toJson( client()->blockInfo( h ), client()->blockDetails( h ), client()->uncleHashes( h ), client()->transactions( h ), client()->sealEngine(), - client()->gasBidPrice( h ) ); + baseFeePerGas ); else return toJson( client()->blockInfo( h ), client()->blockDetails( h ), client()->uncleHashes( h ), client()->transactionHashes( h ), - client()->sealEngine(), client()->gasBidPrice( h ) ); + client()->sealEngine(), baseFeePerGas ); #endif } catch ( ... ) { BOOST_THROW_EXCEPTION( JsonRpcException( Errors::ERROR_RPC_INVALID_PARAMS ) ); From a2dd1de20da601db27a203d42f890e2b32ff6aae Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Fri, 19 Apr 2024 18:37:49 +0100 Subject: [PATCH 30/53] #1719 small fixes --- libweb3jsonrpc/JsonHelper.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libweb3jsonrpc/JsonHelper.cpp b/libweb3jsonrpc/JsonHelper.cpp index 80dcf8e3b..64448b418 100644 --- a/libweb3jsonrpc/JsonHelper.cpp +++ b/libweb3jsonrpc/JsonHelper.cpp @@ -537,6 +537,8 @@ TransactionSkeleton toTransactionSkeleton( Json::Value const& _json ) { if ( !_json["gasPrice"].empty() ) ret.gasPrice = jsToU256( _json["gasPrice"].asString() ); + else if ( !_json["maxFeePerGas"].empty() ) + ret.gasPrice = jsToU256( _json["maxFeePerGas"].asString() ); if ( !_json["data"].empty() ) // ethereum.js has preconstructed the data array ret.data = jsToBytes( _json["data"].asString(), OnFailed::Throw ); From a022d7049a1ba88e8ce346f3312b064d4fc18065 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 22 Apr 2024 11:55:47 +0100 Subject: [PATCH 31/53] #1719 fix build after merge --- test/unittests/libethereum/Transaction.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unittests/libethereum/Transaction.cpp b/test/unittests/libethereum/Transaction.cpp index 3b827e294..b0c1ca483 100644 --- a/test/unittests/libethereum/Transaction.cpp +++ b/test/unittests/libethereum/Transaction.cpp @@ -52,7 +52,7 @@ BOOST_AUTO_TEST_CASE( TransactionGasRequired, "cf52d85ecec934c6f46ea3e96d6355eb8ccde261e1e419885761a0234565f6d227d8eba0937b0" "f03cb25f83aeb24c13b7a39a9ef6e80c1ea272a3c" ), CheckTransaction::None ); - BOOST_CHECK_EQUAL( tr.baseGasRequired( FrontierSchedule ), 14 * 68 + 21000 ); + BOOST_CHECK_EQUAL( tr.baseGasRequired( HomesteadSchedule ), 14 * 68 + 21000 ); BOOST_CHECK_EQUAL( tr.baseGasRequired( IstanbulSchedule ), 14 * 16 + 21000 ); tr = Transaction ( @@ -63,7 +63,7 @@ BOOST_AUTO_TEST_CASE( TransactionGasRequired, "23927f0e208494bd1fd8876597899d72025167fed902e9c1c417ddd8639bb7b4a02a63ea48f7e" "94df3a40c4a840ba98da02f13817acb5fe137d40f632e6c8ed367" ), CheckTransaction::None ); - BOOST_CHECK_EQUAL( tr.baseGasRequired( FrontierSchedule ), 14 * 68 + 21000 ); + BOOST_CHECK_EQUAL( tr.baseGasRequired( HomesteadSchedule ), 14 * 68 + 21000 ); BOOST_CHECK_EQUAL( tr.baseGasRequired( IstanbulSchedule ), 14 * 16 + 21000 ); } From e14427db7b48afbd944adc4aede69662b276e818 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 22 Apr 2024 13:52:57 +0100 Subject: [PATCH 32/53] #1719 add patch timestamp to json rpc api --- libethereum/SchainPatch.cpp | 4 +++ libethereum/SchainPatch.h | 5 +++ libethereum/SchainPatchEnum.h | 1 + libweb3jsonrpc/Eth.cpp | 44 +++++++++++++---------- test/unittests/libweb3jsonrpc/jsonrpc.cpp | 8 ++++- 5 files changed, 42 insertions(+), 20 deletions(-) diff --git a/libethereum/SchainPatch.cpp b/libethereum/SchainPatch.cpp index 1ae076376..bcbe90274 100644 --- a/libethereum/SchainPatch.cpp +++ b/libethereum/SchainPatch.cpp @@ -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 ); } @@ -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 ) ) ); diff --git a/libethereum/SchainPatch.h b/libethereum/SchainPatch.h index d8fabce97..bb630691c 100644 --- a/libethereum/SchainPatch.h +++ b/libethereum/SchainPatch.h @@ -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 diff --git a/libethereum/SchainPatchEnum.h b/libethereum/SchainPatchEnum.h index b1f439211..10fa231c9 100644 --- a/libethereum/SchainPatchEnum.h +++ b/libethereum/SchainPatchEnum.h @@ -16,6 +16,7 @@ enum class SchainPatchEnum { StorageDestructionPatch, SkipInvalidTransactionsPatch, SelfdestructStorageLimitPatch, + EIP1559TransactionsPatch, PatchesCount }; diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index 5140836e9..be43d7e58 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -537,15 +537,18 @@ Json::Value Eth::eth_getBlockByHash( string const& _blockHash, bool _includeTran return Json::Value( Json::nullValue ); u256 baseFeePerGas; - try { - baseFeePerGas = client()->gasBidPrice( client()->numberFromHash( h ) ); - } catch ( std::invalid_argument& _e ) { - cdebug << "Cannot get gas price for block " << _blockHash; - cdebug << _e.what(); - // set default gasPrice - // probably the price was rotated out as we are asking the price for the old block - baseFeePerGas = client()->gasBidPrice(); - } + if ( EIP1559TransactionsPatch::isEnabledWhen( client()->blockInfo( h ).timestamp() ) ) + try { + baseFeePerGas = client()->gasBidPrice( client()->numberFromHash( h ) ); + } catch ( std::invalid_argument& _e ) { + cdebug << "Cannot get gas price for block " << h; + cdebug << _e.what(); + // set default gasPrice + // probably the price was rotated out as we are asking the price for the old block + baseFeePerGas = client()->gasBidPrice(); + } + else + baseFeePerGas = 0; if ( _includeTransactions ) { Transactions transactions = client()->transactions( h ); @@ -596,15 +599,18 @@ Json::Value Eth::eth_getBlockByNumber( string const& _blockNumber, bool _include return Json::Value( Json::nullValue ); u256 baseFeePerGas; - try { - baseFeePerGas = client()->gasBidPrice( h ); - } catch ( std::invalid_argument& _e ) { - cdebug << "Cannot get gas price for block " << h; - cdebug << _e.what(); - // set default gasPrice - // probably the price was rotated out as we are asking the price for the old block - baseFeePerGas = client()->gasBidPrice(); - } + if ( EIP1559TransactionsPatch::isEnabledWhen( client()->blockInfo( h ).timestamp() ) ) + try { + baseFeePerGas = client()->gasBidPrice( h ); + } catch ( std::invalid_argument& _e ) { + cdebug << "Cannot get gas price for block " << h; + cdebug << _e.what(); + // set default gasPrice + // probably the price was rotated out as we are asking the price for the old block + baseFeePerGas = client()->gasBidPrice(); + } + else + baseFeePerGas = 0; #ifdef HISTORIC_STATE h256 bh = client()->hashFromNumber( h ); @@ -957,7 +963,7 @@ Json::Value Eth::eth_feeHistory( const std::string& _blockCount, const std::stri for ( auto bn = newestBlock; bn > oldestBlock - 1; --bn ) { auto blockInfo = client()->blockInfo( client()->hashFromNumber( bn ) ); - if ( blockInfo.timestamp() ) + if ( EIP1559TransactionsPatch::isEnabledWhen( blockInfo.timestamp() ) ) result["baseFeePerGas"].append( toJS( client()->gasBidPrice( bn ) ) ); else result["baseFeePerGas"].append( toJS( 0 ) ); diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index c41a1c937..5a180904b 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -3029,6 +3030,8 @@ BOOST_AUTO_TEST_CASE( eip1559RpcMethods ) { // Set chainID = 151 ret["params"]["chainID"] = "0x97"; + time_t eip1559PatchActivationTimestamp = time(nullptr) + 8; + ret["skaleConfig"]["sChain"]["EIP1559TransactionsPatchTimestamp"] = eip1559PatchActivationTimestamp; Json::FastWriter fastWriter; std::string config = fastWriter.write( ret ); @@ -3058,7 +3061,7 @@ BOOST_AUTO_TEST_CASE( eip1559RpcMethods ) { percentiles[0] = 20; percentiles[1] = 80; - size_t blockCnt = 3; + size_t blockCnt = 7; auto feeHistory = fixture.rpcClient->eth_feeHistory( toJS( blockCnt ), "latest", percentiles ); BOOST_REQUIRE( feeHistory["oldestBlock"] == toJS( bn - blockCnt + 1 ) ); @@ -3068,6 +3071,9 @@ BOOST_AUTO_TEST_CASE( eip1559RpcMethods ) { for (Json::Value::ArrayIndex i = 0; i < blockCnt; ++i) { BOOST_REQUIRE( feeHistory["baseFeePerGas"][i].isString() ); + std::string estimatedBaseFeePerGas = EIP1559TransactionsPatch::isEnabledWhen( + fixture.client->blockInfo( i ).timestamp() ) ? toJS( fixture.client->blockInfo( i ).timestamp() ) : toJS( 0 ); + BOOST_REQUIRE( feeHistory["baseFeePerGas"][i].asString() == estimatedBaseFeePerGas ); BOOST_REQUIRE_GT( feeHistory["gasUsedRatio"][i].asDouble(), 0 ); BOOST_REQUIRE_GT( 1, feeHistory["gasUsedRatio"][i].asDouble() ); for ( Json::Value::ArrayIndex j = 0; j < percentiles.size(); ++j ) { From 41c3a8782e3d9bc1b47b4b0571e906e7fb8a307c Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 22 Apr 2024 16:23:55 +0100 Subject: [PATCH 33/53] #1719 add eip1559PatchTimestamp --- libethcore/TransactionBase.cpp | 10 +++++++--- libethcore/TransactionBase.h | 10 +++++----- libethereum/Block.cpp | 3 ++- libethereum/BlockChain.cpp | 8 +++++--- libethereum/ClientBase.cpp | 17 ++++++++++------- libethereum/SkaleHost.cpp | 6 ++++-- libethereum/Transaction.cpp | 10 ++++++---- libethereum/Transaction.h | 8 ++++---- libethereum/TransactionQueue.cpp | 4 +++- libweb3jsonrpc/Eth.cpp | 7 ++++--- 10 files changed, 50 insertions(+), 33 deletions(-) diff --git a/libethcore/TransactionBase.cpp b/libethcore/TransactionBase.cpp index 21d2180e5..7dfa8b738 100644 --- a/libethcore/TransactionBase.cpp +++ b/libethcore/TransactionBase.cpp @@ -326,11 +326,15 @@ TransactionType TransactionBase::getTransactionType( bytesConstRef _rlp ) { } TransactionBase::TransactionBase( - bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ) { + bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid, bool _eip1559Enabled ) { MICROPROFILE_SCOPEI( "TransactionBase", "ctor", MP_GOLD2 ); try { - TransactionType txnType = getTransactionType( _rlpData ); - fillFromBytesByType( _rlpData, _checkSig, _allowInvalid, txnType ); + if ( _eip1559Enabled ) { + TransactionType txnType = getTransactionType( _rlpData ); + fillFromBytesByType( _rlpData, _checkSig, _allowInvalid, txnType ); + } else { + fillFromBytesLegacy( _rlpData, _checkSig, _allowInvalid ); + } } catch ( ... ) { m_type = Type::Invalid; RLPStream s; diff --git a/libethcore/TransactionBase.h b/libethcore/TransactionBase.h index 431f0dd8c..310ef741a 100644 --- a/libethcore/TransactionBase.h +++ b/libethcore/TransactionBase.h @@ -98,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; diff --git a/libethereum/Block.cpp b/libethereum/Block.cpp index 23fe1deac..f9de3c7e7 100644 --- a/libethereum/Block.cpp +++ b/libethereum/Block.cpp @@ -1018,7 +1018,8 @@ void Block::commitToSeal( receiptsMap.insert( std::make_pair( k.out(), receiptrlp.out() ) ); dev::bytes txOutput = m_transactions[i].toBytes(); - if ( m_transactions[i].txType() != dev::eth::TransactionType::Legacy ) { + if ( EIP1559TransactionsPatch::isEnabledInWorkingBlock() && + m_transactions[i].txType() != dev::eth::TransactionType::Legacy ) { RLPStream s; s.append( txOutput ); txOutput = s.out(); diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index bb5a049b7..0a3695c56 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -1736,9 +1736,11 @@ VerifiedBlockRef BlockChain::verifyBlock( bytesConstRef _block, for ( RLP const& tr : r[1] ) { 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, + EIP1559TransactionsPatch::isEnabledInWorkingBlock() ); Ethash::verifyTransaction( chainParams(), _ir, t, this->info( numberHash( h.number() - 1 ) ).timestamp(), h, 0 ); // the gasUsed vs diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index 387e66b46..f539f756d 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -389,7 +389,8 @@ BlockDetails ClientBase::blockDetails( h256 _hash ) const { Transaction ClientBase::transaction( h256 _transactionHash ) const { // allow invalid! - return Transaction( bc().transaction( _transactionHash ), CheckTransaction::Cheap, true ); + return Transaction( bc().transaction( _transactionHash ), CheckTransaction::Cheap, true, + EIP1559TransactionsPatch::isEnabledInWorkingBlock() ); } LocalisedTransaction ClientBase::localisedTransaction( h256 const& _transactionHash ) const { @@ -402,15 +403,16 @@ 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::isEnabledInWorkingBlock() ); 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::isEnabledInWorkingBlock() ); return LocalisedTransaction( t, _blockHash, _i, numberFromHash( _blockHash ) ); } @@ -422,8 +424,8 @@ LocalisedTransactionReceipt ClientBase::localisedTransactionReceipt( h256 const& _transactionHash ) const { std::pair< h256, unsigned > tl = bc().transactionLocation( _transactionHash ); // allow invalid - Transaction t = - Transaction( bc().transaction( tl.first, tl.second ), CheckTransaction::Cheap, true ); + Transaction t = Transaction( bc().transaction( tl.first, tl.second ), CheckTransaction::Cheap, + true, EIP1559TransactionsPatch::isEnabledInWorkingBlock() ); TransactionReceipt tr = bc().transactionReceipt( tl.first, tl.second ); u256 gasUsed = tr.cumulativeGasUsed(); if ( tl.second > 0 ) @@ -455,7 +457,8 @@ Transactions ClientBase::transactions( h256 _blockHash ) const { Transactions res; for ( unsigned i = 0; i < b[1].itemCount(); i++ ) { auto txRlp = b[1][i]; - res.emplace_back( bytesRefFromTransactionRlp( txRlp ), CheckTransaction::Cheap, true ); + res.emplace_back( bytesRefFromTransactionRlp( txRlp ), CheckTransaction::Cheap, true, + EIP1559TransactionsPatch::isEnabledInWorkingBlock() ); } return res; } diff --git a/libethereum/SkaleHost.cpp b/libethereum/SkaleHost.cpp index 8cab6935b..0f525a21f 100644 --- a/libethereum/SkaleHost.cpp +++ b/libethereum/SkaleHost.cpp @@ -332,7 +332,8 @@ h256 SkaleHost::receiveTransaction( std::string _rlp ) { return h256(); } - Transaction transaction( jsToBytes( _rlp, OnFailed::Throw ), CheckTransaction::None ); + Transaction transaction( jsToBytes( _rlp, OnFailed::Throw ), CheckTransaction::None, + EIP1559TransactionsPatch::isEnabledInWorkingBlock() ); h256 sha = transaction.sha3(); @@ -668,7 +669,8 @@ void SkaleHost::createBlock( const ConsensusExtFace::transactions_vector& _appro // for test std::thread( [t, this]() { m_client.importTransaction( t ); } // ).detach(); } else { - Transaction t( data, CheckTransaction::Everything, true ); + Transaction t( data, CheckTransaction::Everything, true, + EIP1559TransactionsPatch::isEnabledInWorkingBlock() ); t.checkOutExternalGas( m_client.chainParams(), latestInfo.timestamp(), m_client.number(), false ); out_txns.push_back( t ); diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp index 2d8f80f6e..d2c7f9962 100644 --- a/libethereum/Transaction.cpp +++ b/libethereum/Transaction.cpp @@ -164,11 +164,13 @@ Transaction::Transaction( const u256& _value, const u256& _gasPrice, const u256& const bytes& _data, const u256& _nonce ) : TransactionBase( _value, _gasPrice, _gas, _data, _nonce ) {} -Transaction::Transaction( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ) - : TransactionBase( _rlpData, _checkSig, _allowInvalid ) {} +Transaction::Transaction( + bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid, bool _eip1559Enabled ) + : TransactionBase( _rlpData, _checkSig, _allowInvalid, _eip1559Enabled ) {} -Transaction::Transaction( const bytes& _rlp, CheckTransaction _checkSig, bool _allowInvalid ) - : Transaction( &_rlp, _checkSig, _allowInvalid ) {} +Transaction::Transaction( + const bytes& _rlp, CheckTransaction _checkSig, bool _allowInvalid, bool _eip1559Enabled ) + : Transaction( &_rlp, _checkSig, _allowInvalid, _eip1559Enabled ) {} bool Transaction::hasExternalGas() const { if ( !m_externalGasIsChecked ) { diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h index e35edf50b..9d3894f31 100644 --- a/libethereum/Transaction.h +++ b/libethereum/Transaction.h @@ -107,12 +107,12 @@ class Transaction : public TransactionBase { u256 const& _nonce = Invalid256 ); /// Constructs a transaction from the given RLP. - explicit Transaction( - bytesConstRef _rlp, CheckTransaction _checkSig, bool _allowInvalid = false ); + explicit Transaction( bytesConstRef _rlp, CheckTransaction _checkSig, + bool _allowInvalid = false, bool _eip1559Enabled = false ); /// Constructs a transaction from the given RLP. - explicit Transaction( - bytes const& _rlp, CheckTransaction _checkSig, bool _allowInvalid = false ); + explicit Transaction( bytes const& _rlp, CheckTransaction _checkSig, bool _allowInvalid = false, + bool _eip1559Enabled = false ); Transaction( Transaction const& ) = default; diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 284e5c648..e2ed6960d 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -26,6 +26,7 @@ #include "Transaction.h" #include #include +#include #include #include @@ -94,7 +95,8 @@ void TransactionQueue::HandleDestruction() { ImportResult TransactionQueue::import( bytesConstRef _transactionRLP, IfDropped _ik, bool _isFuture ) { try { - Transaction t = Transaction( _transactionRLP, CheckTransaction::Everything ); + Transaction t = Transaction( _transactionRLP, CheckTransaction::Everything, false, + EIP1559TransactionsPatch::isEnabledInWorkingBlock() ); return import( t, _ik, _isFuture ); } catch ( Exception const& ) { return ImportResult::Malformed; diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index be43d7e58..b50ec9416 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -410,8 +410,8 @@ Json::Value Eth::setSchainExitTime( Json::Value const& /*_transaction*/ ) { Json::Value Eth::eth_inspectTransaction( std::string const& _rlp ) { try { - return toJson( - Transaction( jsToBytes( _rlp, OnFailed::Throw ), CheckTransaction::Everything ) ); + return toJson( Transaction( jsToBytes( _rlp, OnFailed::Throw ), + CheckTransaction::Everything, EIP1559TransactionsPatch::isEnabledInWorkingBlock() ) ); } catch ( ... ) { BOOST_THROW_EXCEPTION( JsonRpcException( Errors::ERROR_RPC_INVALID_PARAMS ) ); } @@ -422,7 +422,8 @@ Json::Value Eth::eth_inspectTransaction( std::string const& _rlp ) { string Eth::eth_sendRawTransaction( std::string const& _rlp ) { // Don't need to check the transaction signature (CheckTransaction::None) since it // will be checked as a part of transaction import - Transaction t( jsToBytes( _rlp, OnFailed::Throw ), CheckTransaction::None ); + Transaction t( jsToBytes( _rlp, OnFailed::Throw ), CheckTransaction::None, + EIP1559TransactionsPatch::isEnabledInWorkingBlock() ); return toJS( client()->importTransaction( t ) ); } From 798f2b1c3104d03f7c9a0117958d57a7eb5d7911 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 22 Apr 2024 17:04:28 +0100 Subject: [PATCH 34/53] #1719 fix tests --- test/unittests/libweb3jsonrpc/jsonrpc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index 5a180904b..fec235c8a 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -3030,7 +3030,7 @@ BOOST_AUTO_TEST_CASE( eip1559RpcMethods ) { // Set chainID = 151 ret["params"]["chainID"] = "0x97"; - time_t eip1559PatchActivationTimestamp = time(nullptr) + 8; + time_t eip1559PatchActivationTimestamp = time(nullptr) + 5; ret["skaleConfig"]["sChain"]["EIP1559TransactionsPatchTimestamp"] = eip1559PatchActivationTimestamp; Json::FastWriter fastWriter; @@ -3072,7 +3072,7 @@ BOOST_AUTO_TEST_CASE( eip1559RpcMethods ) { for (Json::Value::ArrayIndex i = 0; i < blockCnt; ++i) { BOOST_REQUIRE( feeHistory["baseFeePerGas"][i].isString() ); std::string estimatedBaseFeePerGas = EIP1559TransactionsPatch::isEnabledWhen( - fixture.client->blockInfo( i ).timestamp() ) ? toJS( fixture.client->blockInfo( i ).timestamp() ) : toJS( 0 ); + fixture.client->blockInfo( bn - i ).timestamp() ) ? toJS( fixture.client->gasBidPrice( bn - i ) ) : toJS( 0 ); BOOST_REQUIRE( feeHistory["baseFeePerGas"][i].asString() == estimatedBaseFeePerGas ); BOOST_REQUIRE_GT( feeHistory["gasUsedRatio"][i].asDouble(), 0 ); BOOST_REQUIRE_GT( 1, feeHistory["gasUsedRatio"][i].asDouble() ); From dfb3f3e4aba50f90db6d08b3d7d05cae130780cb Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 22 Apr 2024 19:45:58 +0100 Subject: [PATCH 35/53] #1719 add patchTimestamp to tests --- libethereum/BlockChain.cpp | 4 +- libethereum/ClientBase.cpp | 10 ++-- libweb3jsonrpc/Eth.cpp | 2 +- test/unittests/libweb3jsonrpc/jsonrpc.cpp | 58 ++++++++++++++++++----- 4 files changed, 55 insertions(+), 19 deletions(-) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 0a3695c56..fc389ab62 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -1739,8 +1739,8 @@ VerifiedBlockRef BlockChain::verifyBlock( bytesConstRef _block, Transaction t( d, ( _ir & ImportRequirements::TransactionSignatures ) ? CheckTransaction::Everything : - CheckTransaction::None, - EIP1559TransactionsPatch::isEnabledInWorkingBlock() ); + CheckTransaction::None, false, + EIP1559TransactionsPatch::isEnabledWhen( h.timestamp() ) ); Ethash::verifyTransaction( chainParams(), _ir, t, this->info( numberHash( h.number() - 1 ) ).timestamp(), h, 0 ); // the gasUsed vs diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index f539f756d..d0267a3f9 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -389,8 +389,9 @@ BlockDetails ClientBase::blockDetails( h256 _hash ) const { Transaction ClientBase::transaction( h256 _transactionHash ) const { // allow invalid! + auto tl = bc().transactionLocation( _transactionHash ); return Transaction( bc().transaction( _transactionHash ), CheckTransaction::Cheap, true, - EIP1559TransactionsPatch::isEnabledInWorkingBlock() ); + EIP1559TransactionsPatch::isEnabledWhen( blockInfo( tl.first ).timestamp() ) ); } LocalisedTransaction ClientBase::localisedTransaction( h256 const& _transactionHash ) const { @@ -404,15 +405,14 @@ Transaction ClientBase::transaction( h256 _blockHash, unsigned _i ) const { if ( _i < b[1].itemCount() ) // allow invalid return Transaction( b[1][_i].data(), CheckTransaction::Cheap, true, - EIP1559TransactionsPatch::isEnabledInWorkingBlock() ); + EIP1559TransactionsPatch::isEnabledWhen( blockInfo( _blockHash ).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, - EIP1559TransactionsPatch::isEnabledInWorkingBlock() ); + Transaction t = Transaction( bc().transaction( _blockHash, _i ), CheckTransaction::Cheap, true, EIP1559TransactionsPatch::isEnabledWhen( blockInfo( _blockHash ).timestamp() ) ); return LocalisedTransaction( t, _blockHash, _i, numberFromHash( _blockHash ) ); } @@ -425,7 +425,7 @@ 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, EIP1559TransactionsPatch::isEnabledInWorkingBlock() ); + true, EIP1559TransactionsPatch::isEnabledWhen( blockInfo( tl.first ).timestamp() ) ); TransactionReceipt tr = bc().transactionReceipt( tl.first, tl.second ); u256 gasUsed = tr.cumulativeGasUsed(); if ( tl.second > 0 ) diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index b50ec9416..cf1c8d1b3 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -422,7 +422,7 @@ Json::Value Eth::eth_inspectTransaction( std::string const& _rlp ) { string Eth::eth_sendRawTransaction( std::string const& _rlp ) { // Don't need to check the transaction signature (CheckTransaction::None) since it // will be checked as a part of transaction import - Transaction t( jsToBytes( _rlp, OnFailed::Throw ), CheckTransaction::None, + Transaction t( jsToBytes( _rlp, OnFailed::Throw ), CheckTransaction::None, false, EIP1559TransactionsPatch::isEnabledInWorkingBlock() ); return toJS( client()->importTransaction( t ) ); } diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index fec235c8a..f11800574 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -2774,6 +2774,8 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { // Set chainID = 151 ret["params"]["chainID"] = "0x97"; + time_t eip1559PatchActivationTimestamp = time(nullptr) + 10; + ret["skaleConfig"]["sChain"]["EIP1559TransactionsPatchTimestamp"] = eip1559PatchActivationTimestamp; Json::FastWriter fastWriter; std::string config = fastWriter.write( ret ); @@ -2802,6 +2804,22 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { BOOST_REQUIRE( fixture.rpcClient->eth_getBalance( "0xc868AF52a6549c773082A334E5AE232e0Ea3B513", "latest" ) == "0x16345785d8a0000" ); + // try sending type1 txn before patchTimestmap + BOOST_REQUIRE_THROW( fixture.rpcClient->eth_sendRawTransaction( "0x01f8678197808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180c001a01ebdc546c8b85511b7ba831f47c4981069d7af972d10b7dce2c57225cb5df6a7a055ae1e84fea41d37589eb740a0a93017a5cd0e9f10ee50f165bf4b1b4c78ddae" ), jsonrpc::JsonRpcException ); // INVALID_PARAMS + sleep( 10 ); + + // force 1 block to update timestamp + txRefill["to"] = "0xc868AF52a6549c773082A334E5AE232e0Ea3B513"; + txRefill["from"] = senderAddress; + txRefill["gas"] = "100000"; + txRefill["gasPrice"] = fixture.rpcClient->eth_gasPrice(); + txRefill["value"] = 0; + txHash = fixture.rpcClient->eth_sendTransaction( txRefill ); + dev::eth::mineTransaction( *( fixture.client ), 1 ); + receipt = fixture.rpcClient->eth_getTransactionReceipt( txHash ); + BOOST_REQUIRE( receipt["status"] == string( "0x1" ) ); + BOOST_REQUIRE( receipt["type"] == "0x0" ); + // send 1 WEI from 0xc868AF52a6549c773082A334E5AE232e0Ea3B513 to 0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b // encoded type 1 txn txHash = fixture.rpcClient->eth_sendRawTransaction( "0x01f8678197808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180c001a01ebdc546c8b85511b7ba831f47c4981069d7af972d10b7dce2c57225cb5df6a7a055ae1e84fea41d37589eb740a0a93017a5cd0e9f10ee50f165bf4b1b4c78ddae" ); @@ -2814,15 +2832,15 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { // compare with txn hash from geth BOOST_REQUIRE( txHash == "0xc843560015a655b8f81f65a458be9019bdb5cd8e416b6329ca18f36de0b8244d" ); - BOOST_REQUIRE( dev::toHexPrefixed( fixture.client->transactions( 3 )[0].toBytes() ) == "0x01f8678197808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180c001a01ebdc546c8b85511b7ba831f47c4981069d7af972d10b7dce2c57225cb5df6a7a055ae1e84fea41d37589eb740a0a93017a5cd0e9f10ee50f165bf4b1b4c78ddae" ); + BOOST_REQUIRE( dev::toHexPrefixed( fixture.client->transactions( 4 )[0].toBytes() ) == "0x01f8678197808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180c001a01ebdc546c8b85511b7ba831f47c4981069d7af972d10b7dce2c57225cb5df6a7a055ae1e84fea41d37589eb740a0a93017a5cd0e9f10ee50f165bf4b1b4c78ddae" ); BOOST_REQUIRE( fixture.rpcClient->eth_getBalance( "0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b", "latest" ) == "0x1" ); - auto block = fixture.rpcClient->eth_getBlockByNumber( "3", false ); + auto block = fixture.rpcClient->eth_getBlockByNumber( "4", false ); BOOST_REQUIRE( block["transactions"].size() == 1 ); BOOST_REQUIRE( block["transactions"][0].asString() == txHash ); - block = fixture.rpcClient->eth_getBlockByNumber( "3", true ); + block = fixture.rpcClient->eth_getBlockByNumber( "4", true ); BOOST_REQUIRE( block["transactions"].size() == 1 ); BOOST_REQUIRE( block["transactions"][0]["hash"].asString() == txHash ); BOOST_REQUIRE( block["transactions"][0]["type"] == "0x1" ); @@ -2850,7 +2868,7 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { BOOST_REQUIRE( toJS( jsToInt( result["yParity"].asString() ) + 35 + 2 * fixture.client->chainParams().chainID ) == result["v"].asString() ); BOOST_REQUIRE( result["accessList"].isArray() ); - result = fixture.rpcClient->eth_getTransactionByBlockNumberAndIndex( "0x3", "0x0" ); + result = fixture.rpcClient->eth_getTransactionByBlockNumberAndIndex( "0x4", "0x0" ); BOOST_REQUIRE( result["hash"].asString() == txHash ); BOOST_REQUIRE( result["type"] == "0x1" ); BOOST_REQUIRE( toJS( jsToInt( result["yParity"].asString() ) + 35 + 2 * fixture.client->chainParams().chainID ) == result["v"].asString() ); @@ -2868,7 +2886,7 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { // compare with txn hash from geth BOOST_REQUIRE( txHash == "0xa6d3541e06dff71fb8344a4db2a4ad4e0b45024eb23a8f568982b70a5f50f94d" ); - BOOST_REQUIRE( dev::toHexPrefixed( fixture.client->transactions( 4 )[0].toBytes() ) == "0x01f8c38197018504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0b03eaf481958e22fc39bd1d526eb9255be1e6625614f02ca939e51c3d7e64bcaa05f675640c04bb050d27bd1f39c07b6ff742311b04dab760bb3bc206054332879" ); + BOOST_REQUIRE( dev::toHexPrefixed( fixture.client->transactions( 5 )[0].toBytes() ) == "0x01f8c38197018504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0b03eaf481958e22fc39bd1d526eb9255be1e6625614f02ca939e51c3d7e64bcaa05f675640c04bb050d27bd1f39c07b6ff742311b04dab760bb3bc206054332879" ); result = fixture.rpcClient->eth_getTransactionByHash( txHash ); BOOST_REQUIRE( result["type"] == "0x1" ); @@ -2881,7 +2899,7 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { BOOST_REQUIRE( result["accessList"][0]["storageKeys"][0].asString() == "0x0000000000000000000000000000000000000000000000000000000000000003" ); BOOST_REQUIRE( result["accessList"][0]["storageKeys"][1].asString() == "0x0000000000000000000000000000000000000000000000000000000000000007" ); - block = fixture.rpcClient->eth_getBlockByNumber( "4", true ); + block = fixture.rpcClient->eth_getBlockByNumber( "5", true ); result = block["transactions"][0]; BOOST_REQUIRE( result["type"] == "0x1" ); BOOST_REQUIRE( result["accessList"].isArray() ); @@ -2901,6 +2919,8 @@ BOOST_AUTO_TEST_CASE( eip1559Transactions ) { // Set chainID = 151 ret["params"]["chainID"] = "0x97"; + time_t eip1559PatchActivationTimestamp = time(nullptr) + 10; + ret["skaleConfig"]["sChain"]["EIP1559TransactionsPatchTimestamp"] = eip1559PatchActivationTimestamp; Json::FastWriter fastWriter; std::string config = fastWriter.write( ret ); @@ -2929,6 +2949,22 @@ BOOST_AUTO_TEST_CASE( eip1559Transactions ) { BOOST_REQUIRE( fixture.rpcClient->eth_getBalance( "0x5EdF1e852fdD1B0Bc47C0307EF755C76f4B9c251", "latest" ) == "0x16345785d8a0000" ); + // try sending type2 txn before patchTimestmap + BOOST_REQUIRE_THROW( fixture.rpcClient->eth_sendRawTransaction( "0x02f8c98197808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0f1a407dfc1a9f782001d89f617e9b3a2f295378533784fb39960dea60beea2d0a05ac3da2946554ba3d5721850f4f89ee7a0c38e4acab7130908e7904d13174388" ), jsonrpc::JsonRpcException ); // INVALID_PARAMS + sleep( 10 ); + + // force 1 block to update timestamp + txRefill["to"] = "0xc868AF52a6549c773082A334E5AE232e0Ea3B513"; + txRefill["from"] = senderAddress; + txRefill["gas"] = "100000"; + txRefill["gasPrice"] = fixture.rpcClient->eth_gasPrice(); + txRefill["value"] = 0; + txHash = fixture.rpcClient->eth_sendTransaction( txRefill ); + dev::eth::mineTransaction( *( fixture.client ), 1 ); + receipt = fixture.rpcClient->eth_getTransactionReceipt( txHash ); + BOOST_REQUIRE( receipt["status"] == string( "0x1" ) ); + BOOST_REQUIRE( receipt["type"] == "0x0" ); + // send 1 WEI from 0x5EdF1e852fdD1B0Bc47C0307EF755C76f4B9c251 to 0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b // encoded type 2 txn txHash = fixture.rpcClient->eth_sendRawTransaction( "0x02f8c98197808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0f1a407dfc1a9f782001d89f617e9b3a2f295378533784fb39960dea60beea2d0a05ac3da2946554ba3d5721850f4f89ee7a0c38e4acab7130908e7904d13174388" ); @@ -2941,16 +2977,16 @@ BOOST_AUTO_TEST_CASE( eip1559Transactions ) { // compare with txn hash from geth BOOST_REQUIRE( txHash == "0x7bd586e93e3012577de4ba33e3b887baf520cbb92c5dd10996b262f9c5c8f747" ); - std::cout << dev::toHexPrefixed( fixture.client->transactions( 3 )[0].toBytes() ) << '\n'; - BOOST_REQUIRE( dev::toHexPrefixed( fixture.client->transactions( 3 )[0].toBytes() ) == "0x02f8c98197808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0f1a407dfc1a9f782001d89f617e9b3a2f295378533784fb39960dea60beea2d0a05ac3da2946554ba3d5721850f4f89ee7a0c38e4acab7130908e7904d13174388" ); + std::cout << dev::toHexPrefixed( fixture.client->transactions( 4 )[0].toBytes() ) << '\n'; + BOOST_REQUIRE( dev::toHexPrefixed( fixture.client->transactions( 4 )[0].toBytes() ) == "0x02f8c98197808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0f1a407dfc1a9f782001d89f617e9b3a2f295378533784fb39960dea60beea2d0a05ac3da2946554ba3d5721850f4f89ee7a0c38e4acab7130908e7904d13174388" ); BOOST_REQUIRE( fixture.rpcClient->eth_getBalance( "0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b", "latest" ) == "0x1" ); - auto block = fixture.rpcClient->eth_getBlockByNumber( "3", false ); + auto block = fixture.rpcClient->eth_getBlockByNumber( "4", false ); BOOST_REQUIRE( block["transactions"].size() == 1 ); BOOST_REQUIRE( block["transactions"][0].asString() == txHash ); - block = fixture.rpcClient->eth_getBlockByNumber( "3", true ); + block = fixture.rpcClient->eth_getBlockByNumber( "4", true ); BOOST_REQUIRE( !block["baseFeePerGas"].asString().empty() ); BOOST_REQUIRE( block["transactions"].size() == 1 ); BOOST_REQUIRE( block["transactions"][0]["hash"].asString() == txHash ); @@ -2980,7 +3016,7 @@ BOOST_AUTO_TEST_CASE( eip1559Transactions ) { BOOST_REQUIRE( result["maxPriorityFeePerGas"] == "0x4a817c800" ); BOOST_REQUIRE( result["maxFeePerGas"] == "0x4a817c800" ); - result = fixture.rpcClient->eth_getTransactionByBlockNumberAndIndex( "0x3", "0x0" ); + result = fixture.rpcClient->eth_getTransactionByBlockNumberAndIndex( "0x4", "0x0" ); BOOST_REQUIRE( result["hash"].asString() == txHash ); BOOST_REQUIRE( result["type"] == "0x2" ); BOOST_REQUIRE( toJS( jsToInt( result["yParity"].asString() ) + 35 + 2 * fixture.client->chainParams().chainID ) == result["v"].asString() ); From 7fb0ac2e3b7c7280a2a3d1c49773d0b0500d72cd Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 22 Apr 2024 19:47:53 +0100 Subject: [PATCH 36/53] #1719 small fixes --- libethereum/BlockChain.cpp | 4 ++-- libethereum/ClientBase.cpp | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index fc389ab62..0ae82f506 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -1739,8 +1739,8 @@ VerifiedBlockRef BlockChain::verifyBlock( bytesConstRef _block, Transaction t( d, ( _ir & ImportRequirements::TransactionSignatures ) ? CheckTransaction::Everything : - CheckTransaction::None, false, - EIP1559TransactionsPatch::isEnabledWhen( h.timestamp() ) ); + CheckTransaction::None, + false, EIP1559TransactionsPatch::isEnabledWhen( h.timestamp() ) ); Ethash::verifyTransaction( chainParams(), _ir, t, this->info( numberHash( h.number() - 1 ) ).timestamp(), h, 0 ); // the gasUsed vs diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index d0267a3f9..8c6377967 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -412,7 +412,8 @@ Transaction ClientBase::transaction( h256 _blockHash, unsigned _i ) const { LocalisedTransaction ClientBase::localisedTransaction( h256 const& _blockHash, unsigned _i ) const { // allow invalid - Transaction t = Transaction( bc().transaction( _blockHash, _i ), CheckTransaction::Cheap, true, EIP1559TransactionsPatch::isEnabledWhen( blockInfo( _blockHash ).timestamp() ) ); + Transaction t = Transaction( bc().transaction( _blockHash, _i ), CheckTransaction::Cheap, true, + EIP1559TransactionsPatch::isEnabledWhen( blockInfo( _blockHash ).timestamp() ) ); return LocalisedTransaction( t, _blockHash, _i, numberFromHash( _blockHash ) ); } From 31f49afb8fa74c07bfb11f3d84001d6f302f8519 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 23 Apr 2024 10:35:59 +0100 Subject: [PATCH 37/53] #1719 fix tests --- test/unittests/libethereum/Transaction.cpp | 36 +++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/test/unittests/libethereum/Transaction.cpp b/test/unittests/libethereum/Transaction.cpp index 55713652d..3104cc46f 100644 --- a/test/unittests/libethereum/Transaction.cpp +++ b/test/unittests/libethereum/Transaction.cpp @@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE( TransactionGasRequired, "000000000000000000000000000000000000000000000000000000000000780a08ae3a721ee02" "cf52d85ecec934c6f46ea3e96d6355eb8ccde261e1e419885761a0234565f6d227d8eba0937b0" "f03cb25f83aeb24c13b7a39a9ef6e80c1ea272a3c" ), - CheckTransaction::None ); + CheckTransaction::None, false, true ); BOOST_CHECK_EQUAL( tr.baseGasRequired( HomesteadSchedule ), 14 * 68 + 21000 ); BOOST_CHECK_EQUAL( tr.baseGasRequired( IstanbulSchedule ), 14 * 16 + 21000 ); @@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE( TransactionGasRequired, "0000003a0000000000000000000000000000000000000000000000000000000000000000780a0" "23927f0e208494bd1fd8876597899d72025167fed902e9c1c417ddd8639bb7b4a02a63ea48f7e" "94df3a40c4a840ba98da02f13817acb5fe137d40f632e6c8ed367" ), - CheckTransaction::None ); + CheckTransaction::None, false, true ); BOOST_CHECK_EQUAL( tr.baseGasRequired( HomesteadSchedule ), 14 * 68 + 21000 ); BOOST_CHECK_EQUAL( tr.baseGasRequired( IstanbulSchedule ), 14 * 16 + 21000 ); } @@ -86,7 +86,7 @@ BOOST_AUTO_TEST_CASE( TransactionWithEmptyRecepient ) { "000003a0000000000000000000000000000000000000000000000000000000000000000780a08d795591e0eb53" "fb374a804ba3f73cf291069549d62316219811c3f7fb8cfad0a07e9d0bd7fabc8f74475624c912b5334dc49224" "b1dede6c802d52a35254bfc457" ); - tx = Transaction( txRlp, CheckTransaction::None ); // shouldn't throw + tx = Transaction( txRlp, CheckTransaction::None, false, true ); // shouldn't throw // recipient RLP is 0xc0 (empty list) txRlp = fromHex( @@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE( TransactionWithEmptyRecepient ) { "000003a0000000000000000000000000000000000000000000000000000000000000000780a08d795591e0eb53" "fb374a804ba3f73cf291069549d62316219811c3f7fb8cfad0a07e9d0bd7fabc8f74475624c912b5334dc49224" "b1dede6c802d52a35254bfc457" ); - BOOST_REQUIRE_THROW( Transaction( txRlp, CheckTransaction::None ), InvalidTransactionFormat ); + BOOST_REQUIRE_THROW( Transaction( txRlp, CheckTransaction::None, false, true ), InvalidTransactionFormat ); txRlp = fromHex( "0x02f8c38197808504a817c8008504a817c80082753080018e0358ac39584bc98a7c979f984b03f85bf85994de" @@ -103,7 +103,7 @@ BOOST_AUTO_TEST_CASE( TransactionWithEmptyRecepient ) { "000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0c8" "029a8b702d54c79ef18b557e755a1bfd8a4afcfcf31813790df34a6f740a95a00ceb8fdf611b4c9ff8d007d2a5" "44bc4bfae0e97a03e32b1c8b8208c82cebcafb" ); - tx = Transaction( txRlp, CheckTransaction::None ); // shouldn't throw + tx = Transaction( txRlp, CheckTransaction::None, false, true ); // shouldn't throw // recipient RLP is 0xc0 (empty list) txRlp = fromHex( @@ -112,7 +112,7 @@ BOOST_AUTO_TEST_CASE( TransactionWithEmptyRecepient ) { "000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0c8" "029a8b702d54c79ef18b557e755a1bfd8a4afcfcf31813790df34a6f740a95a00ceb8fdf611b4c9ff8d007d2a5" "44bc4bfae0e97a03e32b1c8b8208c82cebcafb" ); - BOOST_REQUIRE_THROW( Transaction( txRlp, CheckTransaction::None ), InvalidTransactionFormat ); + BOOST_REQUIRE_THROW( Transaction( txRlp, CheckTransaction::None, false, true ), InvalidTransactionFormat ); } BOOST_AUTO_TEST_CASE( TransactionNotReplayProtected, @@ -132,7 +132,7 @@ BOOST_AUTO_TEST_CASE( TransactionNotReplayProtected, "0000000000000000000000000000000000000000000000000003a000000000000000000000000000000000" "0000000000000000000000000000000701a0a3b1de6f2958e1e34db86438bba310637f2e799fe9768a143a" "d87e47c33d1e6ca00e04ef9fe6bb01176c5a4c5bf4a070662478a320eaaff2895d17451c8d61d472" ); - BOOST_REQUIRE_THROW( Transaction( txRlp, CheckTransaction::None, false ), dev::BadCast ); + BOOST_REQUIRE_THROW( Transaction( txRlp, CheckTransaction::None, false, true ), dev::BadCast ); txRlp = fromHex( "0x02f8d5808504a817c8008504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b" @@ -141,7 +141,7 @@ BOOST_AUTO_TEST_CASE( TransactionNotReplayProtected, "000000000000000000000000000000000000000000000780a023927f0e208494bd1fd8876597899d720251" "67fed902e9c1c417ddd8639bb7b4a02a63ea48f7e94df3a40c4a840ba98da02f13817acb5fe137d40f632e" "6c8ed367" ); - BOOST_REQUIRE_THROW( Transaction( txRlp, CheckTransaction::None, false ), dev::BadCast ); + BOOST_REQUIRE_THROW( Transaction( txRlp, CheckTransaction::None, false, true ), dev::BadCast ); } BOOST_AUTO_TEST_CASE( TransactionChainIDMax64Bit, @@ -168,7 +168,7 @@ BOOST_AUTO_TEST_CASE( TransactionChainIDMax64Bit, "000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000" "00000000000000000000000000000000000701a0e236de02b843139aebfce593d680c06ce79cfd2f2e7f9dcac9" "fe23b38060591aa0734952245446ad42e47ec996c9a7b02973cbc8dd944c9622714416b2bef122f4" ); - tx1 = Transaction{txRlp1, CheckTransaction::None}; + tx1 = Transaction{txRlp1, CheckTransaction::None, false, true}; tx1.checkChainId( std::numeric_limits< uint64_t >::max(), false ); txRlp1 = fromHex( @@ -178,7 +178,7 @@ BOOST_AUTO_TEST_CASE( TransactionChainIDMax64Bit, "00000000000000000000000000000000000000000000000780a0b62465e633b565f2f3632125b452d8df66d4f6" "b48b58f59da6201234e3f9ce75a0467f18ca2b64f3642cb37e7d5470bbac5fbc62c66b23a0ff955b994803fcf3" "74" ); - tx1 = Transaction{txRlp1, CheckTransaction::None}; + tx1 = Transaction{txRlp1, CheckTransaction::None, false, true}; tx1.checkChainId( std::numeric_limits< uint64_t >::max(), false ); } @@ -204,7 +204,7 @@ BOOST_AUTO_TEST_CASE( TransactionChainIDBiggerThan64Bit ) { "0000000000000000000000000000000000000780a0e108b83ed5e1b701b249970e61d9ae409eb6870af96f1a9d" "8827f497375ae5c8a0795eb0b4f36fe712af5e6a8447802c9eb0913a2add86174552bf2e4b0e183feb" ); RLPStream rlpStream; - auto tx = Transaction( txRlp1, CheckTransaction::None ); + auto tx = Transaction( txRlp1, CheckTransaction::None, false, true ); auto txBytes = tx.toBytes(IncludeSignature::WithSignature); BOOST_REQUIRE( txBytes != txRlp1 ); @@ -215,7 +215,7 @@ BOOST_AUTO_TEST_CASE( TransactionChainIDBiggerThan64Bit ) { "0000000000000000000000000000000000000000000000000780a0912e3aad5af05008d3a282d2a76dc975d234" "4eb34e2500c924a58ccfdc9dbeb4a04afcffcb5d1897df030d45a7eeb3ceb7c7e6fe368fc47865156b4899de32" "01c7" ); - tx = Transaction( txRlp1, CheckTransaction::None ); + tx = Transaction( txRlp1, CheckTransaction::None, false, true ); txBytes = tx.toBytes(IncludeSignature::WithSignature); BOOST_REQUIRE( txBytes != txRlp1 ); } @@ -238,7 +238,7 @@ BOOST_AUTO_TEST_CASE( TransactionReplayProtected ) { "000000000000000003a0000000000000000000000000000000000000000000000000000000000000000780a0b0" "3eaf481958e22fc39bd1d526eb9255be1e6625614f02ca939e51c3d7e64bcaa05f675640c04bb050d27bd1f39c" "07b6ff742311b04dab760bb3bc206054332879" ); - tx = Transaction( txRlp, CheckTransaction::None ); + tx = Transaction( txRlp, CheckTransaction::None, false, true ); tx.checkChainId( 151, false ); BOOST_REQUIRE_THROW( tx.checkChainId( 123, false ), InvalidSignature ); @@ -250,7 +250,7 @@ BOOST_AUTO_TEST_CASE( TransactionReplayProtected ) { "000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000" "00000780a0f1a407dfc1a9f782001d89f617e9b3a2f295378533784fb39960dea60beea2d0a05ac3da2946554b" "a3d5721850f4f89ee7a0c38e4acab7130908e7904d13174388" ); - tx = Transaction( txRlp, CheckTransaction::None ); + tx = Transaction( txRlp, CheckTransaction::None, false, true ); tx.checkChainId( 151, false ); BOOST_REQUIRE_THROW( tx.checkChainId( 123, false ), InvalidSignature ); @@ -267,7 +267,7 @@ BOOST_AUTO_TEST_CASE( accessList ) { "3eaf481958e22fc39bd1d526eb9255be1e6625614f02ca939e51c3d7e64bcaa05f675640c04bb050d27bd1f39c" "07b6ff742311b04dab760bb3bc206054332879" ); Transaction tx; - BOOST_REQUIRE_NO_THROW( tx = Transaction( txRlp, CheckTransaction::None ) ); + BOOST_REQUIRE_NO_THROW( tx = Transaction( txRlp, CheckTransaction::None, false, true ) ); BOOST_REQUIRE( tx.accessList().size() == 1 ); // empty accessList @@ -275,7 +275,7 @@ BOOST_AUTO_TEST_CASE( accessList ) { "0x01f8678197808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180c001a01ebdc5" "46c8b85511b7ba831f47c4981069d7af972d10b7dce2c57225cb5df6a7a055ae1e84fea41d37589eb740a0a930" "17a5cd0e9f10ee50f165bf4b1b4c78ddae" ); - BOOST_REQUIRE_NO_THROW( tx = Transaction( txRlp, CheckTransaction::None ) ); + BOOST_REQUIRE_NO_THROW( tx = Transaction( txRlp, CheckTransaction::None, false, true ) ); BOOST_REQUIRE( tx.accessList().size() == 0 ); // no accessList @@ -283,7 +283,7 @@ BOOST_AUTO_TEST_CASE( accessList ) { "0x01f8678197808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b0180c080a025fffe" "aafed61a15aefd1be5ccbd19e3fe07d0088b06ab6ad960d0f6c382d8cea02e255bf1a7de0a75ccec6d00bcc367" "1af06ca9641fc02024a9d6b28f9b01307b" ); - BOOST_REQUIRE_NO_THROW( tx = Transaction( txRlp, CheckTransaction::None ) ); + BOOST_REQUIRE_NO_THROW( tx = Transaction( txRlp, CheckTransaction::None, false, true ) ); BOOST_REQUIRE( tx.accessList().size() == 0 ); // change empty accessList 0xc0 to empty array 0x80 @@ -291,7 +291,7 @@ BOOST_AUTO_TEST_CASE( accessList ) { "0x01f8678197808504a817c800827530947d36af85a184e220a656525fcbb9a63b9ab3c12b01808001a01ebdc5" "46c8b85511b7ba831f47c4981069d7af972d10b7dce2c57225cb5df6a7a055ae1e84fea41d37589eb740a0a930" "17a5cd0e9f10ee50f165bf4b1b4c78ddae" ); - BOOST_REQUIRE_THROW( Transaction( txRlp, CheckTransaction::None ), InvalidTransactionFormat ); + BOOST_REQUIRE_THROW( Transaction( txRlp, CheckTransaction::None, false, true ), InvalidTransactionFormat ); } BOOST_AUTO_TEST_CASE( ExecutionResultOutput, From a5ad610d3d55c435da1310fb1bdcdc514e80af8e Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 23 Apr 2024 13:40:08 +0100 Subject: [PATCH 38/53] #1719 small fixes --- libethereum/BlockChain.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 0ae82f506..e2339685e 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -1740,7 +1740,9 @@ VerifiedBlockRef BlockChain::verifyBlock( bytesConstRef _block, ( _ir & ImportRequirements::TransactionSignatures ) ? CheckTransaction::Everything : CheckTransaction::None, - false, EIP1559TransactionsPatch::isEnabledWhen( h.timestamp() ) ); + 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 From aeeac8bfd1e43e48b24ed4ca45ae7ef4f971d2fe Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 23 Apr 2024 15:18:39 +0100 Subject: [PATCH 39/53] #1719 fix patchTimestamp usage --- libethereum/ClientBase.cpp | 15 ++++++++++----- libweb3jsonrpc/Eth.cpp | 7 ++++--- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index 8c6377967..55b6dab96 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -391,7 +391,8 @@ Transaction ClientBase::transaction( h256 _transactionHash ) const { // allow invalid! auto tl = bc().transactionLocation( _transactionHash ); return Transaction( bc().transaction( _transactionHash ), CheckTransaction::Cheap, true, - EIP1559TransactionsPatch::isEnabledWhen( blockInfo( tl.first ).timestamp() ) ); + EIP1559TransactionsPatch::isEnabledWhen( + blockInfo( numberFromHash( tl.first ) - 1 ).timestamp() ) ); } LocalisedTransaction ClientBase::localisedTransaction( h256 const& _transactionHash ) const { @@ -405,7 +406,8 @@ Transaction ClientBase::transaction( h256 _blockHash, unsigned _i ) const { if ( _i < b[1].itemCount() ) // allow invalid return Transaction( b[1][_i].data(), CheckTransaction::Cheap, true, - EIP1559TransactionsPatch::isEnabledWhen( blockInfo( _blockHash ).timestamp() ) ); + EIP1559TransactionsPatch::isEnabledWhen( + blockInfo( numberFromHash( _blockHash ) - 1 ).timestamp() ) ); else return Transaction(); } @@ -413,7 +415,8 @@ Transaction ClientBase::transaction( h256 _blockHash, unsigned _i ) const { LocalisedTransaction ClientBase::localisedTransaction( h256 const& _blockHash, unsigned _i ) const { // allow invalid Transaction t = Transaction( bc().transaction( _blockHash, _i ), CheckTransaction::Cheap, true, - EIP1559TransactionsPatch::isEnabledWhen( blockInfo( _blockHash ).timestamp() ) ); + EIP1559TransactionsPatch::isEnabledWhen( + blockInfo( numberFromHash( _blockHash ) - 1 ).timestamp() ) ); return LocalisedTransaction( t, _blockHash, _i, numberFromHash( _blockHash ) ); } @@ -425,8 +428,10 @@ LocalisedTransactionReceipt ClientBase::localisedTransactionReceipt( h256 const& _transactionHash ) const { std::pair< h256, unsigned > tl = bc().transactionLocation( _transactionHash ); // allow invalid - Transaction t = Transaction( bc().transaction( tl.first, tl.second ), CheckTransaction::Cheap, - true, EIP1559TransactionsPatch::isEnabledWhen( blockInfo( tl.first ).timestamp() ) ); + Transaction t = + 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 ) diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index cf1c8d1b3..5ff150ecb 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -538,7 +538,8 @@ Json::Value Eth::eth_getBlockByHash( string const& _blockHash, bool _includeTran return Json::Value( Json::nullValue ); u256 baseFeePerGas; - if ( EIP1559TransactionsPatch::isEnabledWhen( client()->blockInfo( h ).timestamp() ) ) + if ( EIP1559TransactionsPatch::isEnabledWhen( + client()->blockInfo( client()->numberFromHash( h ) - 1 ).timestamp() ) ) try { baseFeePerGas = client()->gasBidPrice( client()->numberFromHash( h ) ); } catch ( std::invalid_argument& _e ) { @@ -600,7 +601,7 @@ Json::Value Eth::eth_getBlockByNumber( string const& _blockNumber, bool _include return Json::Value( Json::nullValue ); u256 baseFeePerGas; - if ( EIP1559TransactionsPatch::isEnabledWhen( client()->blockInfo( h ).timestamp() ) ) + if ( EIP1559TransactionsPatch::isEnabledWhen( client()->blockInfo( h - 1 ).timestamp() ) ) try { baseFeePerGas = client()->gasBidPrice( h ); } catch ( std::invalid_argument& _e ) { @@ -962,7 +963,7 @@ Json::Value Eth::eth_feeHistory( const std::string& _blockCount, const std::stri result["gasUsedRatio"] = Json::Value( Json::arrayValue ); result["reward"] = Json::Value( Json::arrayValue ); for ( auto bn = newestBlock; bn > oldestBlock - 1; --bn ) { - auto blockInfo = client()->blockInfo( client()->hashFromNumber( bn ) ); + auto blockInfo = client()->blockInfo( bn - 1 ); if ( EIP1559TransactionsPatch::isEnabledWhen( blockInfo.timestamp() ) ) result["baseFeePerGas"].append( toJS( client()->gasBidPrice( bn ) ) ); From d8bd5dade30dadadbd9961f231fac675b7230a5c Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 23 Apr 2024 16:19:16 +0100 Subject: [PATCH 40/53] #1719 fix patchTimestamp usage --- libethereum/ClientBase.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index 55b6dab96..f8a51807e 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -464,7 +464,8 @@ Transactions ClientBase::transactions( h256 _blockHash ) const { for ( unsigned i = 0; i < b[1].itemCount(); i++ ) { auto txRlp = b[1][i]; res.emplace_back( bytesRefFromTransactionRlp( txRlp ), CheckTransaction::Cheap, true, - EIP1559TransactionsPatch::isEnabledInWorkingBlock() ); + EIP1559TransactionsPatch::isEnabledWhen( + blockInfo( numberFromHash( _blockHash ) - 1 ).timestamp() ) ); } return res; } From cafa20dd1f2c36729c382baef024c51c42a6c528 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 24 Apr 2024 11:05:12 +0100 Subject: [PATCH 41/53] #1719 small fixes --- libweb3jsonrpc/Eth.cpp | 2 +- test/unittests/libweb3jsonrpc/jsonrpc.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index 5ff150ecb..aa6937266 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -966,7 +966,7 @@ Json::Value Eth::eth_feeHistory( const std::string& _blockCount, const std::stri auto blockInfo = client()->blockInfo( bn - 1 ); if ( EIP1559TransactionsPatch::isEnabledWhen( blockInfo.timestamp() ) ) - result["baseFeePerGas"].append( toJS( client()->gasBidPrice( bn ) ) ); + result["baseFeePerGas"].append( toJS( client()->gasBidPrice( bn - 1 ) ) ); else result["baseFeePerGas"].append( toJS( 0 ) ); diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index f11800574..4f5053b52 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -3097,7 +3097,7 @@ BOOST_AUTO_TEST_CASE( eip1559RpcMethods ) { percentiles[0] = 20; percentiles[1] = 80; - size_t blockCnt = 7; + size_t blockCnt = 9; auto feeHistory = fixture.rpcClient->eth_feeHistory( toJS( blockCnt ), "latest", percentiles ); BOOST_REQUIRE( feeHistory["oldestBlock"] == toJS( bn - blockCnt + 1 ) ); @@ -3108,7 +3108,7 @@ BOOST_AUTO_TEST_CASE( eip1559RpcMethods ) { for (Json::Value::ArrayIndex i = 0; i < blockCnt; ++i) { BOOST_REQUIRE( feeHistory["baseFeePerGas"][i].isString() ); std::string estimatedBaseFeePerGas = EIP1559TransactionsPatch::isEnabledWhen( - fixture.client->blockInfo( bn - i ).timestamp() ) ? toJS( fixture.client->gasBidPrice( bn - i ) ) : toJS( 0 ); + fixture.client->blockInfo( bn - i - 1 ).timestamp() ) ? toJS( fixture.client->gasBidPrice( bn - i ) ) : toJS( 0 ); BOOST_REQUIRE( feeHistory["baseFeePerGas"][i].asString() == estimatedBaseFeePerGas ); BOOST_REQUIRE_GT( feeHistory["gasUsedRatio"][i].asDouble(), 0 ); BOOST_REQUIRE_GT( 1, feeHistory["gasUsedRatio"][i].asDouble() ); From ac59ebb2b980a02e3a4ba7c4d410679a4d81b91e Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 24 Apr 2024 13:25:42 +0100 Subject: [PATCH 42/53] #1719 add effectiveGasPrice to receipt --- libethereum/ClientBase.cpp | 3 ++- libethereum/TransactionReceipt.h | 7 +++++-- libweb3jsonrpc/Eth.cpp | 4 ++-- libweb3jsonrpc/JsonHelper.cpp | 2 ++ test/unittests/libweb3jsonrpc/jsonrpc.cpp | 3 +++ 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index f8a51807e..f7cff02f5 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -450,7 +450,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, int( t.txType() ) ); + t.isInvalid() ? dev::Address( 0 ) : t.to(), gasUsed, contractAddress, int( t.txType() ), + t.gasPrice() ); } pair< h256, unsigned > ClientBase::transactionLocation( h256 const& _transactionHash ) const { diff --git a/libethereum/TransactionReceipt.h b/libethereum/TransactionReceipt.h index 66170ea4c..76cb0592f 100644 --- a/libethereum/TransactionReceipt.h +++ b/libethereum/TransactionReceipt.h @@ -98,7 +98,7 @@ class LocalisedTransactionReceipt : public TransactionReceipt { LocalisedTransactionReceipt( TransactionReceipt const& _t, h256 const& _hash, h256 const& _blockHash, BlockNumber _blockNumber, unsigned _transactionIndex, Address _from, Address _to, u256 const& _gasUsed, Address const& _contractAddress = Address(), - int _txType = 0 ) + int _txType = 0, u256 _effectiveGasPrice = 0 ) : TransactionReceipt( _t ), m_hash( _hash ), m_blockHash( _blockHash ), @@ -108,7 +108,8 @@ class LocalisedTransactionReceipt : public TransactionReceipt { m_to( _to ), m_gasUsed( _gasUsed ), m_contractAddress( _contractAddress ), - m_txType( _txType ) { + m_txType( _txType ), + m_effectiveGasPrice( _effectiveGasPrice ) { LogEntries entries = log(); for ( unsigned i = 0; i < entries.size(); i++ ) m_localisedLogs.push_back( LocalisedLogEntry( @@ -127,6 +128,7 @@ class LocalisedTransactionReceipt : public TransactionReceipt { Address const& contractAddress() const { return m_contractAddress; } LocalisedLogEntries const& localisedLogs() const { return m_localisedLogs; }; int txType() const { return m_txType; } + u256 effectiveGasPrice() const { return m_effectiveGasPrice; } private: h256 m_hash; @@ -138,6 +140,7 @@ class LocalisedTransactionReceipt : public TransactionReceipt { Address m_contractAddress; LocalisedLogEntries m_localisedLogs; int m_txType; + u256 m_effectiveGasPrice = 0; Counter< TransactionReceipt > c; diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index aa6937266..22e5aa0c4 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -541,7 +541,7 @@ Json::Value Eth::eth_getBlockByHash( string const& _blockHash, bool _includeTran if ( EIP1559TransactionsPatch::isEnabledWhen( client()->blockInfo( client()->numberFromHash( h ) - 1 ).timestamp() ) ) try { - baseFeePerGas = client()->gasBidPrice( client()->numberFromHash( h ) ); + baseFeePerGas = client()->gasBidPrice( client()->numberFromHash( h ) - 1 ); } catch ( std::invalid_argument& _e ) { cdebug << "Cannot get gas price for block " << h; cdebug << _e.what(); @@ -603,7 +603,7 @@ Json::Value Eth::eth_getBlockByNumber( string const& _blockNumber, bool _include u256 baseFeePerGas; if ( EIP1559TransactionsPatch::isEnabledWhen( client()->blockInfo( h - 1 ).timestamp() ) ) try { - baseFeePerGas = client()->gasBidPrice( h ); + baseFeePerGas = client()->gasBidPrice( h - 1 ); } catch ( std::invalid_argument& _e ) { cdebug << "Cannot get gas price for block " << h; cdebug << _e.what(); diff --git a/libweb3jsonrpc/JsonHelper.cpp b/libweb3jsonrpc/JsonHelper.cpp index f8a13d38c..b197be625 100644 --- a/libweb3jsonrpc/JsonHelper.cpp +++ b/libweb3jsonrpc/JsonHelper.cpp @@ -226,6 +226,7 @@ Json::Value toJson( dev::eth::LocalisedTransactionReceipt const& _t ) { res["revertReason"] = strRevertReason; res["type"] = toJS( _t.txType() ); + res["effectiveGasPrice"] = toJS( _t.effectiveGasPrice() ); return res; } @@ -331,6 +332,7 @@ rapidjson::Document toRapidJson( dev::eth::LocalisedTransactionReceipt const& _t } ADD_FIELD_TO_RAPIDJSON( res, "type", toJS( _t.txType() ), allocator ); + ADD_FIELD_TO_RAPIDJSON( res, "effectiveGasPrice", toJS( _t.effectiveGasPrice() ), allocator ); return res; } diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index 4f5053b52..7687e598e 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -2854,6 +2854,7 @@ BOOST_AUTO_TEST_CASE( eip2930Transactions ) { receipt = fixture.rpcClient->eth_getTransactionReceipt( txHash ); BOOST_REQUIRE( receipt["status"] == string( "0x1" ) ); BOOST_REQUIRE( receipt["type"] == "0x1" ); + BOOST_REQUIRE( receipt["effectiveGasPrice"] == "0x4a817c800" ); result = fixture.rpcClient->eth_getTransactionByHash( txHash ); BOOST_REQUIRE( result["hash"].asString() == txHash ); @@ -2964,6 +2965,7 @@ BOOST_AUTO_TEST_CASE( eip1559Transactions ) { receipt = fixture.rpcClient->eth_getTransactionReceipt( txHash ); BOOST_REQUIRE( receipt["status"] == string( "0x1" ) ); BOOST_REQUIRE( receipt["type"] == "0x0" ); + BOOST_REQUIRE( receipt["effectiveGasPrice"] == "0x4a817c800" ); // send 1 WEI from 0x5EdF1e852fdD1B0Bc47C0307EF755C76f4B9c251 to 0x7D36aF85A184E220A656525fcBb9A63B9ab3C12b // encoded type 2 txn @@ -2999,6 +3001,7 @@ BOOST_AUTO_TEST_CASE( eip1559Transactions ) { receipt = fixture.rpcClient->eth_getTransactionReceipt( txHash ); BOOST_REQUIRE( receipt["status"] == string( "0x1" ) ); BOOST_REQUIRE( receipt["type"] == "0x2" ); + BOOST_REQUIRE( receipt["effectiveGasPrice"] == "0x4a817c800" ); result = fixture.rpcClient->eth_getTransactionByHash( txHash ); BOOST_REQUIRE( result["hash"].asString() == txHash ); From 34780be44a2f8675f04d600910eda9fc71ac525a Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 24 Apr 2024 15:19:05 +0100 Subject: [PATCH 43/53] #1719 eth_call improvement --- libweb3jsonrpc/JsonHelper.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libweb3jsonrpc/JsonHelper.cpp b/libweb3jsonrpc/JsonHelper.cpp index b197be625..717d5286e 100644 --- a/libweb3jsonrpc/JsonHelper.cpp +++ b/libweb3jsonrpc/JsonHelper.cpp @@ -596,6 +596,10 @@ TransactionSkeleton rapidJsonToTransactionSkeleton( rapidjson::Value const& _jso if ( !_json["gasPrice"].IsString() ) throw jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ); ret.gasPrice = jsToU256( _json["gasPrice"].GetString() ); + } else if ( _json.HasMember( "maxFeePerGas" ) ) { + if ( !_json["maxFeePerGas"].IsString() ) + throw jsonrpc::JsonRpcException( jsonrpc::Errors::ERROR_RPC_INVALID_PARAMS ); + ret.gasPrice = jsToU256( _json["maxFeePerGas"].GetString() ); } if ( _json.HasMember( "code" ) ) { From 0d99d32619219709f6f9498952fc4a444991554d Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 24 Apr 2024 15:25:56 +0100 Subject: [PATCH 44/53] #1719 strict chainId check in streamRLP --- libethcore/TransactionBase.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libethcore/TransactionBase.cpp b/libethcore/TransactionBase.cpp index 7dfa8b738..9febca7a1 100644 --- a/libethcore/TransactionBase.cpp +++ b/libethcore/TransactionBase.cpp @@ -416,6 +416,8 @@ void TransactionBase::streamLegacyTransaction( void TransactionBase::streamType1Transaction( RLPStream& _s, IncludeSignature _sig ) const { _s.appendList( ( _sig ? 3 : 0 ) + 8 ); + if ( !m_chainId.has_value() ) + BOOST_THROW_EXCEPTION( InvalidTransactionFormat() ); _s << *m_chainId << m_nonce << m_gasPrice << m_gas; if ( m_type == MessageCall ) _s << m_receiveAddress; @@ -431,6 +433,8 @@ void TransactionBase::streamType1Transaction( RLPStream& _s, IncludeSignature _s void TransactionBase::streamType2Transaction( RLPStream& _s, IncludeSignature _sig ) const { _s.appendList( ( _sig ? 3 : 0 ) + 9 ); + if ( !m_chainId.has_value() ) + BOOST_THROW_EXCEPTION( InvalidTransactionFormat() ); _s << *m_chainId << m_nonce << m_maxPriorityFeePerGas << m_maxFeePerGas << m_gas; if ( m_type == MessageCall ) _s << m_receiveAddress; From 0fa32a3bcea4c167830ce98190443243e044ea41 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 24 Apr 2024 15:36:28 +0100 Subject: [PATCH 45/53] #1719 feeHistory improvements --- libweb3jsonrpc/Eth.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index 22e5aa0c4..4afcc8eba 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -48,6 +48,7 @@ using namespace dev::rpc; const uint64_t MAX_CALL_CACHE_ENTRIES = 1024; const uint64_t MAX_RECEIPT_CACHE_ENTRIES = 1024; +const u256 MAX_BLOCK_RANGE = 1024; #ifdef HISTORIC_STATE @@ -946,7 +947,7 @@ Json::Value Eth::eth_feeHistory( const std::string& _blockCount, const std::stri } } - auto blockCount = jsToU256( _blockCount ); + auto blockCount = std::min( jsToU256( _blockCount ), MAX_BLOCK_RANGE ); auto newestBlock = jsToBlockNumber( _newestBlock ); if ( newestBlock == dev::eth::LatestBlock ) newestBlock = client()->number(); @@ -954,7 +955,7 @@ Json::Value Eth::eth_feeHistory( const std::string& _blockCount, const std::stri auto result = Json::Value( Json::objectValue ); dev::u256 oldestBlock; if ( blockCount > newestBlock ) - oldestBlock = 0; + oldestBlock = 1; else oldestBlock = dev::u256( newestBlock ) - blockCount + 1; result["oldestBlock"] = toJS( oldestBlock ); From 4c2d7af879f9cf4f129997661ea44ca0773ec5ea Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 24 Apr 2024 15:44:51 +0100 Subject: [PATCH 46/53] #1719 fix tests --- test/unittests/libweb3jsonrpc/jsonrpc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unittests/libweb3jsonrpc/jsonrpc.cpp b/test/unittests/libweb3jsonrpc/jsonrpc.cpp index 7687e598e..950fff4ea 100644 --- a/test/unittests/libweb3jsonrpc/jsonrpc.cpp +++ b/test/unittests/libweb3jsonrpc/jsonrpc.cpp @@ -3111,7 +3111,7 @@ BOOST_AUTO_TEST_CASE( eip1559RpcMethods ) { for (Json::Value::ArrayIndex i = 0; i < blockCnt; ++i) { BOOST_REQUIRE( feeHistory["baseFeePerGas"][i].isString() ); std::string estimatedBaseFeePerGas = EIP1559TransactionsPatch::isEnabledWhen( - fixture.client->blockInfo( bn - i - 1 ).timestamp() ) ? toJS( fixture.client->gasBidPrice( bn - i ) ) : toJS( 0 ); + fixture.client->blockInfo( bn - i - 1 ).timestamp() ) ? toJS( fixture.client->gasBidPrice( bn - i - 1 ) ) : toJS( 0 ); BOOST_REQUIRE( feeHistory["baseFeePerGas"][i].asString() == estimatedBaseFeePerGas ); BOOST_REQUIRE_GT( feeHistory["gasUsedRatio"][i].asDouble(), 0 ); BOOST_REQUIRE_GT( 1, feeHistory["gasUsedRatio"][i].asDouble() ); From b6dee228176c5aa6dceb66419a346eea1a4f5f8d Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Wed, 24 Apr 2024 19:10:26 +0100 Subject: [PATCH 47/53] #1719 fix tests --- libethereum/ClientBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index f7cff02f5..aa57fbaa1 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -451,7 +451,7 @@ 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, int( t.txType() ), - t.gasPrice() ); + t.isInvalid() ? 0 : t.gasPrice() ); } pair< h256, unsigned > ClientBase::transactionLocation( h256 const& _transactionHash ) const { From 8e0eeff294be97bb0f235acc2626bbe0f82575f9 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Thu, 25 Apr 2024 11:09:32 +0100 Subject: [PATCH 48/53] #1719 fix historic node --- libweb3jsonrpc/Eth.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index 4afcc8eba..462e7eed4 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -756,7 +756,8 @@ LocalisedTransactionReceipt Eth::eth_getTransactionReceipt( string const& _trans size_t newIndex = m_gapCache->gappedIndexFromReal( rcp.blockNumber(), rcp.transactionIndex() ); rcp = LocalisedTransactionReceipt( rcp, rcp.hash(), rcp.blockHash(), rcp.blockNumber(), - newIndex, rcp.from(), rcp.to(), rcp.gasUsed(), rcp.contractAddress(), rcp.txType() ); + newIndex, rcp.from(), rcp.to(), rcp.gasUsed(), rcp.contractAddress(), rcp.txType(), + rcp.effectiveGasPrice() ); } #endif From 1615a5ec8c213a4cc1266c2475a4cc39dec0c86d Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Mon, 29 Apr 2024 15:24:55 +0100 Subject: [PATCH 49/53] #1719 fix txn proccessing --- libethcore/TransactionBase.cpp | 8 ++++---- libethereum/SkaleHost.cpp | 3 +-- libethereum/TransactionQueue.cpp | 5 +++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libethcore/TransactionBase.cpp b/libethcore/TransactionBase.cpp index 9febca7a1..130693226 100644 --- a/libethcore/TransactionBase.cpp +++ b/libethcore/TransactionBase.cpp @@ -208,14 +208,14 @@ void TransactionBase::fillFromBytesType1( if ( _checkSig >= CheckTransaction::Cheap && !m_vrs->isValid() ) BOOST_THROW_EXCEPTION( InvalidSignature() ); + m_txType = TransactionType::Type1; + if ( _checkSig == CheckTransaction::Everything ) m_sender = sender(); if ( rlp.itemCount() > 11 ) BOOST_THROW_EXCEPTION( InvalidTransactionFormat() << errinfo_comment( "too many fields in the transaction RLP" ) ); - - m_txType = TransactionType::Type1; } catch ( Exception& _e ) { _e << errinfo_name( "invalid transaction format: " + toString( rlp ) + " RLP: " + toHex( rlp.data() ) ); @@ -276,14 +276,14 @@ void TransactionBase::fillFromBytesType2( if ( _checkSig >= CheckTransaction::Cheap && !m_vrs->isValid() ) BOOST_THROW_EXCEPTION( InvalidSignature() ); + m_txType = TransactionType::Type2; + if ( _checkSig == CheckTransaction::Everything ) m_sender = sender(); if ( rlp.itemCount() > 12 ) BOOST_THROW_EXCEPTION( InvalidTransactionFormat() << errinfo_comment( "too many fields in the transaction RLP" ) ); - - m_txType = TransactionType::Type2; } catch ( Exception& _e ) { _e << errinfo_name( "invalid transaction format: " + toString( rlp ) + " RLP: " + toHex( rlp.data() ) ); diff --git a/libethereum/SkaleHost.cpp b/libethereum/SkaleHost.cpp index 0f525a21f..a830dae8a 100644 --- a/libethereum/SkaleHost.cpp +++ b/libethereum/SkaleHost.cpp @@ -332,9 +332,8 @@ h256 SkaleHost::receiveTransaction( std::string _rlp ) { return h256(); } - Transaction transaction( jsToBytes( _rlp, OnFailed::Throw ), CheckTransaction::None, + Transaction transaction( jsToBytes( _rlp, OnFailed::Throw ), CheckTransaction::None, false, EIP1559TransactionsPatch::isEnabledInWorkingBlock() ); - h256 sha = transaction.sha3(); // diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index e2ed6960d..dafacf8f6 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -528,8 +528,9 @@ void TransactionQueue::verifierBody() { } // block try { - Transaction t( work.transaction, CheckTransaction::Cheap ); // Signature will be - // checked later + Transaction t( work.transaction, CheckTransaction::Cheap, false, + EIP1559TransactionsPatch::isEnabledInWorkingBlock() ); // Signature will be + // checked later ImportResult ir = import( t ); m_onImport( ir, t.sha3(), work.nodeId ); } catch ( ... ) { From 18847bac479c4f953955b108f01557b2227050e3 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 30 Apr 2024 11:09:54 +0100 Subject: [PATCH 50/53] #1719 fix eth_getBlockByNumber call --- libweb3jsonrpc/Eth.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index 462e7eed4..586b93667 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -601,12 +601,14 @@ Json::Value Eth::eth_getBlockByNumber( string const& _blockNumber, bool _include if ( !client()->isKnown( h ) ) return Json::Value( Json::nullValue ); + BlockNumber bn = ( h == LatestBlock || h == PendingBlock ) ? client()->number() : h; + u256 baseFeePerGas; - if ( EIP1559TransactionsPatch::isEnabledWhen( client()->blockInfo( h - 1 ).timestamp() ) ) + if ( EIP1559TransactionsPatch::isEnabledWhen( client()->blockInfo( bn - 1 ).timestamp() ) ) try { - baseFeePerGas = client()->gasBidPrice( h - 1 ); + baseFeePerGas = client()->gasBidPrice( bn - 1 ); } catch ( std::invalid_argument& _e ) { - cdebug << "Cannot get gas price for block " << h; + cdebug << "Cannot get gas price for block " << bn; cdebug << _e.what(); // set default gasPrice // probably the price was rotated out as we are asking the price for the old block From bcc31af549c90c1e738c61a8cd009931ba1b3fce Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 30 Apr 2024 15:25:32 +0100 Subject: [PATCH 51/53] #1719 fix getTransaction --- libweb3jsonrpc/JsonHelper.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libweb3jsonrpc/JsonHelper.cpp b/libweb3jsonrpc/JsonHelper.cpp index 717d5286e..b2828a1c2 100644 --- a/libweb3jsonrpc/JsonHelper.cpp +++ b/libweb3jsonrpc/JsonHelper.cpp @@ -95,7 +95,8 @@ Json::Value toJson( dev::eth::Transaction const& _t, std::pair< h256, unsigned > res["to"] = _t.isCreation() ? Json::Value() : toJS( _t.receiveAddress() ); res["from"] = toJS( _t.safeSender() ); res["gas"] = toJS( _t.gas() ); - res["gasPrice"] = toJS( _t.gasPrice() ); + if ( _t.txType() != dev::eth::TransactionType::Type2 ) + res["gasPrice"] = toJS( _t.gasPrice() ); res["nonce"] = toJS( _t.nonce() ); res["value"] = toJS( _t.value() ); res["blockHash"] = toJS( _location.first ); @@ -121,7 +122,7 @@ Json::Value toJson( dev::eth::Transaction const& _t, std::pair< h256, unsigned > } if ( _t.txType() != dev::eth::TransactionType::Type1 ) { res["maxPriorityFeePerGas"] = toJS( _t.maxPriorityFeePerGas() ); - res["maxFeePerGas"] = toJS( _t.maxPriorityFeePerGas() ); + res["maxFeePerGas"] = toJS( _t.maxFeePerGas() ); } } } @@ -343,7 +344,8 @@ Json::Value toJson( dev::eth::Transaction const& _t ) { res["to"] = _t.isCreation() ? Json::Value() : toJS( _t.to() ); res["from"] = toJS( _t.from() ); res["gas"] = toJS( _t.gas() ); - res["gasPrice"] = toJS( _t.gasPrice() ); + if ( _t.txType() != dev::eth::TransactionType::Type2 ) + res["gasPrice"] = toJS( _t.gasPrice() ); res["value"] = toJS( _t.value() ); res["data"] = toJS( _t.data(), 32 ); res["nonce"] = toJS( _t.nonce() ); @@ -366,7 +368,7 @@ Json::Value toJson( dev::eth::Transaction const& _t ) { } if ( _t.txType() != dev::eth::TransactionType::Type1 ) { res["maxPriorityFeePerGas"] = toJS( _t.maxPriorityFeePerGas() ); - res["maxFeePerGas"] = toJS( _t.maxPriorityFeePerGas() ); + res["maxFeePerGas"] = toJS( _t.maxFeePerGas() ); } } } From a7590fb4ef681ad70639ad19ea7d640ab79b8705 Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 30 Apr 2024 18:05:43 +0100 Subject: [PATCH 52/53] #1719 format code --- libethcore/TransactionBase.h | 2 +- libethereum/TransactionQueue.cpp | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libethcore/TransactionBase.h b/libethcore/TransactionBase.h index 310ef741a..36a3cd192 100644 --- a/libethcore/TransactionBase.h +++ b/libethcore/TransactionBase.h @@ -313,7 +313,7 @@ class TransactionBase { /// Constructs a transaction from the given RLP and transaction type. void fillFromBytesByType( bytesConstRef _rlpData, CheckTransaction _checkSig, - bool _allowInvalid, TransactionType type ); + bool _allowInvalid, TransactionType _type ); void fillFromBytesLegacy( bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid ); void fillFromBytesType1( diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index dafacf8f6..16e726e76 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -133,7 +133,6 @@ ImportResult TransactionQueue::import( // if transaction found: if ( t != fs->second.end() ) { - // if( t == fs->second.begin() ){ UpgradeGuard ul( l ); --m_futureSize; m_futureSizeBytes -= t->second.transaction.toBytes().size(); @@ -143,7 +142,6 @@ ImportResult TransactionQueue::import( fs->second.erase( t->second.transaction.nonce() ); if ( fs->second.empty() ) m_future.erase( fs ); - // } } // if found } // if fs->second From 3181ea40dcf773f61e6ed06d662b2f0d5a4a037d Mon Sep 17 00:00:00 2001 From: Oleh Nikolaiev Date: Tue, 30 Apr 2024 18:39:29 +0100 Subject: [PATCH 53/53] #1719 small improvements --- libethcore/TransactionBase.cpp | 18 ++++++++++++------ libweb3jsonrpc/Eth.cpp | 5 ++++- test/tools/libtesteth/BlockChainHelper.cpp | 2 +- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/libethcore/TransactionBase.cpp b/libethcore/TransactionBase.cpp index 130693226..55dbeb154 100644 --- a/libethcore/TransactionBase.cpp +++ b/libethcore/TransactionBase.cpp @@ -36,11 +36,13 @@ using namespace std; using namespace dev; using namespace dev::eth; -std::vector< bytes > validateAccessListRLP( const RLP& data ) { - if ( !data.isList() ) +const size_t MAX_ACCESS_LIST_COUNT = 16; + +std::vector< bytes > validateAccessListRLP( const RLP& _data ) { + if ( !_data.isList() ) BOOST_THROW_EXCEPTION( InvalidTransactionFormat() << errinfo_comment( "transaction accessList RLP must be a list" ) ); - auto rlpList = data.toList(); + auto rlpList = _data.toList(); if ( rlpList.empty() ) { // empty accessList, ignore it return {}; @@ -66,6 +68,10 @@ std::vector< bytes > validateAccessListRLP( const RLP& data ) { "transaction storageKeys RLP must be a list of byte array" ) ); } + if ( rlpList.size() > MAX_ACCESS_LIST_COUNT ) + BOOST_THROW_EXCEPTION( InvalidTransactionFormat() + << errinfo_comment( "The number of access lists is too large." ) ); + std::vector< bytes > accessList( rlpList.size() ); for ( size_t i = 0; i < rlpList.size(); ++i ) { accessList[i] = rlpList.at( i ).data().toBytes(); @@ -298,9 +304,9 @@ void TransactionBase::fillFromBytesType2( } } -void TransactionBase::fillFromBytesByType( - bytesConstRef _rlpData, CheckTransaction _checkSig, bool _allowInvalid, TransactionType type ) { - switch ( type ) { +void TransactionBase::fillFromBytesByType( bytesConstRef _rlpData, CheckTransaction _checkSig, + bool _allowInvalid, TransactionType _type ) { + switch ( _type ) { case TransactionType::Legacy: fillFromBytesLegacy( _rlpData, _checkSig, _allowInvalid ); break; diff --git a/libweb3jsonrpc/Eth.cpp b/libweb3jsonrpc/Eth.cpp index 6849e525d..4c1b42fdf 100644 --- a/libweb3jsonrpc/Eth.cpp +++ b/libweb3jsonrpc/Eth.cpp @@ -956,7 +956,10 @@ Json::Value Eth::eth_feeHistory( const std::string& _blockCount, const std::stri } } - auto blockCount = std::min( jsToU256( _blockCount ), MAX_BLOCK_RANGE ); + auto blockCount = jsToU256( _blockCount ); + if ( blockCount > MAX_BLOCK_RANGE ) + throw std::runtime_error( "Max block range reached. Please try smaller blockCount." ); + auto newestBlock = jsToBlockNumber( _newestBlock ); if ( newestBlock == dev::eth::LatestBlock ) newestBlock = client()->number(); diff --git a/test/tools/libtesteth/BlockChainHelper.cpp b/test/tools/libtesteth/BlockChainHelper.cpp index f24e27b04..53b3ce334 100644 --- a/test/tools/libtesteth/BlockChainHelper.cpp +++ b/test/tools/libtesteth/BlockChainHelper.cpp @@ -122,7 +122,7 @@ void TestBlock::setState( State const& _state ) { void TestBlock::addTransaction( TestTransaction const& _tr ) { m_testTransactions.push_back( _tr ); if ( m_transactionQueue.import( _tr.transaction().toBytes() ) != ImportResult::Success ) - cnote << TestOutputHelper::get().testName() + " Test block failed importing transaction\n"; + cnote << TestOutputHelper::get().testName() + " Test block failed importing transaction"; recalcBlockHeaderBytes(); }