Skip to content

Commit

Permalink
rpcdaemon: rework on eth_getUncleByBlockHashAndIndex and eth_getUncle…
Browse files Browse the repository at this point in the history
…ByBlockNumberAndIndex for snapshot (#1354)
  • Loading branch information
lupin012 authored Jul 22, 2023
1 parent 3f87bf7 commit f439b52
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 63 deletions.
82 changes: 52 additions & 30 deletions silkworm/silkrpc/commands/eth_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ awaitable<void> EthereumRpcApi::handle_eth_get_block_by_hash(const nlohmann::jso
ethdb::TransactionDatabase tx_database{*tx};

const auto chain_storage = tx->create_storage(tx_database, backend_);
const auto block_with_hash = co_await core::read_block_by_hash(*block_cache_, chain_storage, block_hash);
const auto block_with_hash = co_await core::read_block_by_hash(*block_cache_, *chain_storage, block_hash);
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)};
Expand All @@ -249,6 +249,8 @@ awaitable<void> EthereumRpcApi::handle_eth_get_block_by_hash(const nlohmann::jso
} else {
reply = make_json_content(request["id"], {});
}
} catch (const std::invalid_argument& iv) {
reply = make_json_content(request["id"], {});
} catch (const std::exception& e) {
SILK_ERROR << "exception: " << e.what() << " processing request: " << request.dump();
reply = make_json_error(request["id"], 100, e.what());
Expand Down Expand Up @@ -280,7 +282,7 @@ awaitable<void> EthereumRpcApi::handle_eth_get_block_by_number(const nlohmann::j
ethdb::TransactionDatabase tx_database{*tx};
const auto block_number = co_await core::get_block_number(block_id, tx_database);
const auto chain_storage = tx->create_storage(tx_database, backend_);
const auto block_with_hash = co_await core::read_block_by_number(*block_cache_, chain_storage, tx_database, block_number);
const auto block_with_hash = co_await core::read_block_by_number(*block_cache_, *chain_storage, tx_database, 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(), "no difficulty for block number=" + std::to_string(block_number));
Expand All @@ -290,6 +292,8 @@ awaitable<void> EthereumRpcApi::handle_eth_get_block_by_number(const nlohmann::j
} else {
reply = make_json_content(request["id"], {});
}
} catch (const std::invalid_argument& iv) {
reply = make_json_content(request["id"], {});
} catch (const std::exception& e) {
SILK_ERROR << "exception: " << e.what() << " processing request: " << request.dump();
reply = make_json_error(request["id"], 100, e.what());
Expand Down Expand Up @@ -319,12 +323,14 @@ awaitable<void> EthereumRpcApi::handle_eth_get_block_transaction_count_by_hash(c
try {
ethdb::TransactionDatabase tx_database{*tx};
const auto chain_storage = tx->create_storage(tx_database, backend_);
const auto block_with_hash = co_await core::read_block_by_hash(*block_cache_, chain_storage, block_hash);
const auto block_with_hash = co_await core::read_block_by_hash(*block_cache_, *chain_storage, block_hash);
uint64_t tx_count{0};
if (block_with_hash) {
tx_count = block_with_hash->block.transactions.size();
}
reply = make_json_content(request["id"], to_quantity(tx_count));
} catch (const std::invalid_argument& iv) {
reply = make_json_content(request["id"], 0x0);
} catch (const std::exception& e) {
SILK_ERROR << "exception: " << e.what() << " processing request: " << request.dump();
reply = make_json_error(request["id"], 100, e.what());
Expand Down Expand Up @@ -356,12 +362,14 @@ awaitable<void> EthereumRpcApi::handle_eth_get_block_transaction_count_by_number

const auto block_number = co_await core::get_block_number(block_id, tx_database);
const auto chain_storage = tx->create_storage(tx_database, backend_);
const auto block_with_hash = co_await core::read_block_by_number(*block_cache_, chain_storage, tx_database, block_number);
const auto block_with_hash = co_await core::read_block_by_number(*block_cache_, *chain_storage, tx_database, block_number);
uint64_t tx_count{0};
if (block_with_hash) {
tx_count = block_with_hash->block.transactions.size();
}
reply = make_json_content(request["id"], to_quantity(tx_count));
} catch (const std::invalid_argument& iv) {
reply = make_json_content(request["id"], 0x0);
} catch (const std::exception& e) {
SILK_ERROR << "exception: " << e.what() << " processing request: " << request.dump();
reply = make_json_error(request["id"], 100, e.what());
Expand Down Expand Up @@ -391,24 +399,31 @@ awaitable<void> EthereumRpcApi::handle_eth_get_uncle_by_block_hash_and_index(con

try {
ethdb::TransactionDatabase tx_database{*tx};
const auto chain_storage = tx->create_storage(tx_database, backend_);

const auto block_with_hash = co_await core::read_block_by_hash(*block_cache_, tx_database, block_hash);
const auto ommers = block_with_hash->block.ommers;
const auto block_with_hash = co_await core::read_block_by_hash(*block_cache_, *chain_storage, block_hash);
if (block_with_hash) {
const auto ommers = block_with_hash->block.ommers;

const auto idx = std::stoul(index, nullptr, 16);
if (idx >= ommers.size()) {
SILK_WARN << "invalid_argument: index not found processing request: " << request.dump();
reply = make_json_content(request["id"], nullptr);
} else {
const auto block_number = block_with_hash->block.header.number;
const auto total_difficulty = co_await core::rawdb::read_total_difficulty(tx_database, block_hash, block_number);
const auto& uncle = ommers[idx];
const auto idx = std::stoul(index, nullptr, 16);
if (idx >= ommers.size()) {
SILK_WARN << "invalid_argument: index not found processing request: " << request.dump();
reply = make_json_content(request["id"], nullptr);
} else {
const auto block_number = block_with_hash->block.header.number;
const auto total_difficulty = co_await core::rawdb::read_total_difficulty(tx_database, block_hash, block_number);
const auto& uncle = ommers[idx];

silkworm::BlockWithHash uncle_block_with_hash{{{}, uncle}, uncle.hash()};
const Block uncle_block_with_hash_and_td{uncle_block_with_hash, total_difficulty};
silkworm::BlockWithHash uncle_block_with_hash{{{}, uncle}, uncle.hash()};
const Block uncle_block_with_hash_and_td{uncle_block_with_hash, total_difficulty};

reply = make_json_content(request["id"], uncle_block_with_hash_and_td);
reply = make_json_content(request["id"], uncle_block_with_hash_and_td);
}
} else {
reply = make_json_content(request["id"], {});
}
} catch (const std::invalid_argument& iv) {
reply = make_json_content(request["id"], {});
} catch (const std::exception& e) {
SILK_ERROR << "exception: " << e.what() << " processing request: " << request.dump();
reply = make_json_error(request["id"], 100, e.what());
Expand Down Expand Up @@ -438,24 +453,31 @@ awaitable<void> EthereumRpcApi::handle_eth_get_uncle_by_block_number_and_index(c

try {
ethdb::TransactionDatabase tx_database{*tx};
const auto chain_storage = tx->create_storage(tx_database, backend_);

const auto block_number = co_await core::get_block_number(block_id, tx_database);
const auto block_with_hash = co_await core::read_block_by_number(*block_cache_, tx_database, block_number);
const auto ommers = block_with_hash->block.ommers;
const auto block_with_hash = co_await core::read_block_by_number(*block_cache_, *chain_storage, tx_database, block_number);
if (block_with_hash) {
const auto ommers = block_with_hash->block.ommers;

const auto idx = std::stoul(index, nullptr, 16);
if (idx >= ommers.size()) {
SILK_WARN << "invalid_argument: index not found processing request: " << request.dump();
reply = make_json_content(request["id"], nullptr);
} else {
const auto total_difficulty = co_await core::rawdb::read_total_difficulty(tx_database, block_with_hash->hash, block_number);
const auto& uncle = ommers[idx];
const auto idx = std::stoul(index, nullptr, 16);
if (idx >= ommers.size()) {
SILK_WARN << "invalid_argument: index not found processing request: " << request.dump();
reply = make_json_content(request["id"], nullptr);
} else {
const auto total_difficulty = co_await core::rawdb::read_total_difficulty(tx_database, block_with_hash->hash, block_number);
const auto& uncle = ommers[idx];

silkworm::BlockWithHash uncle_block_with_hash{{{}, uncle}, uncle.hash()};
const Block uncle_block_with_hash_and_td{uncle_block_with_hash, total_difficulty};
silkworm::BlockWithHash uncle_block_with_hash{{{}, uncle}, uncle.hash()};
const Block uncle_block_with_hash_and_td{uncle_block_with_hash, total_difficulty};

reply = make_json_content(request["id"], uncle_block_with_hash_and_td);
reply = make_json_content(request["id"], uncle_block_with_hash_and_td);
}
} else {
reply = make_json_content(request["id"], {});
}
} catch (const std::invalid_argument& iv) {
reply = make_json_content(request["id"], {});
} catch (const std::exception& e) {
SILK_ERROR << "exception: " << e.what() << " processing request: " << request.dump();
reply = make_json_error(request["id"], 100, e.what());
Expand Down Expand Up @@ -1123,7 +1145,7 @@ awaitable<void> EthereumRpcApi::handle_eth_call(const nlohmann::json& request, s
const auto chain_config = lookup_chain_config(*chain_id);
const auto [block_number, is_latest_block] = co_await core::get_block_number(block_id, tx_database, /*latest_required=*/true);

const auto block_with_hash = co_await core::read_block_by_number(*block_cache_, chain_storage, tx_database, block_number);
const auto block_with_hash = co_await core::read_block_by_number(*block_cache_, *chain_storage, tx_database, block_number);
silkworm::Transaction txn{call.to_transaction()};

const core::rawdb::DatabaseReader& db_reader =
Expand Down
55 changes: 24 additions & 31 deletions silkworm/silkrpc/core/cached_chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ awaitable<std::shared_ptr<BlockWithHash>> read_block_by_number(BlockCache& cache
if (cached_block) {
co_return cached_block.value();
}
auto block_with_hash = co_await rawdb::read_block(reader, block_hash, block_number);
const auto block_with_hash = co_await rawdb::read_block(reader, block_hash, block_number);
if (block_with_hash->block.transactions.size() != 0) {
// don't save empty (without txs) blocks to cache, if block become non-canonical (not in main chain), we remove it's transactions,
// but block can in the future become canonical(inserted in main chain) with its transactions
Expand All @@ -36,38 +36,32 @@ awaitable<std::shared_ptr<BlockWithHash>> read_block_by_number(BlockCache& cache
co_return block_with_hash;
}

awaitable<std::shared_ptr<BlockWithHash>> read_block_by_number(BlockCache& cache, const std::shared_ptr<ChainStorage> storage, const rawdb::DatabaseReader& reader, uint64_t block_number) {
evmc::bytes32 block_hash;
try {
block_hash = co_await rawdb::read_canonical_block_hash(reader, block_number);
} catch (const std::invalid_argument& iv) {
co_return nullptr;
}
awaitable<std::shared_ptr<BlockWithHash>> read_block_by_number(BlockCache& cache, const ChainStorage& storage, const rawdb::DatabaseReader& reader, uint64_t block_number) {
auto block_hash = co_await rawdb::read_canonical_block_hash(reader, block_number);
const auto cached_block = cache.get(block_hash);
if (cached_block) {
co_return cached_block.value();
}
auto block_with_hash = std::make_shared<BlockWithHash>();
auto block_found = co_await storage->read_block(block_hash, block_with_hash->block);
if (block_found) {
block_with_hash->hash = block_with_hash->block.header.hash();
if (block_with_hash->block.transactions.size() != 0) {
// don't save empty (without txs) blocks to cache, if block become non-canonical (not in main chain), we remove it's transactions,
// but block can in the future become canonical(inserted in main chain) with its transactions
cache.insert(block_hash, block_with_hash);
}
co_return block_with_hash;
} else {
const auto block_with_hash = std::make_shared<BlockWithHash>();
const auto block_found = co_await storage.read_block(block_hash, block_with_hash->block);
if (!block_found) {
co_return nullptr;
}
block_with_hash->hash = block_with_hash->block.header.hash();
if (block_with_hash->block.transactions.size() != 0) {
// don't save empty (without txs) blocks to cache, if block become non-canonical (not in main chain), we remove it's transactions,
// but block can in the future become canonical(inserted in main chain) with its transactions
cache.insert(block_hash, block_with_hash);
}
co_return block_with_hash;
}

awaitable<std::shared_ptr<BlockWithHash>> read_block_by_hash(BlockCache& cache, const rawdb::DatabaseReader& reader, const evmc::bytes32& block_hash) {
const auto cached_block = cache.get(block_hash);
if (cached_block) {
co_return cached_block.value();
}
auto block_with_hash = co_await rawdb::read_block_by_hash(reader, block_hash);
const auto block_with_hash = co_await rawdb::read_block_by_hash(reader, block_hash);
if (block_with_hash->block.transactions.size() != 0) {
// don't save empty (without txs) blocks to cache, if block become non-canonical (not in main chain), we remove it's transactions,
// but block can in the future become canonical(inserted in main chain) with its transactions
Expand All @@ -76,24 +70,23 @@ awaitable<std::shared_ptr<BlockWithHash>> read_block_by_hash(BlockCache& cache,
co_return block_with_hash;
}

awaitable<std::shared_ptr<BlockWithHash>> read_block_by_hash(BlockCache& cache, const std::shared_ptr<ChainStorage> storage, const evmc::bytes32& block_hash) {
awaitable<std::shared_ptr<BlockWithHash>> read_block_by_hash(BlockCache& cache, const ChainStorage& storage, const evmc::bytes32& block_hash) {
const auto cached_block = cache.get(block_hash);
if (cached_block) {
co_return cached_block.value();
}
auto block_with_hash = std::make_shared<BlockWithHash>();
auto block_found = co_await storage->read_block(block_hash, block_with_hash->block);
if (block_found) {
block_with_hash->hash = block_with_hash->block.header.hash();
if (block_with_hash->block.transactions.size() != 0) {
// don't save empty (without txs) blocks to cache, if block become non-canonical (not in main chain), we remove it's transactions,
// but block can in the future become canonical(inserted in main chain) with its transactions
cache.insert(block_hash, block_with_hash);
}
co_return block_with_hash;
} else {
const auto block_found = co_await storage.read_block(block_hash, block_with_hash->block);
if (!block_found) {
co_return nullptr;
}
block_with_hash->hash = block_with_hash->block.header.hash();
if (block_with_hash->block.transactions.size() != 0) {
// don't save empty (without txs) blocks to cache, if block become non-canonical (not in main chain), we remove it's transactions,
// but block can in the future become canonical(inserted in main chain) with its transactions
cache.insert(block_hash, block_with_hash);
}
co_return block_with_hash;
}

awaitable<std::shared_ptr<BlockWithHash>> read_block_by_number_or_hash(BlockCache& cache, const rawdb::DatabaseReader& reader, const BlockNumberOrHash& bnoh) {
Expand Down
4 changes: 2 additions & 2 deletions silkworm/silkrpc/core/cached_chain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ namespace silkworm::rpc::core {
using boost::asio::awaitable;

awaitable<std::shared_ptr<BlockWithHash>> read_block_by_number(BlockCache& cache, const rawdb::DatabaseReader& reader, uint64_t block_number);
awaitable<std::shared_ptr<BlockWithHash>> read_block_by_number(BlockCache& cache, const std::shared_ptr<ChainStorage> storage, const rawdb::DatabaseReader& reader, uint64_t block_number);
awaitable<std::shared_ptr<BlockWithHash>> read_block_by_number(BlockCache& cache, const ChainStorage& storage, const rawdb::DatabaseReader& reader, uint64_t block_number);
awaitable<std::shared_ptr<BlockWithHash>> read_block_by_hash(BlockCache& cache, const rawdb::DatabaseReader& reader, const evmc::bytes32& block_hash);
awaitable<std::shared_ptr<BlockWithHash>> read_block_by_hash(BlockCache& cache, const std::shared_ptr<ChainStorage> storage, const evmc::bytes32& block_hash);
awaitable<std::shared_ptr<BlockWithHash>> read_block_by_hash(BlockCache& cache, const ChainStorage& storage, const evmc::bytes32& block_hash);
awaitable<std::shared_ptr<BlockWithHash>> read_block_by_number_or_hash(BlockCache& cache, const rawdb::DatabaseReader& reader, const BlockNumberOrHash& bnoh);
awaitable<BlockWithHash> read_block_by_transaction_hash(BlockCache& cache, const rawdb::DatabaseReader& reader, const evmc::bytes32& transaction_hash);
awaitable<std::optional<TransactionWithBlock>> read_transaction_by_hash(BlockCache& cache, const rawdb::DatabaseReader& reader, const evmc::bytes32& transaction_hash);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[
{
"request": {
"jsonrpc":"2.0",
"method":"eth_getUncleByBlockHashAndIndex",
"params":["0xffff72e6913a3879217169c6ba461114fa032d9510a56a409d3aab19f668e299","0x0"],
"id":1
},
"response": {
"jsonrpc":"2.0",
"id":1,
"result":null
}
}
]

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[
{
"request": {
"jsonrpc":"2.0",
"method":"eth_getUncleByBlockNumberAndIndex",
"params":["0xffffff", "0x0"],
"id":1
},
"response": {
"jsonrpc":"2.0",
"id":1,
"result":null
}
}
]

0 comments on commit f439b52

Please sign in to comment.