Skip to content

Commit d840a60

Browse files
authored
rpcdaemon: impl API debug_getRawReceipts (#2627)
1 parent a461f8a commit d840a60

File tree

15 files changed

+123
-69
lines changed

15 files changed

+123
-69
lines changed

.github/workflows/rpc-integration-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
- name: Checkout RPC Tests Repository & Install Requirements
3434
run: |
3535
rm -rf ${{runner.workspace}}/rpc-tests
36-
git -c advice.detachedHead=false clone --depth 1 --branch v1.31.0 https://github.com/erigontech/rpc-tests ${{runner.workspace}}/rpc-tests
36+
git -c advice.detachedHead=false clone --depth 1 --branch v1.32.0 https://github.com/erigontech/rpc-tests ${{runner.workspace}}/rpc-tests
3737
cd ${{runner.workspace}}/rpc-tests
3838
pip3 install -r requirements.txt --break-system-packages
3939

docs/JSON-RPC-API.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ The following table shows the current [JSON RPC API](https://eth.wiki/json-rpc/A
9898
| debug_getBadBlocks | No | data not available | | |
9999
| debug_getRawBlock | Yes | can be optimized to avoid re-encoding | | |
100100
| debug_getRawHeader | Yes | | | |
101-
| debug_getRawReceipts | No | see eth_getBlockReceipts | | |
101+
| debug_getRawReceipts | Yes | | | |
102102
| debug_getRawTransaction | Yes | | | |
103103
| debug_storageRangeAt | Yes | | Yes | |
104104
| debug_traceBlockByHash | Yes | uses JSON streaming | Yes | |

silkworm/rpc/commands/debug_api.cpp

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@
2828
#include <silkworm/core/common/util.hpp>
2929
#include <silkworm/core/types/address.hpp>
3030
#include <silkworm/core/types/evmc_bytes32.hpp>
31+
#include <silkworm/core/types/receipt.hpp>
3132
#include <silkworm/db/tables.hpp>
3233
#include <silkworm/infra/common/log.hpp>
3334
#include <silkworm/rpc/common/async_task.hpp>
3435
#include <silkworm/rpc/core/account_dumper.hpp>
3536
#include <silkworm/rpc/core/block_reader.hpp>
3637
#include <silkworm/rpc/core/cached_chain.hpp>
3738
#include <silkworm/rpc/core/evm_debug.hpp>
39+
#include <silkworm/rpc/core/receipts.hpp>
3840
#include <silkworm/rpc/core/storage_walker.hpp>
3941
#include <silkworm/rpc/json/types.hpp>
4042
#include <silkworm/rpc/protocol/errors.hpp>
@@ -113,7 +115,6 @@ Task<void> DebugRpcApi::handle_debug_get_modified_accounts_by_number(const nlohm
113115
reply = make_json_error(request, kInvalidParams, error_msg);
114116
co_return;
115117
}
116-
117118
auto start_block_id = params[0].get<std::string>();
118119
auto end_block_id = start_block_id;
119120
if (params.size() == 2) {
@@ -162,7 +163,6 @@ Task<void> DebugRpcApi::handle_debug_get_modified_accounts_by_hash(const nlohman
162163
reply = make_json_error(request, kInvalidParams, error_msg);
163164
co_return;
164165
}
165-
166166
const auto start_hash = params[0].get<evmc::bytes32>();
167167
auto end_hash = start_hash;
168168
if (params.size() == 2) {
@@ -213,13 +213,11 @@ Task<void> DebugRpcApi::handle_debug_storage_range_at(const nlohmann::json& requ
213213
reply = make_json_error(request, kInvalidParams, error_msg);
214214
co_return;
215215
}
216-
217216
auto block_hash = params[0].get<evmc::bytes32>();
218217
auto tx_index = params[1].get<std::uint64_t>();
219218
auto address = params[2].get<evmc::address>();
220219
auto start_key = params[3].get<evmc::bytes32>();
221220
auto max_result = params[4].get<std::uint64_t>();
222-
223221
SILK_DEBUG << "block_hash: 0x" << silkworm::to_hex(block_hash)
224222
<< " tx_index: " << tx_index
225223
<< " address: " << address
@@ -298,11 +296,9 @@ Task<void> DebugRpcApi::handle_debug_account_at(const nlohmann::json& request, n
298296
reply = make_json_error(request, kInvalidParams, error_msg);
299297
co_return;
300298
}
301-
302299
auto block_hash = params[0].get<evmc::bytes32>();
303300
auto tx_index = params[1].get<uint64_t>();
304301
auto address = params[2].get<evmc::address>();
305-
306302
SILK_DEBUG << "block_hash: 0x" << silkworm::to_hex(block_hash)
307303
<< " tx_index: " << tx_index
308304
<< " address: " << address;
@@ -389,16 +385,13 @@ Task<void> DebugRpcApi::handle_debug_trace_transaction(const nlohmann::json& req
389385
SILK_ERROR << error_msg;
390386
const auto reply = make_json_error(request, kInvalidParams, error_msg);
391387
stream.write_json(reply);
392-
393388
co_return;
394389
}
395-
auto transaction_hash = params[0].get<evmc::bytes32>();
396-
390+
const auto transaction_hash = params[0].get<evmc::bytes32>();
397391
debug::DebugConfig config;
398392
if (params.size() > 1) {
399393
config = params[1].get<debug::DebugConfig>();
400394
}
401-
402395
SILK_DEBUG << "transaction_hash: " << silkworm::to_hex(transaction_hash) << " config: {" << config << "}";
403396

404397
stream.open_object();
@@ -434,7 +427,6 @@ Task<void> DebugRpcApi::handle_debug_trace_call(const nlohmann::json& request, j
434427
SILK_ERROR << error_msg;
435428
const auto reply = make_json_error(request, kInvalidParams, error_msg);
436429
stream.write_json(reply);
437-
438430
co_return;
439431
}
440432
const auto call = params[0].get<Call>();
@@ -443,7 +435,6 @@ Task<void> DebugRpcApi::handle_debug_trace_call(const nlohmann::json& request, j
443435
if (params.size() > 2) {
444436
config = params[2].get<debug::DebugConfig>();
445437
}
446-
447438
SILK_DEBUG << "call: " << call << " block_num_or_hash: " << block_num_or_hash << " config: {" << config << "}";
448439

449440
stream.open_object();
@@ -489,37 +480,29 @@ Task<void> DebugRpcApi::handle_debug_trace_call_many(const nlohmann::json& reque
489480
SILK_ERROR << error_msg << request.dump();
490481
const auto reply = make_json_error(request, kInvalidParams, error_msg);
491482
stream.write_json(reply);
492-
493483
co_return;
494484
}
495-
496485
const auto& params = request["params"];
497486
if (params.size() < 2) {
498487
auto error_msg = "invalid debug_traceCallMany params: " + params.dump();
499488
SILK_ERROR << error_msg;
500489
const auto reply = make_json_error(request, kInvalidParams, error_msg);
501490
stream.write_json(reply);
502-
503491
co_return;
504492
}
505493
const auto bundles = params[0].get<Bundles>();
506-
507494
if (bundles.empty()) {
508495
const auto error_msg = "invalid debug_traceCallMany bundle list: " + params.dump();
509496
SILK_ERROR << error_msg;
510497
const auto reply = make_json_error(request, kInvalidParams, error_msg);
511498
stream.write_json(reply);
512-
513499
co_return;
514500
}
515-
516501
const auto simulation_context = params[1].get<SimulationContext>();
517-
518502
debug::DebugConfig config;
519503
if (params.size() > 2) {
520504
config = params[2].get<debug::DebugConfig>();
521505
}
522-
523506
SILK_DEBUG << "bundles: " << bundles << " simulation_context: " << simulation_context << " config: {" << config << "}";
524507

525508
stream.open_object();
@@ -553,7 +536,6 @@ Task<void> DebugRpcApi::handle_debug_trace_block_by_number(const nlohmann::json&
553536
stream.write_json(reply);
554537
co_return;
555538
}
556-
557539
BlockNum block_num{0};
558540
if (params[0].is_string()) {
559541
const auto value = params[0].get<std::string>();
@@ -565,12 +547,10 @@ Task<void> DebugRpcApi::handle_debug_trace_block_by_number(const nlohmann::json&
565547
} else {
566548
block_num = params[0].get<BlockNum>();
567549
}
568-
569550
debug::DebugConfig config;
570551
if (params.size() > 1) {
571552
config = params[1].get<debug::DebugConfig>();
572553
}
573-
574554
SILK_DEBUG << "block_num: " << block_num << " config: {" << config << "}";
575555

576556
stream.open_object();
@@ -616,12 +596,10 @@ Task<void> DebugRpcApi::handle_debug_trace_block_by_hash(const nlohmann::json& r
616596
co_return;
617597
}
618598
const auto block_hash = params[0].get<evmc::bytes32>();
619-
620599
debug::DebugConfig config;
621600
if (params.size() > 1) {
622601
config = params[1].get<debug::DebugConfig>();
623602
}
624-
625603
SILK_DEBUG << "block_hash: " << silkworm::to_hex(block_hash) << " config: {" << config << "}";
626604

627605
stream.open_object();
@@ -693,7 +671,6 @@ Task<std::set<evmc::address>> get_modified_accounts(db::kv::api::Transaction& tx
693671

694672
Task<void> DebugRpcApi::handle_debug_get_raw_block(const nlohmann::json& request, nlohmann::json& reply) {
695673
const auto& params = request["params"];
696-
697674
if (params.size() != 1) {
698675
auto error_msg = "invalid debug_getRawBlock params: " + params.dump();
699676
SILK_ERROR << error_msg;
@@ -730,6 +707,66 @@ Task<void> DebugRpcApi::handle_debug_get_raw_block(const nlohmann::json& request
730707
co_await tx->close(); // RAII not (yet) available with coroutines
731708
}
732709

710+
Task<void> DebugRpcApi::handle_debug_get_raw_receipts(const nlohmann::json& request, nlohmann::json& reply) {
711+
const auto& params = request["params"];
712+
if (params.size() != 1) {
713+
auto error_msg = "invalid debug_getRawReceipts params: " + params.dump();
714+
SILK_ERROR << error_msg;
715+
reply = make_json_error(request, kInvalidParams, error_msg);
716+
co_return;
717+
}
718+
const auto block_num_or_hash = params[0].get<BlockNumOrHash>();
719+
720+
auto tx = co_await database_->begin();
721+
722+
try {
723+
const auto chain_storage = tx->create_storage();
724+
const auto block_with_hash = co_await core::read_block_by_block_num_or_hash(*block_cache_, *chain_storage, *tx, block_num_or_hash);
725+
if (!block_with_hash) {
726+
reply = make_json_content(request, nullptr);
727+
co_await tx->close(); // RAII not (yet) available with coroutines
728+
co_return;
729+
}
730+
731+
auto receipts = co_await core::get_receipts(*tx, *block_with_hash, *chain_storage, workers_, false);
732+
SILK_TRACE << "#receipts: " << receipts.size();
733+
734+
std::vector<std::string> raw_receipts;
735+
for (auto& rpc_receipt : receipts) {
736+
silkworm::Receipt core_receipt{
737+
.type = rpc_receipt.type,
738+
.success = rpc_receipt.success,
739+
.cumulative_gas_used = rpc_receipt.cumulative_gas_used,
740+
.bloom = rpc_receipt.bloom,
741+
};
742+
for (auto& log : rpc_receipt.logs) {
743+
core_receipt.logs.push_back(silkworm::Log{
744+
.address = log.address,
745+
.topics = std::move(log.topics),
746+
.data = std::move(log.data),
747+
});
748+
}
749+
750+
Bytes receipt_rlp;
751+
rlp::encode(receipt_rlp, core_receipt);
752+
753+
raw_receipts.push_back(silkworm::to_hex(receipt_rlp, /*with_prefix=*/true));
754+
}
755+
reply = make_json_content(request, raw_receipts);
756+
} catch (const std::invalid_argument& iv) {
757+
SILK_ERROR << "exception: " << iv.what() << " processing request: " << request.dump();
758+
reply = make_json_error(request, kServerError, iv.what());
759+
} catch (const std::exception& e) {
760+
SILK_ERROR << "exception: " << e.what() << " processing request: " << request.dump();
761+
reply = make_json_error(request, kInternalError, e.what());
762+
} catch (...) {
763+
SILK_ERROR << "unexpected exception processing request: " << request.dump();
764+
reply = make_json_error(request, kServerError, "unexpected exception");
765+
}
766+
767+
co_await tx->close(); // RAII not (yet) available with coroutines
768+
}
769+
733770
Task<void> DebugRpcApi::handle_debug_get_raw_header(const nlohmann::json& request, nlohmann::json& reply) {
734771
const auto& params = request["params"];
735772
if (params.size() != 1) {
@@ -777,7 +814,7 @@ Task<void> DebugRpcApi::handle_debug_get_raw_transaction(const nlohmann::json& r
777814
reply = make_json_error(request, kInvalidParams, error_msg);
778815
co_return;
779816
}
780-
auto transaction_hash = params[0].get<evmc::bytes32>();
817+
const auto transaction_hash = params[0].get<evmc::bytes32>();
781818
SILK_DEBUG << "transaction_hash: " << silkworm::to_hex(transaction_hash);
782819

783820
auto tx = co_await database_->begin();

silkworm/rpc/commands/debug_api.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class DebugRpcApi {
7070
Task<void> handle_debug_get_raw_block(const nlohmann::json& request, nlohmann::json& reply);
7171
Task<void> handle_debug_get_raw_header(const nlohmann::json& request, nlohmann::json& reply);
7272
Task<void> handle_debug_get_raw_transaction(const nlohmann::json& request, nlohmann::json& reply);
73+
Task<void> handle_debug_get_raw_receipts(const nlohmann::json& request, nlohmann::json& reply);
7374

7475
private:
7576
boost::asio::io_context& ioc_;

silkworm/rpc/commands/rpc_api_table.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ void RpcApiTable::add_debug_handlers() {
105105
method_handlers_[json_rpc::method::k_debug_getRawBlock] = &commands::RpcApi::handle_debug_get_raw_block;
106106
method_handlers_[json_rpc::method::k_debug_getRawHeader] = &commands::RpcApi::handle_debug_get_raw_header;
107107
method_handlers_[json_rpc::method::k_debug_getRawTransaction] = &commands::RpcApi::handle_debug_get_raw_transaction;
108+
method_handlers_[json_rpc::method::k_debug_getRawReceipts] = &commands::RpcApi::handle_debug_get_raw_receipts;
108109

109110
stream_handlers_[json_rpc::method::k_debug_traceCall] = &commands::RpcApi::handle_debug_trace_call;
110111
stream_handlers_[json_rpc::method::k_debug_traceCallMany] = &commands::RpcApi::handle_debug_trace_call_many;

silkworm/rpc/core/evm_executor.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
#include <silkworm/core/common/bytes_to_string.hpp>
2727
#include <silkworm/core/common/util.hpp>
2828
#include <silkworm/core/protocol/intrinsic_gas.hpp>
29-
#include <silkworm/core/protocol/param.hpp>
3029
#include <silkworm/core/types/address.hpp>
3130
#include <silkworm/infra/common/log.hpp>
3231
#include <silkworm/rpc/common/async_task.hpp>
@@ -267,18 +266,18 @@ ExecutionResult EVMExecutor::call_with_receipt(
267266

268267
const auto exec_result = call(block, txn, tracers, refund, gas_bailout);
269268

270-
const auto& logs = execution_processor_.intra_block_state().logs();
269+
auto& logs = execution_processor_.intra_block_state().logs();
271270

272271
receipt.success = exec_result.success();
273272
receipt.bloom = logs_bloom(logs);
274273
receipt.gas_used = txn.gas_limit - exec_result.gas_left;
275-
receipt.type = static_cast<uint8_t>(txn.type);
276-
for (const auto& log : logs) {
274+
receipt.type = txn.type;
275+
for (auto& log : logs) {
277276
Log rpc_log;
278277
rpc_log.address = log.address;
279-
rpc_log.data = log.data;
280-
rpc_log.topics = log.topics;
281-
receipt.logs.push_back(rpc_log);
278+
rpc_log.data = std::move(log.data);
279+
rpc_log.topics = std::move(log.topics);
280+
receipt.logs.push_back(std::move(rpc_log));
282281
}
283282

284283
SILK_DEBUG << "EVMExecutor::call call_result: " << exec_result.error_message() << " #data: " << exec_result.data.size() << " end";

0 commit comments

Comments
 (0)