Skip to content
Draft
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
39 changes: 38 additions & 1 deletion category/execution/ethereum/db/test/test_db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ TYPED_TEST(
EXPECT_EQ(page.value()[compute_slot_offset(adjacent_key)], value2);
}

TEST_F(OnDiskTrieDbWithFileFixture, namespace_reads)
TEST_F(OnDiskTrieDbWithFileFixture, namespace_reads_and_merge)
{
constexpr uint64_t namespace_1{0x1111111111111111ULL};
constexpr uint64_t namespace_2{0x2222222222222222ULL};
Expand Down Expand Up @@ -697,10 +697,13 @@ TEST_F(OnDiskTrieDbWithFileFixture, namespace_reads)

State state_1{block_state, Incarnation{1, 1}, false, namespace_1};
State state_2{block_state, Incarnation{1, 2}, false, namespace_2};
State stale_state_1{block_state, Incarnation{1, 3}, false, namespace_1};
EXPECT_EQ(state_1.get_balance(ADDR_A), account_1.balance);
EXPECT_EQ(state_1.get_storage(ADDR_A, key1), value1);
EXPECT_EQ(state_2.get_balance(ADDR_A), account_2.balance);
EXPECT_EQ(state_2.get_storage(ADDR_A, key1), value2);
EXPECT_EQ(stale_state_1.get_balance(ADDR_A), account_1.balance);
EXPECT_EQ(stale_state_1.get_storage(ADDR_A, key1), value1);

mpt::RODb rodb{mpt::ReadOnlyOnDiskDbConfig{.dbname_paths = {this->dbname}}};
TrieRODb trie_ro{rodb};
Expand All @@ -713,6 +716,40 @@ TEST_F(OnDiskTrieDbWithFileFixture, namespace_reads)
EXPECT_EQ(
trie_ro.read_storage(ADDR_A, Incarnation{0, 0}, key1, namespace_2),
value2);

state_1.add_to_balance(ADDR_A, 10);
EXPECT_EQ(state_1.set_storage(ADDR_A, key1, value2), EVMC_STORAGE_MODIFIED);
EXPECT_TRUE(block_state.can_merge(state_1));
block_state.merge(state_1);
EXPECT_EQ(
block_state.read_account(ADDR_A, namespace_1)->balance,
account_1.balance + 10);
EXPECT_EQ(
block_state.read_storage(ADDR_A, Incarnation{0, 0}, key1, namespace_1),
value2);
EXPECT_EQ(block_state.read_account(ADDR_A, namespace_2), account_2);
EXPECT_EQ(
block_state.read_storage(ADDR_A, Incarnation{0, 0}, key1, namespace_2),
value2);
EXPECT_EQ(block_state.read_account(ADDR_A), std::nullopt);
EXPECT_FALSE(block_state.can_merge(stale_state_1));

state_2.add_to_balance(ADDR_A, 20);
EXPECT_EQ(state_2.set_storage(ADDR_A, key1, value1), EVMC_STORAGE_MODIFIED);
EXPECT_TRUE(block_state.can_merge(state_2));
block_state.merge(state_2);
EXPECT_EQ(
block_state.read_account(ADDR_A, namespace_2)->balance,
account_2.balance + 20);
EXPECT_EQ(
block_state.read_storage(ADDR_A, Incarnation{0, 0}, key1, namespace_2),
value1);
EXPECT_EQ(
block_state.read_account(ADDR_A, namespace_1)->balance,
account_1.balance + 10);
EXPECT_EQ(
block_state.read_storage(ADDR_A, Incarnation{0, 0}, key1, namespace_1),
value2);
}

TEST(DBTest, read_only)
Expand Down
34 changes: 29 additions & 5 deletions category/execution/ethereum/state2/block_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,26 @@ vm::SharedVarcode BlockState::read_code(bytes32_t const &code_hash)
bool BlockState::can_merge(State &state) const
{
MONAD_ASSERT(state_);
auto const &original = state.original();
for (auto &kv : original) {
auto const &ns = state.get_namespace();
StateDeltas const *deltas = nullptr;
if (ns.has_value()) {
NamespacedStateDeltas::const_accessor ns_it{};
Comment thread
zander-xyz marked this conversation as resolved.
MONAD_ASSERT(ns_state_.find(ns_it, *ns));
MONAD_ASSERT(ns_it->second);
deltas = ns_it->second.get();
}
else {
deltas = state_.get();
}

for (auto &kv : state.original()) {
Address const &address = kv.first;
OriginalAccountState const &account_state = kv.second;
auto const &account = account_state.account_;
auto const &storage = account_state.storage_;
MONAD_ASSERT(deltas);
StateDeltas::const_accessor it{};
MONAD_ASSERT(state_->find(it, address));
MONAD_ASSERT(deltas->find(it, address));
if (account != it->second.account.second) {
// RELAXED MERGE
// try to fix original and current in `state` to match the block
Expand Down Expand Up @@ -233,13 +245,25 @@ void BlockState::merge(State const &state)
code_.emplace(code_hash, it->second->intercode()); // TODO try_emplace
}

MONAD_ASSERT(state_);
auto const &ns = state.get_namespace();
StateDeltas *deltas = nullptr;
if (ns.has_value()) {
NamespacedStateDeltas::accessor ns_it{};
MONAD_ASSERT(ns_state_.find(ns_it, *ns));
MONAD_ASSERT(ns_it->second);
deltas = ns_it->second.get();
Comment thread
zander-xyz marked this conversation as resolved.
}
else {
MONAD_ASSERT(state_);
deltas = state_.get();
}

for (auto const &[address, stack] : current) {
auto const &account_state = stack.recent();
auto const &account = account_state.account_;
auto const &storage = account_state.storage_;
StateDeltas::accessor it{};
MONAD_ASSERT(state_->find(it, address));
MONAD_ASSERT(deltas->find(it, address));
it->second.account.second = account;
if (account.has_value()) {
for (auto const &[key, value] : storage) {
Expand Down
5 changes: 5 additions & 0 deletions category/execution/ethereum/state3/state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ class State
State &operator=(State &&) = delete;
State &operator=(State const &) = delete;

std::optional<uint64_t> const &get_namespace() const
{
return namespace_;
}

Map<Address, OriginalAccountState> const &original() const;

Map<Address, VersionStack<AccountState>> const &current() const;
Expand Down
Loading