diff --git a/silkworm/rpc/commands/debug_api.cpp b/silkworm/rpc/commands/debug_api.cpp index 83a0c23008..bad0af9da3 100644 --- a/silkworm/rpc/commands/debug_api.cpp +++ b/silkworm/rpc/commands/debug_api.cpp @@ -302,16 +302,14 @@ Task DebugRpcApi::handle_debug_account_at(const nlohmann::json& request, n SILK_TRACE << "Block number: " << block_number << " #tnx: " << transactions.size(); - auto chain_config_ptr = co_await chain_storage->read_chain_config(); - ensure(chain_config_ptr.has_value(), "cannot read chain config"); - + const auto chain_config = co_await chain_storage->read_chain_config(); auto this_executor = co_await boost::asio::this_coro::executor; auto result = co_await async_task(workers_.executor(), [&]() -> nlohmann::json { auto state = tx->create_state(this_executor, *chain_storage, block_number - 1); auto account_opt = state->read_account(address); account_opt.value_or(silkworm::Account{}); - EVMExecutor executor{*chain_config_ptr, workers_, state}; + EVMExecutor executor{chain_config, workers_, state}; uint64_t index = std::min(static_cast(transactions.size()), tx_index); for (uint64_t idx{0}; idx < index; idx++) { @@ -710,9 +708,9 @@ Task DebugRpcApi::handle_debug_get_raw_header(const nlohmann::json& reques const auto chain_storage = tx->create_storage(); const auto block_number = co_await core::get_block_number(block_id, *tx); const auto block_hash = co_await chain_storage->read_canonical_hash(block_number); - auto header = co_await chain_storage->read_header(block_number, block_hash->bytes); + const auto header = co_await chain_storage->read_header(block_number, block_hash->bytes); if (!header) { - throw std::invalid_argument("header not found"); + throw std::invalid_argument("header " + std::to_string(block_number) + " not found"); } Bytes encoded_header; rlp::encode(encoded_header, *header); diff --git a/silkworm/rpc/commands/engine_api.cpp b/silkworm/rpc/commands/engine_api.cpp index 4eeb86a0e1..b962b43a64 100644 --- a/silkworm/rpc/commands/engine_api.cpp +++ b/silkworm/rpc/commands/engine_api.cpp @@ -318,25 +318,24 @@ Task EngineRpcApi::handle_engine_new_payload_v2(const nlohmann::json& requ #endif const auto storage{tx->create_storage()}; const auto config{co_await storage->read_chain_config()}; - ensure(config.has_value(), "execution layer has invalid configuration"); - ensure(config->shanghai_time.has_value(), "execution layer has no Shanghai timestamp in configuration"); + ensure(config.shanghai_time.has_value(), "execution layer has no Shanghai timestamp in configuration"); // We MUST check that CL has sent the expected ExecutionPayload version [Specification for params] - if (payload.timestamp < config->shanghai_time && payload.version != ExecutionPayload::V1) { + if (payload.timestamp < config.shanghai_time && payload.version != ExecutionPayload::V1) { const auto error_msg = "consensus layer must use ExecutionPayloadV1 if timestamp lower than Shanghai"; SILK_ERROR << error_msg; reply = make_json_error(request, kInvalidParams, error_msg); co_await tx->close(); co_return; } - if (payload.timestamp >= config->shanghai_time && payload.version != ExecutionPayload::V2) { + if (payload.timestamp >= config.shanghai_time && payload.version != ExecutionPayload::V2) { const auto error_msg = "consensus layer must use ExecutionPayloadV2 if timestamp greater or equal to Shanghai"; SILK_ERROR << error_msg; reply = make_json_error(request, kInvalidParams, error_msg); co_await tx->close(); co_return; } - if (config->cancun_time && payload.timestamp >= config->cancun_time) { + if (config.cancun_time && payload.timestamp >= config.cancun_time) { const auto error_msg = "consensus layer must use ExecutionPayloadV3 if timestamp greater or equal to Cancun"; SILK_ERROR << error_msg; reply = make_json_error(request, kUnsupportedFork, error_msg); @@ -382,12 +381,11 @@ Task EngineRpcApi::handle_engine_new_payload_v3(const nlohmann::json& requ #endif const auto storage{tx->create_storage()}; const auto config{co_await storage->read_chain_config()}; - ensure(config.has_value(), "execution layer has invalid configuration"); - ensure(config->shanghai_time.has_value(), "execution layer has no Shanghai timestamp in configuration"); - ensure(config->cancun_time.has_value(), "execution layer has no Cancun timestamp in configuration"); + ensure(config.shanghai_time.has_value(), "execution layer has no Shanghai timestamp in configuration"); + ensure(config.cancun_time.has_value(), "execution layer has no Cancun timestamp in configuration"); // We MUST check that CL has sent the expected ExecutionPayload version [Specification for params] - if (payload.timestamp >= config->cancun_time && payload.version != ExecutionPayload::V3) { + if (payload.timestamp >= config.cancun_time && payload.version != ExecutionPayload::V3) { const auto error_msg = "consensus layer must use ExecutionPayloadV3 if timestamp greater or equal to Cancun"; SILK_ERROR << error_msg; reply = make_json_error(request, kUnsupportedFork, error_msg); @@ -581,13 +579,12 @@ Task EngineRpcApi::handle_engine_exchange_transition_configuration_v1(cons #endif const auto storage{tx->create_storage()}; const auto config{co_await storage->read_chain_config()}; - ensure(config.has_value(), "execution layer has invalid configuration"); - ensure(config->terminal_total_difficulty.has_value(), "execution layer does not have terminal total difficulty"); + ensure(config.terminal_total_difficulty.has_value(), "execution layer does not have terminal total difficulty"); // We SHOULD check for any configuration mismatch except `terminalBlockNumber` [Specification 2.] - if (config->terminal_total_difficulty != cl_configuration.terminal_total_difficulty) { + if (config.terminal_total_difficulty != cl_configuration.terminal_total_difficulty) { SILK_ERROR << "execution layer has the incorrect terminal total difficulty, expected: " - << cl_configuration.terminal_total_difficulty << " got: " << config->terminal_total_difficulty.value(); + << cl_configuration.terminal_total_difficulty << " got: " << config.terminal_total_difficulty.value(); reply = make_json_error(request, kInvalidParams, "consensus layer terminal total difficulty does not match"); co_await tx->close(); co_return; @@ -602,7 +599,7 @@ Task EngineRpcApi::handle_engine_exchange_transition_configuration_v1(cons // We MUST respond with configurable setting values set according to EIP-3675 [Specification 1.] const TransitionConfiguration transition_configuration{ - .terminal_total_difficulty = config->terminal_total_difficulty.value(), + .terminal_total_difficulty = config.terminal_total_difficulty.value(), .terminal_block_hash = kZeroHash, // terminal_block_hash removed from chain_config, return zero .terminal_block_number = 0 // terminal_block_number removed from chain_config, return zero }; diff --git a/silkworm/rpc/commands/erigon_api.cpp b/silkworm/rpc/commands/erigon_api.cpp index 96a1bb628d..4af26544e9 100644 --- a/silkworm/rpc/commands/erigon_api.cpp +++ b/silkworm/rpc/commands/erigon_api.cpp @@ -129,9 +129,12 @@ Task ErigonRpcApi::handle_erigon_get_block_by_timestamp(const nlohmann::js // Lookup the first and last block headers const auto first_header = co_await chain_storage->read_canonical_header(kEarliestBlockNumber); + ensure(first_header.has_value(), "cannot find earliest header"); const auto head_header_hash = co_await core::rawdb::read_head_header_hash(*tx); - const auto header_header_block_number = co_await chain_storage->read_block_number(head_header_hash); - const auto current_header = co_await chain_storage->read_header(*header_header_block_number, head_header_hash); + const auto head_header_block_number = co_await chain_storage->read_block_number(head_header_hash); + ensure(head_header_block_number.has_value(), "cannot find head header hash"); + const auto current_header = co_await chain_storage->read_header(*head_header_block_number, head_header_hash); + ensure(current_header.has_value(), "cannot find head header"); const BlockNum current_block_number = current_header->number; // Find the lowest block header w/ timestamp greater or equal to provided timestamp @@ -142,13 +145,14 @@ Task ErigonRpcApi::handle_erigon_get_block_by_timestamp(const nlohmann::js block_number = kEarliestBlockNumber; } else { // Good-old binary search to find the lowest block header matching timestamp + // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines) auto matching_block_number = co_await binary_search(current_block_number, [&](uint64_t bn) -> Task { const auto header = co_await chain_storage->read_canonical_header(bn); - co_return header->timestamp >= timestamp; + co_return header && header->timestamp >= timestamp; }); // TODO(canepat) we should try to avoid this block header lookup (just done in search) auto matching_header = co_await chain_storage->read_canonical_header(matching_block_number); - while (matching_header->timestamp > timestamp) { + while (matching_header && matching_header->timestamp > timestamp) { const auto header = co_await chain_storage->read_canonical_header(matching_block_number - 1); if (!header || header->timestamp < timestamp) { break; @@ -161,14 +165,9 @@ Task ErigonRpcApi::handle_erigon_get_block_by_timestamp(const nlohmann::js // Lookup and return the matching block const auto block_with_hash = co_await core::read_block_by_number(*block_cache_, *chain_storage, block_number); - if (!block_with_hash) { - const std::string error_msg = "block not found "; - SILK_ERROR << "erigon_get_block_by_timestamp: core::read_block_by_number: " << error_msg << request.dump(); - make_glaze_json_error(request, 100, error_msg, reply); - co_await tx->close(); // RAII not (yet) available with coroutines - co_return; - } + ensure(block_with_hash != nullptr, [&]() { return "block " + std::to_string(block_number) + " not found"; }); const auto total_difficulty = co_await chain_storage->read_total_difficulty(block_with_hash->hash, block_number); + ensure(total_difficulty.has_value(), [&]() { return "no total difficulty for block " + std::to_string(block_number); }); const Block extended_block{block_with_hash, *total_difficulty, full_tx}; make_glaze_json_content(request, extended_block, reply); @@ -449,11 +448,7 @@ Task ErigonRpcApi::handle_erigon_forks(const nlohmann::json& request, nloh const auto chain_storage = tx->create_storage(); const auto chain_config{co_await chain_storage->read_chain_config()}; - if (!chain_config) { - throw std::runtime_error("Chain config missing"); - } - SILK_DEBUG << "chain config: " << *chain_config; - Forks forks{*chain_config}; + Forks forks{chain_config}; reply = make_json_content(request, forks); } catch (const std::exception& e) { diff --git a/silkworm/rpc/commands/eth_api.cpp b/silkworm/rpc/commands/eth_api.cpp index f3472c14b2..3c98a41109 100644 --- a/silkworm/rpc/commands/eth_api.cpp +++ b/silkworm/rpc/commands/eth_api.cpp @@ -75,9 +75,8 @@ Task EthereumRpcApi::handle_eth_chain_id(const nlohmann::json& request, nl try { const auto chain_storage{tx->create_storage()}; - auto chain_config = co_await chain_storage->read_chain_config(); - ensure(chain_config.has_value(), "cannot read chain config"); - reply = make_json_content(request, to_quantity((*chain_config).chain_id)); + const auto chain_config = co_await chain_storage->read_chain_config(); + reply = make_json_content(request, to_quantity(chain_config.chain_id)); } catch (const std::exception& e) { SILK_ERROR << "exception: " << e.what() << " processing request: " << request.dump(); reply = make_json_error(request, 100, e.what()); @@ -199,7 +198,7 @@ Task EthereumRpcApi::handle_eth_get_block_by_hash(const nlohmann::json& re if (block_with_hash) { BlockNum block_number = block_with_hash->block.header.number; const auto total_difficulty{co_await chain_storage->read_total_difficulty(block_with_hash->hash, block_number)}; - ensure_post_condition(total_difficulty.has_value(), [&]() { return "no difficulty for block number=" + std::to_string(block_number); }); + ensure(total_difficulty.has_value(), [&]() { return "no total difficulty for block: " + std::to_string(block_number); }); const Block extended_block{block_with_hash, *total_difficulty, full_tx}; make_glaze_json_content(request, extended_block, reply); } else { @@ -240,7 +239,7 @@ Task EthereumRpcApi::handle_eth_get_block_by_number(const nlohmann::json& const auto block_with_hash = co_await core::read_block_by_number(*block_cache_, *chain_storage, block_number); if (block_with_hash) { const auto total_difficulty{co_await chain_storage->read_total_difficulty(block_with_hash->hash, block_number)}; - ensure_post_condition(total_difficulty.has_value(), [&]() { return "no difficulty for block number=" + std::to_string(block_number); }); + ensure(total_difficulty.has_value(), [&]() { return "no total difficulty for block: " + std::to_string(block_number); }); const Block extended_block{block_with_hash, *total_difficulty, full_tx}; make_glaze_json_content(request, extended_block, reply); @@ -365,6 +364,7 @@ Task EthereumRpcApi::handle_eth_get_uncle_by_block_hash_and_index(const nl } else { const auto block_number = block_with_hash->block.header.number; const auto total_difficulty = co_await chain_storage->read_total_difficulty(block_hash, block_number); + ensure(total_difficulty.has_value(), [&]() { return "no total difficulty for block: " + std::to_string(block_number); }); const auto& uncle = ommers[idx]; auto uncle_block_with_hash = std::make_shared(); @@ -420,6 +420,7 @@ Task EthereumRpcApi::handle_eth_get_uncle_by_block_number_and_index(const make_glaze_json_null_content(request, reply); } else { const auto total_difficulty = co_await chain_storage->read_total_difficulty(block_with_hash->hash, block_number); + ensure(total_difficulty.has_value(), [&]() { return "no total difficulty for block: " + std::to_string(block_number); }); const auto& uncle = ommers[idx]; auto uncle_block_with_hash = std::make_shared(); @@ -900,11 +901,9 @@ Task EthereumRpcApi::handle_eth_estimate_gas(const nlohmann::json& request const BlockNumberOrHash block_number_or_hash{core::kLatestBlockId}; const auto chain_storage{tx->create_storage()}; - auto chain_config = co_await chain_storage->read_chain_config(); - ensure(chain_config.has_value(), "cannot read chain config"); - + const auto chain_config = co_await chain_storage->read_chain_config(); const auto latest_block_number = co_await core::get_block_number(core::kLatestBlockId, *tx); - SILK_DEBUG << "chain_id: " << (*chain_config).chain_id << ", latest_block_number: " << latest_block_number; + SILK_DEBUG << "chain_id: " << chain_config.chain_id << ", latest_block_number: " << latest_block_number; const auto latest_block_with_hash = co_await core::read_block_by_number(*block_cache_, *chain_storage, latest_block_number); if (!latest_block_with_hash) { @@ -923,9 +922,8 @@ Task EthereumRpcApi::handle_eth_estimate_gas(const nlohmann::json& request return state_reader.read_account(address, block_number + 1); }; - rpc::EstimateGasOracle estimate_gas_oracle{block_header_provider, account_reader, *chain_config, workers_, *tx, *chain_storage}; - - auto estimated_gas = co_await estimate_gas_oracle.estimate_gas(call, latest_block); + rpc::EstimateGasOracle estimate_gas_oracle{block_header_provider, account_reader, chain_config, workers_, *tx, *chain_storage}; + const auto estimated_gas = co_await estimate_gas_oracle.estimate_gas(call, latest_block); reply = make_json_content(request, to_quantity(estimated_gas)); } catch (const rpc::EstimateGasException& e) { @@ -1136,8 +1134,7 @@ Task EthereumRpcApi::handle_eth_call(const nlohmann::json& request, std::s try { const auto chain_storage{tx->create_storage()}; - auto chain_config = co_await chain_storage->read_chain_config(); - ensure(chain_config.has_value(), "cannot read chain config"); + const auto chain_config = co_await chain_storage->read_chain_config(); const auto [block_number, is_latest_block] = co_await core::get_block_number(block_id, *tx, /*latest_required=*/true); tx->set_state_cache_enabled(/*cache_enabled=*/is_latest_block); @@ -1150,7 +1147,7 @@ Task EthereumRpcApi::handle_eth_call(const nlohmann::json& request, std::s silkworm::Transaction txn{call.to_transaction(block_with_hash->block.header.base_fee_per_gas)}; const auto execution_result = co_await EVMExecutor::call( - *chain_config, *chain_storage, workers_, block_with_hash->block, txn, [&](auto& io_executor, auto block_num, auto& storage) { + chain_config, *chain_storage, workers_, block_with_hash->block, txn, [&](auto& io_executor, auto block_num, auto& storage) { return tx->create_state(io_executor, storage, block_num); }); @@ -1302,9 +1299,7 @@ Task EthereumRpcApi::handle_eth_create_access_list(const nlohmann::json& r co_return; } - auto chain_config = co_await chain_storage->read_chain_config(); - ensure(chain_config.has_value(), "cannot read chain config"); - + const auto chain_config = co_await chain_storage->read_chain_config(); const bool is_latest_block = co_await core::get_latest_executed_block_number(*tx) == block_with_hash->block.header.number; tx->set_state_cache_enabled(/*cache_enabled=*/is_latest_block); @@ -1339,7 +1334,7 @@ Task EthereumRpcApi::handle_eth_create_access_list(const nlohmann::json& r AccessList saved_access_list = call.access_list; while (true) { const auto execution_result = co_await EVMExecutor::call( - *chain_config, *chain_storage, workers_, block_with_hash->block, txn, [&](auto& io_executor, auto block_num, auto& storage) { + chain_config, *chain_storage, workers_, block_with_hash->block, txn, [&](auto& io_executor, auto block_num, auto& storage) { return tx->create_state(io_executor, storage, block_num); }, tracers, /* refund */ true, /* gasBailout */ false); @@ -1413,9 +1408,7 @@ Task EthereumRpcApi::handle_eth_call_bundle(const nlohmann::json& request, co_await tx->close(); // RAII not (yet) available with coroutines co_return; } - auto chain_config = co_await chain_storage->read_chain_config(); - ensure(chain_config.has_value(), "cannot read chain config"); - + const auto chain_config = co_await chain_storage->read_chain_config(); const bool is_latest_block = co_await core::get_latest_executed_block_number(*tx) == block_with_hash->block.header.number; tx->set_state_cache_enabled(/*cache_enabled=*/is_latest_block); @@ -1437,7 +1430,7 @@ Task EthereumRpcApi::handle_eth_call_bundle(const nlohmann::json& request, } const auto execution_result = co_await EVMExecutor::call( - *chain_config, *chain_storage, workers_, block_with_hash->block, tx_with_block->transaction, [&](auto& io_executor, auto block_num, auto& storage) { + chain_config, *chain_storage, workers_, block_with_hash->block, tx_with_block->transaction, [&](auto& io_executor, auto block_num, auto& storage) { return tx->create_state(io_executor, storage, block_num); }); if (execution_result.pre_check_error) { @@ -2100,10 +2093,8 @@ Task EthereumRpcApi::handle_fee_history(const nlohmann::json& request, nlo return core::get_block_number(core::kLatestBlockId, *tx); }; - auto chain_config = co_await chain_storage->read_chain_config(); - ensure(chain_config.has_value(), "cannot read chain config"); - - rpc::fee_history::FeeHistoryOracle oracle{*chain_config, block_header_provider, block_provider, receipts_provider, latest_block_provider}; + const auto chain_config = co_await chain_storage->read_chain_config(); + rpc::fee_history::FeeHistoryOracle oracle{chain_config, block_header_provider, block_provider, receipts_provider, latest_block_provider}; const auto block_number = co_await core::get_block_number(newest_block, *tx); const auto fee_history = co_await oracle.fee_history(block_number, block_count, reward_percentiles); diff --git a/silkworm/rpc/commands/ots_api.cpp b/silkworm/rpc/commands/ots_api.cpp index ebbd7fee5f..c5ebb0d958 100644 --- a/silkworm/rpc/commands/ots_api.cpp +++ b/silkworm/rpc/commands/ots_api.cpp @@ -108,7 +108,7 @@ Task OtsRpcApi::handle_ots_get_block_details(const nlohmann::json& request const auto block_with_hash = co_await core::read_block_by_number(*block_cache_, *chain_storage, block_number); if (block_with_hash) { const auto total_difficulty{co_await chain_storage->read_total_difficulty(block_with_hash->hash, block_number)}; - ensure_post_condition(total_difficulty.has_value(), [&]() { return "no difficulty for block number=" + std::to_string(block_number); }); + ensure(total_difficulty.has_value(), [&]() { return "no total difficulty for block: " + std::to_string(block_number); }); const Block extended_block{block_with_hash, *total_difficulty, false}; const auto block_size = extended_block.get_block_size(); const BlockDetails block_details{block_size, block_with_hash->hash, block_with_hash->block.header, *total_difficulty, @@ -116,8 +116,7 @@ Task OtsRpcApi::handle_ots_get_block_details(const nlohmann::json& request block_with_hash->block.withdrawals}; const auto receipts = co_await core::get_receipts(*tx, *block_with_hash); const auto chain_config = co_await chain_storage->read_chain_config(); - ensure(chain_config.has_value(), "cannot read chain config"); - const IssuanceDetails issuance = get_issuance(*chain_config, *block_with_hash); + const IssuanceDetails issuance = get_issuance(chain_config, *block_with_hash); const intx::uint256 total_fees = get_block_fees(*block_with_hash, receipts); const BlockDetailsResponse block_details_response{block_details, issuance, total_fees}; reply = make_json_content(request, block_details_response); @@ -159,7 +158,7 @@ Task OtsRpcApi::handle_ots_get_block_details_by_hash(const nlohmann::json& if (block_with_hash) { const auto block_number = block_with_hash->block.header.number; const auto total_difficulty{co_await chain_storage->read_total_difficulty(block_with_hash->hash, block_number)}; - ensure_post_condition(total_difficulty.has_value(), [&]() { return "no difficulty for block number=" + std::to_string(block_number); }); + ensure(total_difficulty.has_value(), [&]() { return "no total difficulty for block: " + std::to_string(block_number); }); const Block extended_block{block_with_hash, *total_difficulty, false}; const auto block_size = extended_block.get_block_size(); const BlockDetails block_details{block_size, block_with_hash->hash, block_with_hash->block.header, *total_difficulty, @@ -167,8 +166,7 @@ Task OtsRpcApi::handle_ots_get_block_details_by_hash(const nlohmann::json& block_with_hash->block.withdrawals}; const auto receipts = co_await core::get_receipts(*tx, *block_with_hash); const auto chain_config = co_await chain_storage->read_chain_config(); - ensure(chain_config.has_value(), "cannot read chain config"); - const IssuanceDetails issuance = get_issuance(*chain_config, *block_with_hash); + const IssuanceDetails issuance = get_issuance(chain_config, *block_with_hash); const intx::uint256 total_fees = get_block_fees(*block_with_hash, receipts); const BlockDetailsResponse block_details_response{block_details, issuance, total_fees}; reply = make_json_content(request, block_details_response); @@ -214,7 +212,7 @@ Task OtsRpcApi::handle_ots_get_block_transactions(const nlohmann::json& re const auto block_with_hash = co_await core::read_block_by_number(*block_cache_, *chain_storage, block_number); if (block_with_hash) { const auto total_difficulty{co_await chain_storage->read_total_difficulty(block_with_hash->hash, block_number)}; - ensure_post_condition(total_difficulty.has_value(), [&]() { return "no difficulty for block number=" + std::to_string(block_number); }); + ensure(total_difficulty.has_value(), [&]() { return "no total difficulty for block: " + std::to_string(block_number); }); const Block extended_block{block_with_hash, *total_difficulty, false}; auto receipts = co_await core::get_receipts(*tx, *block_with_hash); auto block_size = extended_block.get_block_size(); @@ -866,7 +864,7 @@ Task OtsRpcApi::trace_block(ethdb::Transaction& tx, BlockNum block_number, } const auto total_difficulty{co_await chain_storage->read_total_difficulty(block_with_hash->hash, block_number)}; - ensure_post_condition(total_difficulty.has_value(), [&]() { return "no difficulty for block number=" + std::to_string(block_number); }); + ensure(total_difficulty.has_value(), [&]() { return "no total difficulty for block: " + std::to_string(block_number); }); const auto receipts = co_await core::get_receipts(tx, *block_with_hash); const Block extended_block{block_with_hash, *total_difficulty, false}; diff --git a/silkworm/rpc/core/call_many.cpp b/silkworm/rpc/core/call_many.cpp index bb7a7c9c01..9acd908761 100644 --- a/silkworm/rpc/core/call_many.cpp +++ b/silkworm/rpc/core/call_many.cpp @@ -156,9 +156,7 @@ Task CallExecutor::execute( co_return result; } - const auto chain_config_ptr = co_await chain_storage->read_chain_config(); - ensure(chain_config_ptr.has_value(), "cannot read chain config"); - + const auto chain_config = co_await chain_storage->read_chain_config(); const auto block_with_hash = co_await rpc::core::read_block_by_number_or_hash(block_cache_, *chain_storage, transaction_, context.block_number); if (!block_with_hash) { throw std::invalid_argument("read_block_by_number_or_hash: block not found"); @@ -170,7 +168,7 @@ Task CallExecutor::execute( auto this_executor = co_await boost::asio::this_coro::executor; result = co_await async_task(workers_.executor(), [&]() -> CallManyResult { - return executes_all_bundles(*chain_config_ptr, + return executes_all_bundles(chain_config, *chain_storage, block_with_hash, bundles, diff --git a/silkworm/rpc/core/estimate_gas_oracle.cpp b/silkworm/rpc/core/estimate_gas_oracle.cpp index 14435d95fc..04929ad5b9 100644 --- a/silkworm/rpc/core/estimate_gas_oracle.cpp +++ b/silkworm/rpc/core/estimate_gas_oracle.cpp @@ -39,7 +39,7 @@ Task EstimateGasOracle::estimate_gas(const Call& call, const silk } else { const auto header = co_await block_header_provider_(block_number); if (!header) { - throw EstimateGasException{-1, "invalid header"}; + throw EstimateGasException{-1, "header " + std::to_string(block_number) + " not found"}; } hi = header->gas_limit; diff --git a/silkworm/rpc/core/estimate_gas_oracle_test.cpp b/silkworm/rpc/core/estimate_gas_oracle_test.cpp index 6ca2dec97b..df9714e671 100644 --- a/silkworm/rpc/core/estimate_gas_oracle_test.cpp +++ b/silkworm/rpc/core/estimate_gas_oracle_test.cpp @@ -86,10 +86,12 @@ TEST_CASE("estimate gas") { silkworm::Account kAccount{0, kBalance}; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines) BlockHeaderProvider block_header_provider = [&kBlockHeader](BlockNum /*block_number*/) -> Task> { co_return kBlockHeader; }; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines) AccountReader account_reader = [&kAccount](const evmc::address& /*address*/, BlockNum /*block_number*/) -> Task> { co_return kAccount; }; diff --git a/silkworm/rpc/core/evm_debug.cpp b/silkworm/rpc/core/evm_debug.cpp index e6d90eb678..003293c537 100644 --- a/silkworm/rpc/core/evm_debug.cpp +++ b/silkworm/rpc/core/evm_debug.cpp @@ -382,12 +382,11 @@ Task DebugExecutor::execute(json::Stream& stream, const ChainStorage& stor SILK_DEBUG << "execute: block_number: " << block_number << " #txns: " << transactions.size() << " config: " << config_; - const auto chain_config_ptr = co_await storage.read_chain_config(); - ensure(chain_config_ptr.has_value(), "cannot read chain config"); + const auto chain_config = co_await storage.read_chain_config(); auto current_executor = co_await boost::asio::this_coro::executor; co_await async_task(workers_.executor(), [&]() -> void { auto state = tx_.create_state(current_executor, storage, block_number - 1); - EVMExecutor executor{*chain_config_ptr, workers_, state}; + EVMExecutor executor{chain_config, workers_, state}; for (std::uint64_t idx = 0; idx < transactions.size(); idx++) { rpc::Transaction txn{block.transactions[idx]}; @@ -441,12 +440,11 @@ Task DebugExecutor::execute( << " index: " << std::dec << index << " config: " << config_; - const auto chain_config_ptr = co_await storage.read_chain_config(); - ensure(chain_config_ptr.has_value(), "cannot read chain config"); + const auto chain_config = co_await storage.read_chain_config(); auto current_executor = co_await boost::asio::this_coro::executor; co_await async_task(workers_.executor(), [&]() { auto state = tx_.create_state(current_executor, storage, block_number); - EVMExecutor executor{*chain_config_ptr, workers_, state}; + EVMExecutor executor{chain_config, workers_, state}; for (auto idx{0}; idx < index; idx++) { silkworm::Transaction txn{block.transactions[std::size_t(idx)]}; @@ -493,13 +491,11 @@ Task DebugExecutor::execute( << " transaction_index: " << std::dec << transaction_index << " config: " << config_; - const auto chain_config_ptr = co_await storage.read_chain_config(); - ensure(chain_config_ptr.has_value(), "cannot read chain config"); - + const auto chain_config = co_await storage.read_chain_config(); auto current_executor = co_await boost::asio::this_coro::executor; co_await async_task(workers_.executor(), [&]() { auto state = tx_.create_state(current_executor, storage, block.header.number); - EVMExecutor executor{*chain_config_ptr, workers_, state}; + EVMExecutor executor{chain_config, workers_, state}; for (auto idx{0}; idx < transaction_index; idx++) { silkworm::Transaction txn{block_transactions[std::size_t(idx)]}; diff --git a/silkworm/rpc/core/evm_trace.cpp b/silkworm/rpc/core/evm_trace.cpp index eed932aeff..caf330c660 100644 --- a/silkworm/rpc/core/evm_trace.cpp +++ b/silkworm/rpc/core/evm_trace.cpp @@ -1268,9 +1268,8 @@ Task> TraceCallExecutor::trace_block(const BlockWithHash& blo co_return traces; } - const auto chain_config_ptr = co_await chain_storage_.read_chain_config(); - ensure(chain_config_ptr.has_value(), "cannot read chain config"); - const auto rule_set_factory = protocol::rule_set_factory(*chain_config_ptr); + const auto chain_config = co_await chain_storage_.read_chain_config(); + const auto rule_set_factory = protocol::rule_set_factory(chain_config); const auto block_rewards = rule_set_factory->compute_reward(block_with_hash.block); if (filter.count > 0 && filter.after == 0) { @@ -1327,9 +1326,7 @@ Task> TraceCallExecutor::trace_block_transactions(c SILK_TRACE << "trace_block_transactions: block_number: " << std::dec << block_number << " #txns: " << transactions.size() << " config: " << config; - const auto chain_config_ptr = co_await chain_storage_.read_chain_config(); - ensure(chain_config_ptr.has_value(), "cannot read chain config"); - + const auto chain_config = co_await chain_storage_.read_chain_config(); auto current_executor = co_await boost::asio::this_coro::executor; const auto call_result = co_await async_task(workers_.executor(), [&]() -> std::vector { auto state = tx_.create_state(current_executor, chain_storage_, block_number - 1); @@ -1339,7 +1336,7 @@ Task> TraceCallExecutor::trace_block_transactions(c std::shared_ptr ibs_tracer = std::make_shared(state_addresses); auto curr_state = tx_.create_state(current_executor, chain_storage_, block_number - 1); - EVMExecutor executor{*chain_config_ptr, workers_, curr_state}; + EVMExecutor executor{chain_config, workers_, curr_state}; std::vector trace_call_result(transactions.size()); for (size_t index = 0; index < transactions.size(); index++) { @@ -1394,9 +1391,7 @@ Task TraceCallExecutor::trace_calls(const silkworm::Block& << " block_number: " << block_number << " #trace_calls: " << calls.size(); - const auto chain_config_ptr = co_await chain_storage_.read_chain_config(); - ensure(chain_config_ptr.has_value(), "cannot read chain config"); - + const auto chain_config = co_await chain_storage_.read_chain_config(); auto current_executor = co_await boost::asio::this_coro::executor; const auto trace_calls_result = co_await async_task(workers_.executor(), [&]() -> TraceManyCallResult { auto state = tx_.create_state(current_executor, chain_storage_, block_number); @@ -1404,7 +1399,7 @@ Task TraceCallExecutor::trace_calls(const silkworm::Block& StateAddresses state_addresses(initial_ibs); auto curr_state = tx_.create_state(current_executor, chain_storage_, block_number); - EVMExecutor executor{*chain_config_ptr, workers_, state}; + EVMExecutor executor{chain_config, workers_, state}; std::shared_ptr ibs_tracer = std::make_shared(state_addresses); @@ -1457,16 +1452,14 @@ Task TraceCallExecutor::trace_deploy_transaction(const silkwo SILK_TRACE << "trace_deploy_transaction: block_number: " << std::dec << block_number << " #txns: " << transactions.size(); - const auto chain_config_ptr = co_await chain_storage_.read_chain_config(); - ensure(chain_config_ptr.has_value(), "cannot read chain config"); - + const auto chain_config = co_await chain_storage_.read_chain_config(); auto current_executor = co_await boost::asio::this_coro::executor; const auto deploy_result = co_await async_task(workers_.executor(), [&]() -> TraceDeployResult { auto state = tx_.create_state(current_executor, chain_storage_, block_number - 1); silkworm::IntraBlockState initial_ibs{*state}; auto curr_state = tx_.create_state(current_executor, chain_storage_, block_number - 1); - EVMExecutor executor{*chain_config_ptr, workers_, curr_state}; + EVMExecutor executor{chain_config, workers_, curr_state}; TraceDeployResult result; @@ -1515,15 +1508,13 @@ Task TraceCallExecutor::trace_transaction_entries(const Tran const auto& block = transaction_with_block.block_with_hash->block; const auto block_number = block.header.number; - const auto chain_config_ptr = co_await chain_storage_.read_chain_config(); - ensure(chain_config_ptr.has_value(), "cannot read chain config"); - + const auto chain_config = co_await chain_storage_.read_chain_config(); auto current_executor = co_await boost::asio::this_coro::executor; const auto trace_result = co_await async_task(workers_.executor(), [&]() -> TraceEntriesResult { auto state = tx_.create_state(current_executor, chain_storage_, block_number - 1); silkworm::IntraBlockState initial_ibs{*state}; auto curr_state = tx_.create_state(current_executor, chain_storage_, block_number - 1); - EVMExecutor executor{*chain_config_ptr, workers_, curr_state}; + EVMExecutor executor{chain_config, workers_, curr_state}; executor.call_first_n(block, transaction_with_block.transaction.transaction_index); @@ -1542,16 +1533,14 @@ Task TraceCallExecutor::trace_transaction_error(const TransactionWi const auto& block = transaction_with_block.block_with_hash->block; const auto block_number = block.header.number; - const auto chain_config_ptr = co_await chain_storage_.read_chain_config(); - ensure(chain_config_ptr.has_value(), "cannot read chain config"); - + const auto chain_config = co_await chain_storage_.read_chain_config(); auto current_executor = co_await boost::asio::this_coro::executor; const auto trace_error = co_await async_task(workers_.executor(), [&]() -> std::string { auto state = tx_.create_state(current_executor, chain_storage_, block_number - 1); silkworm::IntraBlockState initial_ibs{*state}; auto curr_state = tx_.create_state(current_executor, chain_storage_, block_number - 1); - EVMExecutor executor{*chain_config_ptr, workers_, curr_state}; + EVMExecutor executor{chain_config, workers_, curr_state}; executor.call_first_n(block, transaction_with_block.transaction.transaction_index); @@ -1572,16 +1561,14 @@ Task TraceCallExecutor::trace_operations(const Transactio const auto& block = transaction_with_block.block_with_hash->block; auto block_number = block.header.number; - const auto chain_config_ptr = co_await chain_storage_.read_chain_config(); - ensure(chain_config_ptr.has_value(), "cannot read chain config"); - + const auto chain_config = co_await chain_storage_.read_chain_config(); auto current_executor = co_await boost::asio::this_coro::executor; const auto trace_op_result = co_await async_task(workers_.executor(), [&]() -> TraceOperationsResult { auto state = tx_.create_state(current_executor, chain_storage_, block_number - 1); silkworm::IntraBlockState initial_ibs{*state}; auto curr_state = tx_.create_state(current_executor, chain_storage_, block_number - 1); - EVMExecutor executor{*chain_config_ptr, workers_, curr_state}; + EVMExecutor executor{chain_config, workers_, curr_state}; executor.call_first_n(block, transaction_with_block.transaction.transaction_index); @@ -1604,16 +1591,14 @@ Task TraceCallExecutor::trace_touch_block(const silkworm::BlockWithHash& b auto block_number = block.header.number; auto& hash = block_with_hash.hash; - const auto chain_config_ptr = co_await chain_storage_.read_chain_config(); - ensure(chain_config_ptr.has_value(), "cannot read chain config"); - + const auto chain_config = co_await chain_storage_.read_chain_config(); auto current_executor = co_await boost::asio::this_coro::executor; const bool result = co_await async_task(workers_.executor(), [&]() -> bool { auto state = tx_.create_state(current_executor, chain_storage_, block_number - 1); silkworm::IntraBlockState initial_ibs{*state}; auto curr_state = tx_.create_state(current_executor, chain_storage_, block_number - 1); - EVMExecutor executor{*chain_config_ptr, workers_, curr_state}; + EVMExecutor executor{chain_config, workers_, curr_state}; for (size_t i = 0; i < block.transactions.size(); i++) { auto tracer = std::make_shared(address, initial_ibs); @@ -1706,9 +1691,7 @@ Task TraceCallExecutor::execute( << " index: " << std::dec << index << " config: " << config; - const auto chain_config_ptr = co_await chain_storage_.read_chain_config(); - ensure(chain_config_ptr.has_value(), "cannot read chain config"); - + const auto chain_config = co_await chain_storage_.read_chain_config(); auto current_executor = co_await boost::asio::this_coro::executor; const auto trace_call_result = co_await async_task(workers_.executor(), [&]() -> TraceCallResult { auto state = tx_.create_state(current_executor, chain_storage_, block_number); @@ -1720,7 +1703,7 @@ Task TraceCallExecutor::execute( tracers.push_back(tracer); auto curr_state = tx_.create_state(current_executor, chain_storage_, block_number); - EVMExecutor executor{*chain_config_ptr, workers_, curr_state}; + EVMExecutor executor{chain_config, workers_, curr_state}; for (std::size_t idx{0}; idx < transaction.transaction_index; idx++) { silkworm::Transaction txn{block.transactions[idx]}; const auto execution_result = executor.call(block, txn, tracers, /*refund=*/true, /*gas_bailout=*/true); diff --git a/silkworm/rpc/core/rawdb/chain.cpp b/silkworm/rpc/core/rawdb/chain.cpp index db67869908..8cc5bdb8e2 100644 --- a/silkworm/rpc/core/rawdb/chain.cpp +++ b/silkworm/rpc/core/rawdb/chain.cpp @@ -75,10 +75,11 @@ Task read_head_header_hash(ethdb::Transaction& tx) { const silkworm::Bytes kHeadHeaderKey = silkworm::bytes_of_string(db::table::kHeadHeaderName); const auto value = co_await tx.get_one(db::table::kHeadHeaderName, kHeadHeaderKey); if (value.empty()) { - throw std::invalid_argument{"empty head header hash value in read_head_header_hash"}; + throw std::runtime_error{"empty head header hash value in read_head_header_hash"}; } const auto head_header_hash{silkworm::to_bytes32(value)}; SILK_DEBUG << "head header hash: " << silkworm::to_hex(head_header_hash); co_return head_header_hash; } + } // namespace silkworm::rpc::core::rawdb diff --git a/silkworm/rpc/json/types.cpp b/silkworm/rpc/json/types.cpp index 6795e51d38..2b6ee53f39 100644 --- a/silkworm/rpc/json/types.cpp +++ b/silkworm/rpc/json/types.cpp @@ -164,7 +164,7 @@ std::string to_quantity(uint64_t number) { return "0x" + to_hex_no_leading_zeros(number); } -std::string to_quantity(intx::uint256 number) { +std::string to_quantity(const intx::uint256& number) { if (number == 0) { return "0x0"; } diff --git a/silkworm/rpc/json/types.hpp b/silkworm/rpc/json/types.hpp index c57885dbeb..7d4b48df44 100644 --- a/silkworm/rpc/json/types.hpp +++ b/silkworm/rpc/json/types.hpp @@ -119,7 +119,7 @@ std::string to_hex(uint64_t number); std::string to_hex_no_leading_zeros(uint64_t number); std::string to_hex_no_leading_zeros(silkworm::ByteView bytes); std::string to_quantity(uint64_t number); -std::string to_quantity(intx::uint256 number); +std::string to_quantity(const intx::uint256& number); std::string to_quantity(silkworm::ByteView bytes); void to_quantity(std::span hex_bytes, uint64_t number); diff --git a/silkworm/rpc/storage/chain_storage.hpp b/silkworm/rpc/storage/chain_storage.hpp index 63a3bb3094..9f4bcf261f 100644 --- a/silkworm/rpc/storage/chain_storage.hpp +++ b/silkworm/rpc/storage/chain_storage.hpp @@ -16,8 +16,6 @@ #pragma once -#include - #include #include @@ -33,7 +31,7 @@ class ChainStorage { virtual ~ChainStorage() = default; //! Read the current chain configuration parameters - [[nodiscard]] virtual Task> read_chain_config() const = 0; + [[nodiscard]] virtual Task read_chain_config() const = 0; //! Get the highest block number [[nodiscard]] virtual Task highest_block_number() const = 0; diff --git a/silkworm/rpc/storage/local_chain_storage.cpp b/silkworm/rpc/storage/local_chain_storage.cpp index 1a025b3982..52bec2ec27 100644 --- a/silkworm/rpc/storage/local_chain_storage.cpp +++ b/silkworm/rpc/storage/local_chain_storage.cpp @@ -25,8 +25,12 @@ namespace silkworm::rpc { LocalChainStorage::LocalChainStorage(db::ROTxn& txn) : data_model_{txn} {} -Task> LocalChainStorage::read_chain_config() const { - co_return data_model_.read_chain_config(); +Task LocalChainStorage::read_chain_config() const { + const auto chain_config{data_model_.read_chain_config()}; + if (!chain_config) { + throw std::runtime_error{"empty chain config data in storage"}; + } + co_return *chain_config; } Task LocalChainStorage::highest_block_number() const { diff --git a/silkworm/rpc/storage/local_chain_storage.hpp b/silkworm/rpc/storage/local_chain_storage.hpp index 5e85f7da1a..07279be7dc 100644 --- a/silkworm/rpc/storage/local_chain_storage.hpp +++ b/silkworm/rpc/storage/local_chain_storage.hpp @@ -30,7 +30,7 @@ class LocalChainStorage : public ChainStorage { explicit LocalChainStorage(db::ROTxn& txn); ~LocalChainStorage() override = default; - [[nodiscard]] Task> read_chain_config() const override; + [[nodiscard]] Task read_chain_config() const override; [[nodiscard]] Task highest_block_number() const override; @@ -42,9 +42,7 @@ class LocalChainStorage : public ChainStorage { Task read_block(BlockNum number, bool read_senders, silkworm::Block& block) const override; [[nodiscard]] Task> read_header(BlockNum number, HashAsArray hash) const override; - [[nodiscard]] Task> read_header(BlockNum number, const Hash& hash) const override; - [[nodiscard]] Task> read_header(const Hash& hash) const override; [[nodiscard]] Task> read_sibling_headers(BlockNum number) const override; diff --git a/silkworm/rpc/storage/remote_chain_storage.cpp b/silkworm/rpc/storage/remote_chain_storage.cpp index ccfdfa4c37..5067a2e287 100644 --- a/silkworm/rpc/storage/remote_chain_storage.cpp +++ b/silkworm/rpc/storage/remote_chain_storage.cpp @@ -33,7 +33,7 @@ RemoteChainStorage::RemoteChainStorage(ethdb::Transaction& tx, block_provider_{std::move(block_provider)}, block_number_from_txn_hash_provider_{std::move(block_number_from_txn_hash_provider)} {} -Task> RemoteChainStorage::read_chain_config() const { +Task RemoteChainStorage::read_chain_config() const { const auto genesis_block_hash{co_await core::rawdb::read_canonical_block_hash(tx_, kEarliestBlockNumber)}; SILK_DEBUG << "rawdb::read_chain_config genesis_block_hash: " << to_hex(genesis_block_hash); const ByteView genesis_block_hash_bytes{genesis_block_hash.bytes, kHashLength}; @@ -45,8 +45,11 @@ Task> RemoteChainStorage::read_chain_config() const { const auto json_config = nlohmann::json::parse(data.begin(), data.end()); SILK_TRACE << "rawdb::read_chain_config chain config JSON: " << json_config.dump(); std::optional chain_config = ChainConfig::from_json(json_config); + if (!chain_config) { + throw std::runtime_error{"invalid chain config JSON in read_chain_config"}; + } chain_config->genesis_hash = genesis_block_hash; - co_return chain_config; + co_return *chain_config; } Task RemoteChainStorage::highest_block_number() const { diff --git a/silkworm/rpc/storage/remote_chain_storage.hpp b/silkworm/rpc/storage/remote_chain_storage.hpp index 49f364bb49..2a54b69e5a 100644 --- a/silkworm/rpc/storage/remote_chain_storage.hpp +++ b/silkworm/rpc/storage/remote_chain_storage.hpp @@ -38,7 +38,7 @@ class RemoteChainStorage : public ChainStorage { BlockNumberFromTxnHashProvider block_number_from_txn_hash_provider); ~RemoteChainStorage() override = default; - [[nodiscard]] Task> read_chain_config() const override; + [[nodiscard]] Task read_chain_config() const override; [[nodiscard]] Task highest_block_number() const override; diff --git a/silkworm/rpc/storage/remote_chain_storage_test.cpp b/silkworm/rpc/storage/remote_chain_storage_test.cpp index 54b0171641..c7fc9e97b4 100644 --- a/silkworm/rpc/storage/remote_chain_storage_test.cpp +++ b/silkworm/rpc/storage/remote_chain_storage_test.cpp @@ -86,10 +86,8 @@ TEST_CASE_METHOD(RemoteChainStorageTest, "read_chain_config") { co_return kChainConfig; })); const auto chain_config = spawn_and_wait(storage.read_chain_config()); - CHECK(chain_config.has_value()); - if (chain_config) { - CHECK(chain_config->genesis_hash == 0x439816753229fc0736bf86a5048de4bc9fcdede8c91dadf88c828c76b2281dff_bytes32); - CHECK(chain_config->to_json() == R"({ + CHECK(chain_config.genesis_hash == 0x439816753229fc0736bf86a5048de4bc9fcdede8c91dadf88c828c76b2281dff_bytes32); + CHECK(chain_config.to_json() == R"({ "berlinBlock":12244000, "byzantiumBlock":4370000, "chainId":1, @@ -105,7 +103,6 @@ TEST_CASE_METHOD(RemoteChainStorageTest, "read_chain_config") { "muirGlacierBlock":9200000, "petersburgBlock":7280000 })"_json); - } } } diff --git a/silkworm/rpc/test_util/mock_chain_storage.hpp b/silkworm/rpc/test_util/mock_chain_storage.hpp index 77d8dd9efe..d1c9e9ddcf 100644 --- a/silkworm/rpc/test_util/mock_chain_storage.hpp +++ b/silkworm/rpc/test_util/mock_chain_storage.hpp @@ -32,9 +32,7 @@ namespace silkworm::rpc::test { class MockChainStorage : public silkworm::rpc::ChainStorage { public: - MOCK_METHOD((Task>), read_chain_config, (), (const override)); - - MOCK_METHOD((Task>), read_chain_id, (), (const override)); + MOCK_METHOD((Task), read_chain_config, (), (const override)); MOCK_METHOD((Task), highest_block_number, (), (const override));