LCOV - differential code coverage report
Current view: top level - test/state - state.hpp (source / functions) Coverage Total Hit UBC CBC
Current: DIFF_COVERAGE Lines: 71.4 % 7 5 2 5
Current Date: 2024-03-20 16:29:22 Functions: 80.0 % 5 4 1 4
Baseline: coverage_BASE.lcov
Baseline Date: 2024-03-20 14:19:08

           TLA  Line data    Source code
       1                 : // evmone: Fast Ethereum Virtual Machine implementation
       2                 : // Copyright 2022 The evmone Authors.
       3                 : // SPDX-License-Identifier: Apache-2.0
       4                 : 
       5                 : #pragma once
       6                 : 
       7                 : #include "account.hpp"
       8                 : #include "bloom_filter.hpp"
       9                 : #include "hash_utils.hpp"
      10                 : #include <cassert>
      11                 : #include <optional>
      12                 : #include <variant>
      13                 : #include <vector>
      14                 : 
      15                 : namespace evmone::state
      16                 : {
      17                 : /// The Ethereum State: the collection of accounts mapped by their addresses.
      18                 : ///
      19                 : /// TODO: This class is copyable for testing. Consider making it non-copyable.
      20                 : class State
      21                 : {
      22                 :     struct JournalBase
      23                 :     {
      24                 :         address addr;
      25                 :     };
      26                 : 
      27                 :     struct JournalBalanceChange : JournalBase
      28                 :     {
      29                 :         intx::uint256 prev_balance;
      30                 :     };
      31                 : 
      32                 :     struct JournalTouched : JournalBase
      33                 :     {};
      34                 : 
      35                 :     struct JournalStorageChange : JournalBase
      36                 :     {
      37                 :         bytes32 key;
      38                 :         bytes32 prev_value;
      39                 :         evmc_access_status prev_access_status;
      40                 :     };
      41                 : 
      42                 :     struct JournalTransientStorageChange : JournalBase
      43                 :     {
      44                 :         bytes32 key;
      45                 :         bytes32 prev_value;
      46                 :     };
      47                 : 
      48                 :     struct JournalNonceBump : JournalBase
      49                 :     {};
      50                 : 
      51                 :     struct JournalCreate : JournalBase
      52                 :     {
      53                 :         bool existed;
      54                 :     };
      55                 : 
      56                 :     struct JournalDestruct : JournalBase
      57                 :     {};
      58                 : 
      59                 :     struct JournalAccessAccount : JournalBase
      60                 :     {};
      61                 : 
      62                 :     using JournalEntry =
      63                 :         std::variant<JournalBalanceChange, JournalTouched, JournalStorageChange, JournalNonceBump,
      64                 :             JournalCreate, JournalTransientStorageChange, JournalDestruct, JournalAccessAccount>;
      65                 : 
      66                 :     std::unordered_map<address, Account> m_accounts;
      67                 : 
      68                 :     /// The state journal: the list of changes made in the state
      69                 :     /// with information how to revert them.
      70                 :     std::vector<JournalEntry> m_journal;
      71                 : 
      72                 : public:
      73                 :     /// Inserts the new account at the address.
      74                 :     /// There must not exist any account under this address before.
      75                 :     Account& insert(const address& addr, Account account = {});
      76                 : 
      77                 :     /// Returns the pointer to the account at the address if the account exists. Null otherwise.
      78                 :     Account* find(const address& addr) noexcept;
      79                 : 
      80                 :     /// Gets the account at the address (the account must exist).
      81                 :     Account& get(const address& addr) noexcept;
      82                 : 
      83                 :     /// Gets an existing account or inserts new account.
      84                 :     Account& get_or_insert(const address& addr, Account account = {});
      85                 : 
      86 CBC         318 :     [[nodiscard]] auto& get_accounts() noexcept { return m_accounts; }
      87                 : 
      88              53 :     [[nodiscard]] const auto& get_accounts() const noexcept { return m_accounts; }
      89                 : 
      90                 :     /// Returns the state journal checkpoint. It can be later used to in rollback()
      91                 :     /// to revert changes newer than the checkpoint.
      92             105 :     [[nodiscard]] size_t checkpoint() const noexcept { return m_journal.size(); }
      93                 : 
      94                 :     /// Reverts state changes made after the checkpoint.
      95                 :     void rollback(size_t checkpoint);
      96                 : 
      97                 :     /// Methods performing changes to the state which can be reverted by rollback().
      98                 :     /// @{
      99                 : 
     100                 :     /// Touches (as in EIP-161) an existing account or inserts new erasable account.
     101                 :     Account& touch(const address& addr);
     102                 : 
     103                 :     void journal_balance_change(const address& addr, const intx::uint256& prev_balance);
     104                 : 
     105                 :     void journal_storage_change(const address& addr, const bytes32& key, const StorageValue& value);
     106                 : 
     107                 :     void journal_transient_storage_change(
     108                 :         const address& addr, const bytes32& key, const bytes32& value);
     109                 : 
     110                 :     void journal_bump_nonce(const address& addr);
     111                 : 
     112                 :     void journal_create(const address& addr, bool existed);
     113                 : 
     114                 :     void journal_destruct(const address& addr);
     115                 : 
     116                 :     void journal_access_account(const address& addr);
     117                 : 
     118                 :     /// @}
     119                 : };
     120                 : 
     121                 : struct Ommer
     122                 : {
     123                 :     address beneficiary;  ///< Ommer block beneficiary address.
     124                 :     uint32_t delta = 0;   ///< Difference between current and ommer block number.
     125                 : };
     126                 : 
     127                 : struct Withdrawal
     128                 : {
     129                 :     uint64_t index = 0;
     130                 :     uint64_t validator_index = 0;
     131                 :     address recipient;
     132                 :     uint64_t amount_in_gwei = 0;  ///< The amount is denominated in gwei.
     133                 : 
     134                 :     /// Returns withdrawal amount in wei.
     135 UBC           0 :     [[nodiscard]] intx::uint256 get_amount() const noexcept
     136                 :     {
     137               0 :         return intx::uint256{amount_in_gwei} * 1'000'000'000;
     138                 :     }
     139                 : };
     140                 : 
     141                 : struct BlockInfo
     142                 : {
     143                 :     /// Max amount of blob gas allowed in block. It's constant now but can be dynamic in the future.
     144                 :     static constexpr int64_t MAX_BLOB_GAS_PER_BLOCK = 786432;
     145                 : 
     146                 :     int64_t number = 0;
     147                 :     int64_t timestamp = 0;
     148                 :     int64_t parent_timestamp = 0;
     149                 :     int64_t gas_limit = 0;
     150                 :     address coinbase;
     151                 :     int64_t difficulty = 0;
     152                 :     int64_t parent_difficulty = 0;
     153                 :     hash256 parent_ommers_hash;
     154                 :     bytes32 prev_randao;
     155                 :     hash256 parent_beacon_block_root;
     156                 :     uint64_t base_fee = 0;
     157                 : 
     158                 :     /// The "excess blob gas" parameter from EIP-4844
     159                 :     /// for computing the blob gas price in the current block.
     160                 :     uint64_t excess_blob_gas = 0;
     161                 : 
     162                 :     /// The blob gas price parameter from EIP-4844.
     163                 :     /// This values is not stored in block headers directly but computed from excess_blob_gas.
     164                 :     intx::uint256 blob_base_fee = 0;
     165                 : 
     166                 :     std::vector<Ommer> ommers;
     167                 :     std::vector<Withdrawal> withdrawals;
     168                 :     std::unordered_map<int64_t, hash256> known_block_hashes;
     169                 : };
     170                 : 
     171                 : using AccessList = std::vector<std::pair<address, std::vector<bytes32>>>;
     172                 : 
     173                 : struct Transaction
     174                 : {
     175                 :     /// The type of the transaction.
     176                 :     ///
     177                 :     /// The format is defined by EIP-2718: Typed Transaction Envelope.
     178                 :     /// https://eips.ethereum.org/EIPS/eip-2718.
     179                 :     enum class Type : uint8_t
     180                 :     {
     181                 :         /// The legacy RLP-encoded transaction without leading "type" byte.
     182                 :         legacy = 0,
     183                 : 
     184                 :         /// The typed transaction with optional account/storage access list.
     185                 :         /// Introduced by EIP-2930 https://eips.ethereum.org/EIPS/eip-2930.
     186                 :         access_list = 1,
     187                 : 
     188                 :         /// The typed transaction with priority gas price.
     189                 :         /// Introduced by EIP-1559 https://eips.ethereum.org/EIPS/eip-1559.
     190                 :         eip1559 = 2,
     191                 : 
     192                 :         /// The typed blob transaction (with array of blob hashes).
     193                 :         /// Introduced by EIP-4844 https://eips.ethereum.org/EIPS/eip-4844.
     194                 :         blob = 3,
     195                 :     };
     196                 : 
     197                 :     /// Returns amount of blob gas used by this transaction
     198 CBC          53 :     [[nodiscard]] int64_t blob_gas_used() const
     199                 :     {
     200                 :         static constexpr auto GAS_PER_BLOB = 0x20000;
     201              53 :         return GAS_PER_BLOB * static_cast<int64_t>(blob_hashes.size());
     202                 :     }
     203                 : 
     204                 :     Type type = Type::legacy;
     205                 :     bytes data;
     206                 :     int64_t gas_limit;
     207                 :     intx::uint256 max_gas_price;
     208                 :     intx::uint256 max_priority_gas_price;
     209                 :     intx::uint256 max_blob_gas_price;
     210                 :     address sender;
     211                 :     std::optional<address> to;
     212                 :     intx::uint256 value;
     213                 :     AccessList access_list;
     214                 :     std::vector<bytes32> blob_hashes;
     215                 :     uint64_t chain_id = 0;
     216                 :     uint64_t nonce = 0;
     217                 :     intx::uint256 r;
     218                 :     intx::uint256 s;
     219                 :     uint8_t v = 0;
     220                 : };
     221                 : 
     222                 : struct Log
     223                 : {
     224                 :     address addr;
     225                 :     bytes data;
     226                 :     std::vector<hash256> topics;
     227                 : };
     228                 : 
     229                 : /// Transaction Receipt
     230                 : ///
     231                 : /// This struct is used in two contexts:
     232                 : /// 1. As the formally specified, RLP-encode transaction receipt included in the Ethereum blocks.
     233                 : /// 2. As the internal representation of the transaction execution result.
     234                 : /// These both roles share most, but not all the information. There are some fields that cannot be
     235                 : /// assigned in the single transaction execution context. There are also fields that are not a part
     236                 : /// of the RLP-encoded transaction receipts.
     237                 : /// TODO: Consider splitting the struct into two based on the duality explained above.
     238                 : struct TransactionReceipt
     239                 : {
     240                 :     Transaction::Type type = Transaction::Type::legacy;
     241                 :     evmc_status_code status = EVMC_INTERNAL_ERROR;
     242                 : 
     243                 :     /// Amount of gas used by this transaction.
     244                 :     int64_t gas_used = 0;
     245                 : 
     246                 :     /// Amount of gas used by this and previous transactions in the block.
     247                 :     int64_t cumulative_gas_used = 0;
     248                 :     std::vector<Log> logs;
     249                 :     BloomFilter logs_bloom_filter;
     250                 : 
     251                 :     /// Root hash of the state after this transaction. Used only in old pre-Byzantium transactions.
     252                 :     std::optional<bytes32> post_state;
     253                 : };
     254                 : 
     255                 : /// Computes the current blob gas price based on the excess blob gas.
     256                 : intx::uint256 compute_blob_gas_price(uint64_t excess_blob_gas) noexcept;
     257                 : 
     258                 : /// Finalize state after applying a "block" of transactions.
     259                 : ///
     260                 : /// Applies block reward to coinbase, withdrawals (post Shanghai) and deletes empty touched accounts
     261                 : /// (post Spurious Dragon).
     262                 : void finalize(State& state, evmc_revision rev, const address& coinbase,
     263                 :     std::optional<uint64_t> block_reward, std::span<const Ommer> ommers,
     264                 :     std::span<const Withdrawal> withdrawals);
     265                 : 
     266                 : [[nodiscard]] std::variant<TransactionReceipt, std::error_code> transition(State& state,
     267                 :     const BlockInfo& block, const Transaction& tx, evmc_revision rev, evmc::VM& vm,
     268                 :     int64_t block_gas_left, int64_t blob_gas_left);
     269                 : 
     270                 : std::variant<int64_t, std::error_code> validate_transaction(const Account& sender_acc,
     271                 :     const BlockInfo& block, const Transaction& tx, evmc_revision rev, int64_t block_gas_left,
     272                 :     int64_t blob_gas_left) noexcept;
     273                 : 
     274                 : /// Performs the system call.
     275                 : ///
     276                 : /// Executes code at pre-defined accounts from the system sender (0xff...fe).
     277                 : /// The sender's nonce is not increased.
     278                 : void system_call(State& state, const BlockInfo& block, evmc_revision rev, evmc::VM& vm);
     279                 : 
     280                 : /// Defines how to RLP-encode a Transaction.
     281                 : [[nodiscard]] bytes rlp_encode(const Transaction& tx);
     282                 : 
     283                 : /// Defines how to RLP-encode a TransactionReceipt.
     284                 : [[nodiscard]] bytes rlp_encode(const TransactionReceipt& receipt);
     285                 : 
     286                 : /// Defines how to RLP-encode a Log.
     287                 : [[nodiscard]] bytes rlp_encode(const Log& log);
     288                 : 
     289                 : /// Defines how to RLP-encode a Withdrawal.
     290                 : [[nodiscard]] bytes rlp_encode(const Withdrawal& withdrawal);
     291                 : 
     292                 : }  // namespace evmone::state
        

Generated by: LCOV version 2.0-1