Skip to content
This repository has been archived by the owner on Jan 9, 2024. It is now read-only.

Exposing Engine_GetPayloadV1 #227

Merged
merged 47 commits into from
Feb 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
4793c9a
added engine_
Giulio2002 Jan 29, 2022
ad87b25
added engine_api_test
Giulio2002 Jan 29, 2022
c4ef951
added integration tests
Giulio2002 Jan 29, 2022
7ada83e
lint happy
Giulio2002 Jan 29, 2022
8c81133
Merge branch 'master' into get-payload-v1
Giulio2002 Jan 31, 2022
42ab07b
Merge branch 'master' into get-payload-v1
Giulio2002 Feb 2, 2022
8b76f72
added tests
Giulio2002 Feb 2, 2022
46d180d
lint
Giulio2002 Feb 2, 2022
5f0cdf5
resize
Giulio2002 Feb 2, 2022
fc09ede
clean up
Giulio2002 Feb 2, 2022
1c1b282
inheritance
Giulio2002 Feb 2, 2022
0e9a694
test
Giulio2002 Feb 3, 2022
22a8d97
diagnostic
Giulio2002 Feb 3, 2022
9aa8475
ops
Giulio2002 Feb 3, 2022
31b4bd8
lint
Giulio2002 Feb 3, 2022
b4581a4
happy gcc
Giulio2002 Feb 3, 2022
7b8d4b8
()
Giulio2002 Feb 3, 2022
b99c7a3
fixed coverage
Giulio2002 Feb 3, 2022
b9881d3
better coverage
Giulio2002 Feb 3, 2022
ac2b490
better coverage
Giulio2002 Feb 3, 2022
e649315
type
Giulio2002 Feb 3, 2022
48eba21
more coverage
Giulio2002 Feb 3, 2022
c5d97b0
more coverage
Giulio2002 Feb 3, 2022
cc66091
even more coverage
Giulio2002 Feb 3, 2022
dd4c222
net cov
Giulio2002 Feb 3, 2022
6486c26
config
Giulio2002 Feb 3, 2022
9c69331
lint
Giulio2002 Feb 3, 2022
e2769ba
lint again
Giulio2002 Feb 3, 2022
45cc96b
simple
Giulio2002 Feb 3, 2022
920d56f
even more coooverage
Giulio2002 Feb 4, 2022
c6c5639
rpc coverage
Giulio2002 Feb 4, 2022
5f3e6d5
more concise tests
Giulio2002 Feb 4, 2022
7cd90d3
smaller tests
Giulio2002 Feb 4, 2022
0954cfb
typos
Giulio2002 Feb 4, 2022
13bfdf3
lint
Giulio2002 Feb 4, 2022
164ed03
get_target
Giulio2002 Feb 8, 2022
24c7030
smaller PR
Giulio2002 Feb 10, 2022
6d892ad
resizing
Giulio2002 Feb 10, 2022
6c17641
resizing
Giulio2002 Feb 10, 2022
327a3f3
ops
Giulio2002 Feb 10, 2022
3aa0e4d
resize
Giulio2002 Feb 10, 2022
75fadd8
ops
Giulio2002 Feb 10, 2022
0a5bd24
resize
Giulio2002 Feb 10, 2022
66a547c
net_api
Giulio2002 Feb 10, 2022
0371141
dates
Giulio2002 Feb 10, 2022
7eff62f
tests
Giulio2002 Feb 10, 2022
a3eae74
comments
Giulio2002 Feb 11, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ add_subdirectory(silkworm)
option(SILKRPC_CLANG_COVERAGE "Clang instrumentation for code coverage reports" OFF)

if(SILKRPC_CLANG_COVERAGE)
add_compile_options(-fprofile-instr-generate -fcoverage-mapping)

add_compile_options(-fprofile-instr-generate -fcoverage-mapping -DBUILD_COVERAGE)
add_link_options(-fprofile-instr-generate -fcoverage-mapping)
endif()

Expand Down
4 changes: 2 additions & 2 deletions cmd/ethbackend_coroutines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#include <silkrpc/common/constants.hpp>
#include <silkrpc/common/util.hpp>
#include <silkrpc/context_pool.hpp>
#include <silkrpc/ethbackend/backend.hpp>
#include <silkrpc/ethbackend/backend_grpc.hpp>
#include <silkrpc/interfaces/types/types.pb.h>

