Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a table in db to hold runtime state info. #118

Merged
merged 1 commit into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions silkworm/node/db/access_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<ByteView> 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<uint64_t> 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<const unsigned char*>(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
12 changes: 12 additions & 0 deletions silkworm/node/db/access_layer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<ByteView> 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<uint64_t> 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);
Expand Down
49 changes: 49 additions & 0 deletions silkworm/node/db/access_layer_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions silkworm/node/db/tables.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions silkworm/node/db/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions silkworm/node/db/util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<evmc::address, Bytes>;

Expand All @@ -73,6 +77,9 @@ using StorageChanges = absl::btree_map<evmc::address, absl::btree_map<uint64_t,
// address can be either plain account address (20 bytes) or hash thereof (32 bytes)
Bytes storage_prefix(ByteView address, uint64_t incarnation);

// Encode RuntimeState
Bytes block_key(RuntimeState runtime_state);

// Erigon EncodeBlockNumber
Bytes block_key(BlockNum block_number);

Expand Down