Skip to content

Commit

Permalink
Merge pull request #114 from eosnetworkfoundation/elmato/merge-fix-fo…
Browse files Browse the repository at this point in the history
…rk-switch-into-0.2

[0.1 -> 0.2] Fix fork switch A->B->A
  • Loading branch information
elmato authored Dec 19, 2023
2 parents a582afe + 997cfa1 commit dced0ac
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 1 deletion.
1 change: 0 additions & 1 deletion silkworm/node/stagedsync/execution_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ void ExecutionEngine::insert_blocks(const std::vector<std::shared_ptr<Block>>& b
bool ExecutionEngine::insert_block(const std::shared_ptr<Block> block) {
Hash header_hash{block->header.hash()};

if (block_cache_.get(header_hash)) return true; // ignore repeated blocks
block_cache_.put(header_hash, block);

if (block_progress_ < block->header.number) block_progress_ = block->header.number;
Expand Down
58 changes: 58 additions & 0 deletions silkworm/node/stagedsync/execution_engine_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,4 +365,62 @@ TEST_CASE("ExecutionEngine") {
}
}

TEST_CASE("ExecutionEngine test fork A->B->A") {
test::SetLogVerbosityGuard log_guard(log::Level::kNone);

asio::io_context io;
asio::executor_work_guard<decltype(io.get_executor())> work{io.get_executor()};

test::Context context;
context.add_genesis_data();
context.commit_txn();

PreverifiedHashes::current.clear(); // disable preverified hashes
Environment::set_stop_before_stage(db::stages::kSendersKey); // only headers, block hashes and bodies

db::RWAccess db_access{context.env()};
ExecutionEngine_ForTest exec_engine{io, context.node_settings(), db_access};
exec_engine.open();

auto& tx = exec_engine.main_chain_.tx(); // mdbx refuses to open a ROTxn when there is a RWTxn in the same thread

auto header0_hash = db::read_canonical_hash(tx, 0);
REQUIRE(header0_hash.has_value());

auto header0 = db::read_canonical_header(tx, 0);
REQUIRE(header0.has_value());

SECTION("fork A->B->A") {
auto block1 = generateSampleChildrenBlock(*header0);
auto block2 = generateSampleChildrenBlock(block1->header);
auto block3 = generateSampleChildrenBlock(block2->header);

// inserting & verifying the block
exec_engine.insert_block(block1);
exec_engine.insert_block(block2);
exec_engine.insert_block(block3);

auto verification = exec_engine.verify_chain(block3->header.hash()).get();
REQUIRE(holds_alternative<ValidChain>(verification));

// creating a fork and changing the head (trigger unwind)
auto block2b = generateSampleChildrenBlock(block1->header);
block2b->header.extra_data = string_view_to_byte_view("I'm different"); // to make it different from block2
exec_engine.insert_block(block2b);

verification = exec_engine.verify_chain(block2b->header.hash()).get();
REQUIRE(holds_alternative<ValidChain>(verification));

// insert block3 again and verify
exec_engine.insert_block(block3);
verification = exec_engine.verify_chain(block3->header.hash()).get();
REQUIRE(holds_alternative<ValidChain>(verification));

CHECK(exec_engine.get_header(block1->header.hash()).has_value()); // we do not remove old blocks
CHECK(exec_engine.get_header(block2->header.hash()).has_value()); // we do not remove old blocks
CHECK(exec_engine.get_header(block2b->header.hash()).has_value()); // we do not remove old blocks
CHECK(exec_engine.get_header(block3->header.hash()).has_value()); // we do not remove old blocks
}
}

} // namespace silkworm

0 comments on commit dced0ac

Please sign in to comment.