inline std::ostream& operator<<(std::ostream& out, const types::H160& address) {
Expand Down Expand Up @@ -74,7 +74,7 @@ int ethbackend_coroutines(const std::string& target) {
const auto channel = grpc::CreateChannel(target, grpc::InsecureChannelCredentials());

// Etherbase
silkrpc::ethbackend::BackEnd eth_backend{*io_context, channel, grpc_queue.get()};
silkrpc::ethbackend::BackEndGrpc eth_backend{*io_context, channel, grpc_queue.get()};
asio::co_spawn(*io_context, ethbackend_etherbase(eth_backend), [&](std::exception_ptr exptr) {
context_pool.stop();
});
Expand Down
49 changes: 49 additions & 0 deletions silkrpc/commands/engine_api.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
Copyright 2022 The Silkrpc Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include "engine_api.hpp"

#include <string>

namespace silkrpc::commands {

asio::awaitable<void> EngineRpcApi::handle_engine_get_payload_v1(const nlohmann::json& request, nlohmann::json& reply) {
auto params = request.at("params");

if (params.size() != 1) {
auto error_msg = "invalid engine_getPayloadV1 params: " + params.dump();
SILKRPC_ERROR << error_msg << "\n";
reply = make_json_error(request.at("id"), 100, error_msg);
co_return;
}
#ifndef BUILD_COVERAGE
Giulio2002 marked this conversation as resolved.
Show resolved Hide resolved
try {
#endif
const auto payload_id = params[0].get<std::string>();
reply = co_await backend_->engine_get_payload_v1(std::stoul(payload_id, 0, 16));
#ifndef BUILD_COVERAGE
} catch (const std::exception& e) {
SILKRPC_ERROR << "exception: " << e.what() << " processing request: " << request.dump() << "\n";
reply = make_json_error(request.at("id"), 100, e.what());
} catch (...) {
SILKRPC_ERROR << "unexpected exception processing request: " << request.dump() << "\n";
reply = make_json_error(request.at("id"), 100, "unexpected exception");
}
#endif
}


} // namespace silkrpc::commands
55 changes: 55 additions & 0 deletions silkrpc/commands/engine_api.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
Copyright 2022 The Silkrpc Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef SILKRPC_COMMANDS_ENGINE_API_HPP_
#define SILKRPC_COMMANDS_ENGINE_API_HPP_

#include <memory>
#include <vector>

#include <asio/awaitable.hpp>
#include <asio/thread_pool.hpp>
#include <nlohmann/json.hpp>

#include <silkrpc/context_pool.hpp>
#include <silkrpc/json/types.hpp>
#include <silkrpc/ethbackend/backend.hpp>


namespace silkrpc::http { class RequestHandler; }

namespace silkrpc::commands {

class EngineRpcApi {
public:
explicit EngineRpcApi(std::unique_ptr<ethbackend::BackEnd>& backend): backend_(backend) {}
virtual ~EngineRpcApi() {}

EngineRpcApi(const EngineRpcApi&) = delete;
EngineRpcApi& operator=(const EngineRpcApi&) = delete;

protected:
asio::awaitable<void> handle_engine_get_payload_v1(const nlohmann::json& request, nlohmann::json& reply);

private:
std::unique_ptr<ethbackend::BackEnd>& backend_;

friend class silkrpc::http::RequestHandler;
};

} // namespace silkrpc::commands

#endif // SILKRPC_COMMANDS_ENGINE_API_HPP_
135 changes: 135 additions & 0 deletions silkrpc/commands/engine_api_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
Copyright 2021 The Silkrpc Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include "engine_api.hpp"

#include <silkrpc/json/types.hpp>
#include <silkrpc/http/methods.hpp>
#include <catch2/catch.hpp>
#include <gmock/gmock.h>
#include <asio/awaitable.hpp>
#include <asio/use_future.hpp>
#include <asio/co_spawn.hpp>
#include <utility>
#include <string>

namespace silkrpc::commands {

using Catch::Matchers::Message;

namespace {
class BackEndMock : public ethbackend::BackEnd {
public:
MOCK_METHOD((asio::awaitable<evmc::address>), etherbase, ());
MOCK_METHOD((asio::awaitable<uint64_t>), protocol_version, ());
MOCK_METHOD((asio::awaitable<uint64_t>), net_version, ());
MOCK_METHOD((asio::awaitable<std::string>), client_version, ());
MOCK_METHOD((asio::awaitable<uint64_t>), net_peer_count, ());
MOCK_METHOD((asio::awaitable<ExecutionPayload>), engine_get_payload_v1, (uint64_t payload_id));
};

} // namespace

class EngineRpcApiTest : public EngineRpcApi{
public:
explicit EngineRpcApiTest(std::unique_ptr<ethbackend::BackEnd>& backend): EngineRpcApi(backend) {}

using EngineRpcApi::handle_engine_get_payload_v1;
};

using testing::InvokeWithoutArgs;

TEST_CASE("handle_engine_get_payload_v1 succeeds if request is expected payload", "[silkrpc][engine_api]") {
SILKRPC_LOG_VERBOSITY(LogLevel::None);

BackEndMock backend;
EXPECT_CALL(backend, engine_get_payload_v1(1)).WillOnce(InvokeWithoutArgs(
[]() -> asio::awaitable<ExecutionPayload> {
co_return ExecutionPayload{1};
}
));

std::unique_ptr<ethbackend::BackEnd> backend_ptr(&backend);

nlohmann::json reply;
nlohmann::json request = R"({
"jsonrpc":"2.0",
"id":1,
"method":"engine_getPayloadV1",
"params":["0x0000000000000001"]
})"_json;
// Initialize contex pool
ContextPool cp{1, []() { return grpc::CreateChannel("localhost", grpc::InsecureChannelCredentials()); }};
auto context_pool_thread = std::thread([&]() { cp.run(); });
// Initialise components
EngineRpcApiTest rpc(backend_ptr);

// spawn routine
auto result{asio::co_spawn(cp.get_io_context(), [&rpc, &reply, &request]() {
return rpc.handle_engine_get_payload_v1(
request,
reply
);
}, asio::use_future)};
result.get();

CHECK(reply == ExecutionPayload{1});

cp.stop();
context_pool_thread.join();
backend_ptr.release();
}

TEST_CASE("handle_engine_get_payload_v1 fails with invalid amount of params", "[silkrpc][engine_api]") {
SILKRPC_LOG_VERBOSITY(LogLevel::None);

nlohmann::json reply;
nlohmann::json request = R"({
"jsonrpc":"2.0",
"id":1,
"method":"engine_getPayloadV1",
"params":[]
})"_json;
// Initialize contex pool
ContextPool cp{1, []() { return grpc::CreateChannel("localhost", grpc::InsecureChannelCredentials()); }};
auto context_pool_thread = std::thread([&]() { cp.run(); });
// Initialise components
std::unique_ptr<ethbackend::BackEnd> backend_ptr(new BackEndMock);
EngineRpcApiTest rpc(backend_ptr);

