Skip to content

Commit 9787672

Browse files
authored
rpcdaemon: move read_chain_config to chain storage (#2104)
rpcdaemon: remove unused read_chain_id
1 parent 68782d1 commit 9787672

14 files changed

+173
-194
lines changed

silkworm/rpc/commands/erigon_api.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <silkworm/core/common/util.hpp>
2626
#include <silkworm/core/protocol/ethash_rule_set.hpp>
2727
#include <silkworm/core/types/evmc_bytes32.hpp>
28+
#include <silkworm/infra/common/ensure.hpp>
2829
#include <silkworm/infra/common/log.hpp>
2930
#include <silkworm/rpc/common/binary_search.hpp>
3031
#include <silkworm/rpc/common/util.hpp>
@@ -444,10 +445,14 @@ Task<void> ErigonRpcApi::handle_erigon_forks(const nlohmann::json& request, nloh
444445
auto tx = co_await database_->begin();
445446

446447
try {
447-
const auto chain_config{co_await core::rawdb::read_chain_config(*tx)};
448-
SILK_DEBUG << "chain config: " << chain_config;
448+
const auto chain_storage = tx->create_storage();
449449

450-
Forks forks{chain_config};
450+
const auto chain_config{co_await chain_storage->read_chain_config()};
451+
if (!chain_config) {
452+
throw std::runtime_error("Chain config missing");
453+
}
454+
SILK_DEBUG << "chain config: " << *chain_config;
455+
Forks forks{*chain_config};
451456

452457
reply = make_json_content(request, forks);
453458
} catch (const std::exception& e) {
@@ -479,11 +484,12 @@ Task<void> ErigonRpcApi::handle_erigon_watch_the_burn(const nlohmann::json& requ
479484
try {
480485
const auto chain_storage = tx->create_storage();
481486

482-
const auto chain_config{co_await core::rawdb::read_chain_config(*tx)};
483-
SILK_DEBUG << "chain config: " << chain_config;
487+
const auto chain_config{co_await chain_storage->read_chain_config()};
488+
ensure(chain_config.has_value(), "cannot read chain config");
489+
SILK_DEBUG << "chain config: " << *chain_config;
484490

485491
Issuance issuance{}; // default is empty: no PoW => no issuance
486-
if (chain_config.config.count("ethash") != 0) {
492+
if (std::holds_alternative<protocol::EthashConfig>(chain_config->rule_set_config)) {
487493
const auto block_number = co_await core::get_block_number(block_id, *tx);
488494
const auto block_with_hash{co_await core::read_block_by_number(*block_cache_, *chain_storage, block_number)};
489495
if (!block_with_hash) {
@@ -493,11 +499,7 @@ Task<void> ErigonRpcApi::handle_erigon_watch_the_burn(const nlohmann::json& requ
493499
co_await tx->close(); // RAII not (yet) available with coroutines
494500
co_return;
495501
}
496-
const auto cc{silkworm::ChainConfig::from_json(chain_config.config)};
497-
if (!cc) {
498-
throw std::runtime_error("Invalid chain config");
499-
}
500-
const auto rule_set_factory = protocol::rule_set_factory(*cc);
502+
const auto rule_set_factory = protocol::rule_set_factory(*chain_config);
501503
const auto block_reward{rule_set_factory->compute_reward(block_with_hash->block)};
502504
intx::uint256 total_ommer_reward = 0;
503505
for (const auto ommer_reward : block_reward.ommers) {

silkworm/rpc/core/rawdb/chain.cpp

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -45,28 +45,6 @@ Task<uint64_t> read_header_number(ethdb::Transaction& tx, const evmc::bytes32& b
4545
co_return endian::load_big_u64(value.data());
4646
}
4747

48-
Task<ChainConfig> read_chain_config(ethdb::Transaction& tx) {
49-
const auto genesis_block_hash{co_await read_canonical_block_hash(tx, kEarliestBlockNumber)};
50-
SILK_DEBUG << "rawdb::read_chain_config genesis_block_hash: " << silkworm::to_hex(genesis_block_hash);
51-
const silkworm::ByteView genesis_block_hash_bytes{genesis_block_hash.bytes, silkworm::kHashLength};
52-
const auto data{co_await tx.get_one(db::table::kConfigName, genesis_block_hash_bytes)};
53-
if (data.empty()) {
54-
throw std::invalid_argument{"empty chain config data in read_chain_config"};
55-
}
56-
SILK_DEBUG << "rawdb::read_chain_config chain config data: " << data.c_str();
57-
const auto json_config = nlohmann::json::parse(data.c_str());
58-
SILK_TRACE << "rawdb::read_chain_config chain config JSON: " << json_config.dump();
59-
co_return ChainConfig{genesis_block_hash, json_config};
60-
}
61-
62-
Task<uint64_t> read_chain_id(ethdb::Transaction& tx) {
63-
const auto chain_info = co_await read_chain_config(tx);
64-
if (chain_info.config.count("chainId") == 0) {
65-
throw std::runtime_error{"missing chainId in chain config"};
66-
}
67-
co_return chain_info.config["chainId"].get<uint64_t>();
68-
}
69-
7048
Task<evmc::bytes32> read_canonical_block_hash(ethdb::Transaction& tx, uint64_t block_number) {
7149
const auto block_key = silkworm::db::block_key(block_number);
7250
SILK_TRACE << "rawdb::read_canonical_block_hash block_key: " << silkworm::to_hex(block_key);

silkworm/rpc/core/rawdb/chain.hpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,6 @@ using Transactions = std::vector<silkworm::Transaction>;
3535

3636
Task<uint64_t> read_header_number(ethdb::Transaction& tx, const evmc::bytes32& block_hash);
3737

38-
Task<ChainConfig> read_chain_config(ethdb::Transaction& tx);
39-
40-
Task<uint64_t> read_chain_id(ethdb::Transaction& tx);
41-
4238
Task<evmc::bytes32> read_canonical_block_hash(ethdb::Transaction& tx, BlockNum block_number);
4339

4440
Task<intx::uint256> read_total_difficulty(ethdb::Transaction& tx, const evmc::bytes32& block_hash, BlockNum block_number);

silkworm/rpc/core/rawdb/chain_test.cpp

Lines changed: 0 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
#include <catch2/catch.hpp>
2424
#include <evmc/evmc.h>
2525
#include <gmock/gmock.h>
26-
#include <nlohmann/json.hpp>
2726

2827
#include <silkworm/core/common/empty_hashes.hpp>
2928
#include <silkworm/core/common/util.hpp>
@@ -60,30 +59,6 @@ static silkworm::Bytes kHeader{*silkworm::from_hex(
6059
"ddcab467d5db31d063f2d58f266fa86c4502aa169d17762090e92b821843de69b41adbb5d86f5d114ba7f01a000000000000000000000"
6160
"00000000000000000000000000000000000000000000880000000000000000")};
6261
static silkworm::Bytes kBody{*silkworm::from_hex("c68369e45a03c0")};
63-
static silkworm::Bytes kNotEmptyBody{*silkworm::from_hex("c683897f2e04c0")};
64-
static silkworm::Bytes kInvalidJsonChainConfig{*silkworm::from_hex("000102")};
65-
static silkworm::Bytes kMissingChainIdConfig{*silkworm::from_hex(
66-
"7b226265726c696e426c6f636b223a31323234343030302c"
67-
"2262797a616e7469756d426c6f636b223a343337303030302c22636f6e7374616e74696e6f706c65426c6f636b223a373238303030302"
68-
"c2264616f466f726b426c6f636b223a313932303030302c22656970313530426c6f636b223a323436333030302c22656970313535426c"
69-
"6f636b223a323637353030302c22657468617368223a7b7d2c22686f6d657374656164426c6f636b223a313135303030302c226973746"
70-
"16e62756c426c6f636b223a393036393030302c226c6f6e646f6e426c6f636b223a31323936353030302c226d756972476c6163696572"
71-
"426c6f636b223a393230303030302c2270657465727362757267426c6f636b223a373238303030307d")};
72-
static silkworm::Bytes kInvalidChainIdConfig{*silkworm::from_hex(
73-
"7b226265726c696e426c6f636b223a31323234343030302c"
74-
"2262797a616e7469756d426c6f636b223a343337303030302c22636861696e4964223a22666f6f222c22636f6e7374616e74696e6f706"
75-
"c65426c6f636b223a373238303030302c2264616f466f726b426c6f636b223a313932303030302c22656970313530426c6f636b223a32"
76-
"3436333030302c22656970313535426c6f636b223a323637353030302c22657468617368223a7b7d2c22686f6d657374656164426c6f6"
77-
"36b223a313135303030302c22697374616e62756c426c6f636b223a393036393030302c226c6f6e646f6e426c6f636b223a3132393635"
78-
"3030302c226d756972476c6163696572426c6f636b223a393230303030302c2270657465727362757267426c6f636b223a37323830303"
79-
"0307d")};
80-
static silkworm::Bytes kChainConfig{*silkworm::from_hex(
81-
"7b226265726c696e426c6f636b223a31323234343030302c2262797a6"
82-
"16e7469756d426c6f636b223a343337303030302c22636861696e4964223a312c22636f6e7374616e74696e6f706c65426c6f636b223a"
83-
"373238303030302c2264616f466f726b426c6f636b223a313932303030302c22656970313530426c6f636b223a323436333030302c226"
84-
"56970313535426c6f636b223a323637353030302c22657468617368223a7b7d2c22686f6d657374656164426c6f636b223a3131353030"
85-
"30302c22697374616e62756c426c6f636b223a393036393030302c226c6f6e646f6e426c6f636b223a31323936353030302c226d75697"
86-
"2476c6163696572426c6f636b223a393230303030302c2270657465727362757267426c6f636b223a373238303030307d")};
8762

8863
TEST_CASE("read_header_number") {
8964
silkworm::test_util::SetLogVerbosityGuard log_guard{log::Level::kNone};
@@ -110,81 +85,6 @@ TEST_CASE("read_header_number") {
11085
}
11186
}
11287

113-
TEST_CASE("read_chain_config") {
114-
silkworm::test_util::SetLogVerbosityGuard log_guard{log::Level::kNone};
115-
WorkerPool pool{1};
116-
test::MockTransaction transaction;
117-
118-
SECTION("empty chain data") {
119-
EXPECT_CALL(transaction, get_one(db::table::kCanonicalHashesName, _)).WillOnce(InvokeWithoutArgs([]() -> Task<silkworm::Bytes> { co_return kBlockHash; }));
120-
EXPECT_CALL(transaction, get_one(db::table::kConfigName, _)).WillOnce(InvokeWithoutArgs([]() -> Task<silkworm::Bytes> { co_return silkworm::Bytes{}; }));
121-
auto result = boost::asio::co_spawn(pool, read_chain_config(transaction), boost::asio::use_future);
122-
#ifdef SILKWORM_SANITIZE // Avoid comparison against exception message: it triggers a TSAN data race seemingly related to libstdc++ string implementation
123-
CHECK_THROWS_AS(result.get(), std::invalid_argument);
124-
#else
125-
CHECK_THROWS_MATCHES(result.get(), std::invalid_argument, Message("empty chain config data in read_chain_config"));
126-
#endif // SILKWORM_SANITIZE
127-
}
128-
129-
SECTION("invalid JSON chain data") {
130-
EXPECT_CALL(transaction, get_one(db::table::kCanonicalHashesName, _)).WillOnce(InvokeWithoutArgs([]() -> Task<silkworm::Bytes> { co_return kBlockHash; }));
131-
EXPECT_CALL(transaction, get_one(db::table::kConfigName, _)).WillOnce(InvokeWithoutArgs([]() -> Task<silkworm::Bytes> { co_return kInvalidJsonChainConfig; }));
132-
auto result = boost::asio::co_spawn(pool, read_chain_config(transaction), boost::asio::use_future);
133-
CHECK_THROWS_AS(result.get(), nlohmann::json::parse_error);
134-
}
135-
136-
SECTION("valid JSON chain data") {
137-
EXPECT_CALL(transaction, get_one(db::table::kCanonicalHashesName, _)).WillOnce(InvokeWithoutArgs([]() -> Task<silkworm::Bytes> { co_return kBlockHash; }));
138-
EXPECT_CALL(transaction, get_one(db::table::kConfigName, _)).WillOnce(InvokeWithoutArgs([]() -> Task<silkworm::Bytes> { co_return kChainConfig; }));
139-
auto result = boost::asio::co_spawn(pool, read_chain_config(transaction), boost::asio::use_future);
140-
const auto chain_config = result.get();
141-
CHECK(chain_config.genesis_hash == 0x439816753229fc0736bf86a5048de4bc9fcdede8c91dadf88c828c76b2281dff_bytes32);
142-
CHECK(chain_config.config == R"({
143-
"berlinBlock":12244000,
144-
"byzantiumBlock":4370000,
145-
"chainId":1,
146-
"constantinopleBlock":7280000,
147-
"daoForkBlock":1920000,
148-
"eip150Block":2463000,
149-
"eip155Block":2675000,
150-
"ethash":{},
151-
"homesteadBlock":1150000,
152-
"istanbulBlock":9069000,
153-
"londonBlock":12965000,
154-
"muirGlacierBlock":9200000,
155-
"petersburgBlock":7280000
156-
})"_json);
157-
}
158-
}
159-
160-
TEST_CASE("read_chain_id") {
161-
silkworm::test_util::SetLogVerbosityGuard log_guard{log::Level::kNone};
162-
WorkerPool pool{1};
163-
test::MockTransaction transaction;
164-
165-
SECTION("missing chain identifier") {
166-
EXPECT_CALL(transaction, get_one(db::table::kCanonicalHashesName, _)).WillOnce(InvokeWithoutArgs([]() -> Task<silkworm::Bytes> { co_return kBlockHash; }));
167-
EXPECT_CALL(transaction, get_one(db::table::kConfigName, _)).WillOnce(InvokeWithoutArgs([]() -> Task<silkworm::Bytes> { co_return kMissingChainIdConfig; }));
168-
auto result = boost::asio::co_spawn(pool, read_chain_id(transaction), boost::asio::use_future);
169-
CHECK_THROWS_AS(result.get(), std::runtime_error);
170-
}
171-
172-
SECTION("invalid chain identifier") {
173-
EXPECT_CALL(transaction, get_one(db::table::kCanonicalHashesName, _)).WillOnce(InvokeWithoutArgs([]() -> Task<silkworm::Bytes> { co_return kBlockHash; }));
174-
EXPECT_CALL(transaction, get_one(db::table::kConfigName, _)).WillOnce(InvokeWithoutArgs([]() -> Task<silkworm::Bytes> { co_return kInvalidChainIdConfig; }));
175-
auto result = boost::asio::co_spawn(pool, read_chain_id(transaction), boost::asio::use_future);
176-
CHECK_THROWS_AS(result.get(), nlohmann::json::type_error);
177-
}
178-
179-
SECTION("valid chain identifier") {
180-
EXPECT_CALL(transaction, get_one(db::table::kCanonicalHashesName, _)).WillOnce(InvokeWithoutArgs([]() -> Task<silkworm::Bytes> { co_return kBlockHash; }));
181-
EXPECT_CALL(transaction, get_one(db::table::kConfigName, _)).WillOnce(InvokeWithoutArgs([]() -> Task<silkworm::Bytes> { co_return kChainConfig; }));
182-
auto result = boost::asio::co_spawn(pool, read_chain_id(transaction), boost::asio::use_future);
183-
const auto chain_id = result.get();
184-
CHECK(chain_id == 1);
185-
}
186-
}
187-
18888
TEST_CASE("read_canonical_block_hash") {
18989
silkworm::test_util::SetLogVerbosityGuard log_guard{log::Level::kNone};
19090
WorkerPool pool{1};

silkworm/rpc/json/types_test.cpp

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -621,10 +621,10 @@ TEST_CASE("deserialize block_number_or_hash", "[silkworm::json][from_json]") {
621621
}
622622

623623
TEST_CASE("serialize zero forks", "[silkworm::json][to_json]") {
624-
silkworm::rpc::ChainConfig cc{
625-
0x0000000000000000000000000000000000000000000000000000000000000000_bytes32,
626-
R"({"chainId":1,"ethash":{}})"_json};
627-
silkworm::rpc::Forks f{cc};
624+
auto cc = ChainConfig::from_json(R"({"chainId":1,"ethash":{}})"_json);
625+
REQUIRE(cc.has_value());
626+
cc->genesis_hash = 0x0000000000000000000000000000000000000000000000000000000000000000_bytes32;
627+
Forks f{*cc};
628628
nlohmann::json j = f;
629629
CHECK(j == R"({
630630
"genesis":"0x0000000000000000000000000000000000000000000000000000000000000000",
@@ -634,25 +634,25 @@ TEST_CASE("serialize zero forks", "[silkworm::json][to_json]") {
634634
}
635635

636636
TEST_CASE("serialize forks", "[silkworm::json][to_json]") {
637-
silkworm::rpc::ChainConfig cc{
638-
0x374f3a049e006f36f6cf91b02a3b0ee16c858af2f75858733eb0e927b5b7126c_bytes32,
639-
R"({
640-
"berlinBlock":12244000,
641-
"byzantiumBlock":4370000,
642-
"chainId":1,
643-
"constantinopleBlock":7280000,
644-
"daoForkBlock":1920000,
645-
"eip150Block":2463000,
646-
"eip155Block":2675000,
647-
"ethash":{},
648-
"homesteadBlock":1150000,
649-
"istanbulBlock":9069000,
650-
"londonBlock":12965000,
651-
"muirGlacierBlock":9200000,
652-
"petersburgBlock":7280000,
653-
"shanghaiTime":1678832736
654-
})"_json};
655-
silkworm::rpc::Forks f{cc};
637+
auto cc = ChainConfig::from_json(R"({
638+
"berlinBlock":12244000,
639+
"byzantiumBlock":4370000,
640+
"chainId":1,
641+
"constantinopleBlock":7280000,
642+
"daoForkBlock":1920000,
643+
"eip150Block":2463000,
644+
"eip155Block":2675000,
645+
"ethash":{},
646+
"homesteadBlock":1150000,
647+
"istanbulBlock":9069000,
648+
"londonBlock":12965000,
649+
"muirGlacierBlock":9200000,
650+
"petersburgBlock":7280000,
651+
"shanghaiTime":1678832736
652+
})"_json);
653+
REQUIRE(cc.has_value());
654+
cc->genesis_hash = 0x374f3a049e006f36f6cf91b02a3b0ee16c858af2f75858733eb0e927b5b7126c_bytes32;
655+
Forks f{*cc};
656656
nlohmann::json j = f;
657657
CHECK(j == R"({
658658
"genesis":"0x374f3a049e006f36f6cf91b02a3b0ee16c858af2f75858733eb0e927b5b7126c",

silkworm/rpc/storage/chain_storage.hpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,7 @@ class ChainStorage {
3333
virtual ~ChainStorage() = default;
3434

3535
//! Read the current chain configuration parameters
36-
[[nodiscard]] virtual Task<std::optional<silkworm::ChainConfig>> read_chain_config() const = 0;
37-
38-
//! Read the current chain unique identifier
39-
[[nodiscard]] virtual Task<std::optional<ChainId>> read_chain_id() const = 0;
36+
[[nodiscard]] virtual Task<std::optional<ChainConfig>> read_chain_config() const = 0;
4037

4138
//! Get the highest block number
4239
[[nodiscard]] virtual Task<BlockNum> highest_block_number() const = 0;

silkworm/rpc/storage/local_chain_storage.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@ Task<std::optional<ChainConfig>> LocalChainStorage::read_chain_config() const {
2929
co_return data_model_.read_chain_config();
3030
}
3131

32-
Task<std::optional<ChainId>> LocalChainStorage::read_chain_id() const {
33-
co_return data_model_.read_chain_id();
34-
}
35-
3632
Task<BlockNum> LocalChainStorage::highest_block_number() const {
3733
co_return data_model_.highest_block_number();
3834
}

silkworm/rpc/storage/local_chain_storage.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ class LocalChainStorage : public ChainStorage {
3131
~LocalChainStorage() override = default;
3232

3333
[[nodiscard]] Task<std::optional<ChainConfig>> read_chain_config() const override;
34-
[[nodiscard]] Task<std::optional<ChainId>> read_chain_id() const override;
3534

3635
[[nodiscard]] Task<BlockNum> highest_block_number() const override;
3736

silkworm/rpc/storage/remote_chain_storage.cpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818

1919
#include <utility>
2020

21+
#include <silkworm/db/tables.hpp>
22+
#include <silkworm/infra/common/log.hpp>
2123
#include <silkworm/infra/grpc/common/conversion.hpp>
24+
#include <silkworm/rpc/core/blocks.hpp>
2225
#include <silkworm/rpc/core/rawdb/chain.hpp>
2326

2427
namespace silkworm::rpc {
@@ -30,13 +33,20 @@ RemoteChainStorage::RemoteChainStorage(ethdb::Transaction& tx,
3033
block_provider_{std::move(block_provider)},
3134
block_number_from_txn_hash_provider_{std::move(block_number_from_txn_hash_provider)} {}
3235

33-
Task<std::optional<silkworm::ChainConfig>> RemoteChainStorage::read_chain_config() const {
34-
const auto rpc_chain_config{co_await core::rawdb::read_chain_config(tx_)};
35-
co_return silkworm::ChainConfig::from_json(rpc_chain_config.config);
36-
}
37-
38-
Task<std::optional<ChainId>> RemoteChainStorage::read_chain_id() const {
39-
co_return co_await core::rawdb::read_chain_id(tx_);
36+
Task<std::optional<ChainConfig>> RemoteChainStorage::read_chain_config() const {
37+
const auto genesis_block_hash{co_await core::rawdb::read_canonical_block_hash(tx_, core::kEarliestBlockNumber)};
38+
SILK_DEBUG << "rawdb::read_chain_config genesis_block_hash: " << to_hex(genesis_block_hash);
39+
const ByteView genesis_block_hash_bytes{genesis_block_hash.bytes, kHashLength};
40+
const auto data{co_await tx_.get_one(db::table::kConfigName, genesis_block_hash_bytes)};
41+
if (data.empty()) {
42+
throw std::invalid_argument{"empty chain config data in read_chain_config"};
43+
}
44+
SILK_DEBUG << "rawdb::read_chain_config chain config data: " << data.c_str();
45+
const auto json_config = nlohmann::json::parse(data.begin(), data.end());
46+
SILK_TRACE << "rawdb::read_chain_config chain config JSON: " << json_config.dump();
47+
std::optional<ChainConfig> chain_config = ChainConfig::from_json(json_config);
48+
chain_config->genesis_hash = genesis_block_hash;
49+
co_return chain_config;
4050
}
4151

4252
Task<BlockNum> RemoteChainStorage::highest_block_number() const {

silkworm/rpc/storage/remote_chain_storage.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ class RemoteChainStorage : public ChainStorage {
3939
~RemoteChainStorage() override = default;
4040

4141
[[nodiscard]] Task<std::optional<silkworm::ChainConfig>> read_chain_config() const override;
42-
[[nodiscard]] Task<std::optional<ChainId>> read_chain_id() const override;
4342

4443
[[nodiscard]] Task<BlockNum> highest_block_number() const override;
4544

0 commit comments

Comments
 (0)