From 2a17dceaa80b1633f936678ff5fb245b4908d34b Mon Sep 17 00:00:00 2001 From: yarkin Date: Thu, 11 Jan 2024 17:45:33 +0800 Subject: [PATCH] Add a table in db to hold runtime state info. --- silkworm/node/db/access_layer.cpp | 33 +++++++++++++++++ silkworm/node/db/access_layer.hpp | 12 +++++++ silkworm/node/db/access_layer_test.cpp | 49 ++++++++++++++++++++++++++ silkworm/node/db/tables.hpp | 4 +++ silkworm/node/db/util.cpp | 6 ++++ silkworm/node/db/util.hpp | 7 ++++ 6 files changed, 111 insertions(+) diff --git a/silkworm/node/db/access_layer.cpp b/silkworm/node/db/access_layer.cpp index 0eebe6561..1d616a5a8 100644 --- a/silkworm/node/db/access_layer.cpp +++ b/silkworm/node/db/access_layer.cpp @@ -1184,4 +1184,37 @@ bool DataModel::read_rlp_transactions(BlockNum height, const evmc::bytes32& hash return read_rlp_transactions_from_snapshot(height, transactions); } +std::optional read_runtime_states_bytes(ROTxn& txn, RuntimeState runtime_state) { + auto cursor = txn.ro_cursor(table::kRuntimeStates); + auto key{db::block_key(runtime_state)}; + auto data{cursor->find(to_slice(key), /*throw_notfound=*/false)}; + if (!data) { + return std::nullopt; + } + return from_slice(data.value); +} + +void write_runtime_states_bytes(RWTxn& txn, const Bytes value, RuntimeState runtime_state) { + auto cursor = txn.rw_cursor(table::kRuntimeStates); + auto key{db::block_key(runtime_state)}; + cursor->upsert(to_slice(key), db::to_slice(value)); +} + +std::optional read_runtime_states_u64(ROTxn& txn, RuntimeState runtime_state) { + auto cursor = txn.ro_cursor(table::kRuntimeStates); + // block_key support uint64_t via support for BlockNum + auto key{db::block_key(runtime_state)}; + auto data{cursor->find(to_slice(key), /*throw_notfound=*/false)}; + if (!data) { + return std::nullopt; + } + auto num = endian::load_big_u64(static_cast(data.value.data())); + return num; +} + +void write_runtime_states_u64(RWTxn& txn, uint64_t num, RuntimeState runtime_state) { + Bytes value{db::block_key(num)}; + write_runtime_states_bytes(txn, value, runtime_state); +} + } // namespace silkworm::db diff --git a/silkworm/node/db/access_layer.hpp b/silkworm/node/db/access_layer.hpp index 431ff08da..8d0131ee7 100644 --- a/silkworm/node/db/access_layer.hpp +++ b/silkworm/node/db/access_layer.hpp @@ -237,6 +237,18 @@ void write_last_safe_block(RWTxn& txn, const evmc::bytes32& hash); //! \brief Write the last finalized block as stated by the last FCU void write_last_finalized_block(RWTxn& txn, const evmc::bytes32& hash); +//! \brief read runtime states by index +std::optional read_runtime_states_bytes(ROTxn& txn, RuntimeState runtime_state); + +//! \brief Write runtime states by index +void write_runtime_states_bytes(RWTxn& txn, const Bytes value, RuntimeState runtime_state); + +//! \brief Read runtime states by index as uint64_t +std::optional read_runtime_states_u64(ROTxn& txn, RuntimeState runtime_state); + +//! \brief Write uint64_t as runtime states by index +void write_runtime_states_u64(RWTxn& txn, uint64_t num, RuntimeState runtime_state); + class DataModel { public: static void set_snapshot_repository(snapshot::SnapshotRepository* repository); diff --git a/silkworm/node/db/access_layer_test.cpp b/silkworm/node/db/access_layer_test.cpp index 1f114bb8f..0fa09055b 100644 --- a/silkworm/node/db/access_layer_test.cpp +++ b/silkworm/node/db/access_layer_test.cpp @@ -862,4 +862,53 @@ TEST_CASE("read rlp encoded transactions") { } } +TEST_CASE("RuntimeStates_u64") { + test::Context context; + auto& txn{context.rw_txn()}; + + RuntimeState index = kLibProcessed; + uint64_t value1{11111}; + uint64_t value2{22222}; + + CHECK(read_runtime_states_u64(txn, kLibProcessed) == std::nullopt); + + write_runtime_states_u64(txn, value1, index ); + CHECK(read_runtime_states_u64(txn, index) == value1); + + write_runtime_states_u64(txn, value1, RuntimeState(1) ); + CHECK(read_runtime_states_u64(txn, RuntimeState(1)) == value1); + + + write_runtime_states_u64(txn, value2, index ); + CHECK(read_runtime_states_u64(txn, index) == value2); + + CHECK(read_runtime_states_u64(txn, RuntimeState(1)) == value1); + + Bytes bvalue1{*from_hex("11111")}; + Bytes bvalue2{*from_hex("22222")}; +} + +TEST_CASE("RuntimeStates_bytes") { + test::Context context; + auto& txn{context.rw_txn()}; + + RuntimeState index = kLibProcessed; + Bytes value1{*from_hex("11111")}; + Bytes value2{*from_hex("22222")}; + + CHECK(read_runtime_states_bytes(txn, kLibProcessed) == std::nullopt); + + write_runtime_states_bytes(txn, value1, index ); + CHECK(read_runtime_states_bytes(txn, index) == value1); + + write_runtime_states_bytes(txn, value1, RuntimeState(1) ); + CHECK(read_runtime_states_bytes(txn, RuntimeState(1)) == value1); + + + write_runtime_states_bytes(txn, value2, index ); + CHECK(read_runtime_states_bytes(txn, index) == value2); + + CHECK(read_runtime_states_bytes(txn, RuntimeState(1)) == value1); +} + } // namespace silkworm::db diff --git a/silkworm/node/db/tables.hpp b/silkworm/node/db/tables.hpp index 3c2301694..b39afbd27 100644 --- a/silkworm/node/db/tables.hpp +++ b/silkworm/node/db/tables.hpp @@ -374,6 +374,9 @@ inline constexpr db::MapConfig kIssuance{kIssuanceName}; inline constexpr const char* kCumulativeGasIndexName{"CumulativeGasIndex"}; inline constexpr db::MapConfig kCumulativeGasIndex{kCumulativeGasIndexName}; +inline constexpr const char* kRuntimeStatesName{"RuntimeStates"}; +inline constexpr db::MapConfig kRuntimeStates{kRuntimeStatesName}; + inline constexpr db::MapConfig kChainDataTables[]{ kAccountChangeSet, kAccountHistory, @@ -418,6 +421,7 @@ inline constexpr db::MapConfig kChainDataTables[]{ kTrieOfAccounts, kTrieOfStorage, kTxLookup, + kRuntimeStates, }; //! \brief Ensures all defined tables are present in db with consistent flags. Should a table not exist it gets created diff --git a/silkworm/node/db/util.cpp b/silkworm/node/db/util.cpp index 634856008..2758728a7 100644 --- a/silkworm/node/db/util.cpp +++ b/silkworm/node/db/util.cpp @@ -35,6 +35,12 @@ Bytes storage_prefix(ByteView address, uint64_t incarnation) { return res; } +Bytes block_key(RuntimeState runtime_state) { + Bytes key(sizeof(runtime_state), '\0'); + endian::store_big_u64(&key[0], runtime_state); + return key; +} + Bytes block_key(BlockNum block_number) { Bytes key(sizeof(BlockNum), '\0'); endian::store_big_u64(&key[0], block_number); diff --git a/silkworm/node/db/util.hpp b/silkworm/node/db/util.hpp index a1f980176..ff63210d4 100644 --- a/silkworm/node/db/util.hpp +++ b/silkworm/node/db/util.hpp @@ -63,6 +63,10 @@ static_assert(kLocationLength == sizeof(evmc::bytes32)); inline constexpr size_t kPlainStoragePrefixLength{kAddressLength + kIncarnationLength}; inline constexpr size_t kHashedStoragePrefixLength{kHashLength + kIncarnationLength}; +enum RuntimeState: uint64_t { + kLibProcessed, // Last irreversible block processed. +}; + // address -> storage-encoded initial value using AccountChanges = absl::btree_map; @@ -73,6 +77,9 @@ using StorageChanges = absl::btree_map