// spawn routine
auto result{asio::co_spawn(cp.get_io_context(), [&rpc, &reply, &request]() {
return rpc.handle_engine_get_payload_v1(
request,
reply
);
}, asio::use_future)};
result.get();

CHECK(reply == R"({
"error":{
"code":100,
"message":"invalid engine_getPayloadV1 params: []"
},
"id":1,
"jsonrpc":"2.0"
})"_json);

cp.stop();
context_pool_thread.join();
}

} // namespace silkrpc::commands
1 change: 1 addition & 0 deletions silkrpc/commands/net_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <silkrpc/json/types.hpp>
#include <silkrpc/types/log.hpp>
#include <silkrpc/ethbackend/backend.hpp>
#include <silkrpc/common/log.hpp>

namespace silkrpc::http { class RequestHandler; }

Expand Down
6 changes: 4 additions & 2 deletions silkrpc/commands/rpc_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,20 @@
#include <silkrpc/commands/tg_api.hpp>
#include <silkrpc/commands/trace_api.hpp>
#include <silkrpc/commands/web3_api.hpp>
#include <silkrpc/commands/engine_api.hpp>

namespace silkrpc::http { class RequestHandler; }

namespace silkrpc::commands {

class RpcApiTable;

class RpcApi : protected EthereumRpcApi, NetRpcApi, Web3RpcApi, DebugRpcApi, ParityRpcApi, TurboGethRpcApi, TraceRpcApi {
class RpcApi : protected EthereumRpcApi, NetRpcApi, Web3RpcApi, DebugRpcApi, ParityRpcApi, TurboGethRpcApi, TraceRpcApi, EngineRpcApi {
public:
explicit RpcApi(Context& context, asio::thread_pool& workers) :
EthereumRpcApi{context, workers}, NetRpcApi{context.backend}, Web3RpcApi{context}, DebugRpcApi{context.database},
ParityRpcApi{context.database}, TurboGethRpcApi{context.database}, TraceRpcApi{context.database} {}
ParityRpcApi{context.database}, TurboGethRpcApi{context.database}, TraceRpcApi{context.database},
EngineRpcApi(context.backend) {}
virtual ~RpcApi() {}

RpcApi(const RpcApi&) = delete;
Expand Down
6 changes: 6 additions & 0 deletions silkrpc/commands/rpc_api_table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ void RpcApiTable::add_handlers(const std::string& api_namespace) {
add_trace_handlers();
} else if (api_namespace == kWeb3ApiNamespace) {
add_web3_handlers();
} else if (api_namespace == kEngineApiNamespace) {
add_engine_handlers();
} else {
SILKRPC_WARN << "Server::add_handlers invalid namespace [" << api_namespace << "] ignored\n";
}
Expand Down Expand Up @@ -156,4 +158,8 @@ void RpcApiTable::add_web3_handlers() {
handlers_[http::method::k_web3_sha3] = &commands::RpcApi::handle_web3_sha3;
}

void RpcApiTable::add_engine_handlers() {
handlers_[http::method::k_engine_getPayloadV1] = &commands::RpcApi::handle_engine_get_payload_v1;
}

} // namespace silkrpc::commands
1 change: 1 addition & 0 deletions silkrpc/commands/rpc_api_table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class RpcApiTable {
void add_tg_handlers();
void add_trace_handlers();
void add_web3_handlers();
void add_engine_handlers();

std::map<std::string, HandleMethod> handlers_;
};
Expand Down
2 changes: 1 addition & 1 deletion silkrpc/commands/web3_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace silkrpc::commands {

// https://eth.wiki/json-rpc/API#web3_clientversion
asio::awaitable<void> Web3RpcApi::handle_web3_client_version(const nlohmann::json& request, nlohmann::json& reply) {
try {
try {
const auto client_version = co_await backend_->client_version();
reply = make_json_content(request["id"], client_version);
} catch (const std::exception& e) {
Expand Down
3 changes: 2 additions & 1 deletion silkrpc/context_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include <silkrpc/common/log.hpp>
#include <silkrpc/ethdb/kv/remote_database.hpp>
#include <silkrpc/ethbackend/backend_grpc.hpp>

namespace silkrpc {

Expand Down Expand Up @@ -52,7 +53,7 @@ ContextPool::ContextPool(std::size_t pool_size, ChannelFactory create_channel) :
auto grpc_queue = std::make_unique<grpc::CompletionQueue>();
auto grpc_runner = std::make_unique<CompletionRunner>(*grpc_queue, *io_context);
auto database = std::make_unique<ethdb::kv::RemoteDatabase<>>(*io_context, grpc_channel, grpc_queue.get()); // TODO(canepat): move elsewhere
auto backend = std::make_unique<ethbackend::BackEnd>(*io_context, grpc_channel, grpc_queue.get()); // TODO(canepat): move elsewhere
auto backend = std::make_unique<ethbackend::BackEndGrpc>(*io_context, grpc_channel, grpc_queue.get()); // TODO(canepat): move elsewhere
auto miner = std::make_unique<txpool::Miner>(*io_context, grpc_channel, grpc_queue.get()); // TODO(canepat): move elsewhere
auto tx_pool = std::make_unique<txpool::TransactionPool>(*io_context, grpc_channel, grpc_queue.get()); // TODO(canepat): move elsewhere
contexts_.push_back({
Expand Down
Loading