Skip to content

Commit

Permalink
rpcdaemon: use boost::beast for HTTP (#1762)
Browse files Browse the repository at this point in the history
Co-authored-by: canepat <[email protected]>
  • Loading branch information
lupin012 and canepat authored Jan 21, 2024
1 parent df77e63 commit 960c05f
Show file tree
Hide file tree
Showing 18 changed files with 213 additions and 1,599 deletions.
32 changes: 16 additions & 16 deletions silkworm/rpc/commands/eth_api_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ namespace silkworm::rpc::commands {
#ifndef SILKWORM_SANITIZE
TEST_CASE_METHOD(test::RpcApiE2ETest, "unit: eth_blockNumber succeeds if request well-formed", "[rpc][api]") {
const auto request = R"({"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]})"_json;
Channel::Response reply;
std::string reply;
run<&test::RequestHandler_ForTest::request_and_create_reply>(request, reply);
CHECK(nlohmann::json::parse(reply.content) == R"({
CHECK(nlohmann::json::parse(reply) == R"({
"jsonrpc":"2.0",
"id":1,
"result":"0x9"
Expand All @@ -37,9 +37,9 @@ TEST_CASE_METHOD(test::RpcApiE2ETest, "unit: eth_blockNumber succeeds if request

TEST_CASE_METHOD(test::RpcApiE2ETest, "unit: eth_blockNumber fails if request empty", "[rpc][api]") {
const auto request = R"({})"_json;
Channel::Response reply;
std::string reply;
run<&test::RequestHandler_ForTest::request_and_create_reply>(request, reply);
CHECK(nlohmann::json::parse(reply.content) == R"({
CHECK(nlohmann::json::parse(reply) == R"({
"jsonrpc":"2.0",
"id":null,
"error":{"code":-32600,"message":"invalid request"}
Expand All @@ -53,9 +53,9 @@ TEST_CASE_METHOD(test::RpcApiE2ETest, "unit: eth_sendRawTransaction fails rlp pa
"method": "eth_sendRawTransaction",
"params": ["0xd46ed67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f0724456"]
})"_json;
Channel::Response reply;
std::string reply;
run<&test::RequestHandler_ForTest::request_and_create_reply>(request, reply);
CHECK(nlohmann::json::parse(reply.content) == R"({
CHECK(nlohmann::json::parse(reply) == R"({
"jsonrpc":"2.0",
"id":1,
"error":{"code":-32000,"message":"rlp: input exceeds encoded length"}
Expand All @@ -69,9 +69,9 @@ TEST_CASE_METHOD(test::RpcApiE2ETest, "unit: eth_sendRawTransaction fails wrong
"method": "eth_sendRawTransaction",
"params": ["0xd46ed67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445"]
})"_json;
Channel::Response reply;
std::string reply;
run<&test::RequestHandler_ForTest::request_and_create_reply>(request, reply);
CHECK(nlohmann::json::parse(reply.content) == R"({
CHECK(nlohmann::json::parse(reply) == R"({
"jsonrpc":"2.0",
"id":1,
"error":{"code":-32000,"message":"rlp: unexpected EIP-2178 serialization"}
Expand All @@ -80,9 +80,9 @@ TEST_CASE_METHOD(test::RpcApiE2ETest, "unit: eth_sendRawTransaction fails wrong

TEST_CASE_METHOD(test::RpcApiE2ETest, "unit: eth_feeHistory succeeds if request well-formed", "[rpc][api]") {
const auto request = R"({"jsonrpc":"2.0","id":1,"method":"eth_feeHistory","params":["0x1","0x867A80",[25,75]]})"_json;
Channel::Response reply;
std::string reply;
run<&test::RequestHandler_ForTest::request_and_create_reply>(request, reply);
CHECK(nlohmann::json::parse(reply.content) == R"({
CHECK(nlohmann::json::parse(reply) == R"({
"jsonrpc":"2.0",
"id":1,
"result":{"gasUsedRatio":null,"oldestBlock":"0x0"}
Expand All @@ -91,9 +91,9 @@ TEST_CASE_METHOD(test::RpcApiE2ETest, "unit: eth_feeHistory succeeds if request

TEST_CASE_METHOD(test::RpcApiE2ETest, "fuzzy: eth_call invalid params", "[rpc][api]") {
const auto request = R"({"jsonrpc":"2.0","id":1,"method":"eth_call","params":[{}, "latest"]})"_json;
Channel::Response reply;
std::string reply;
run<&test::RequestHandler_ForTest::request_and_create_reply>(request, reply);
CHECK(nlohmann::json::parse(reply.content) == R"({
CHECK(nlohmann::json::parse(reply) == R"({
"jsonrpc":"2.0",
"id":1,
"error":{"code":-32000,"message":"malformed transaction: cannot recover sender"}
Expand All @@ -102,9 +102,9 @@ TEST_CASE_METHOD(test::RpcApiE2ETest, "fuzzy: eth_call invalid params", "[rpc][a

TEST_CASE_METHOD(test::RpcApiE2ETest, "fuzzy: eth_feeHistory sigsegv invalid input", "[rpc][api]") {
const auto request = R"({"jsonrpc":"2.0","id":1,"method":"eth_feeHistory","params":["5x1","0x2",[95,99]]})"_json;
Channel::Response reply;
std::string reply;
run<&test::RequestHandler_ForTest::request_and_create_reply>(request, reply);
CHECK(nlohmann::json::parse(reply.content) == R"({
CHECK(nlohmann::json::parse(reply) == R"({
"jsonrpc":"2.0",
"id":1,
"error":{"code":100,"message":"invalid block_count: 5x1"}
Expand All @@ -113,9 +113,9 @@ TEST_CASE_METHOD(test::RpcApiE2ETest, "fuzzy: eth_feeHistory sigsegv invalid inp

TEST_CASE_METHOD(test::RpcApiE2ETest, "fuzzy: eth_feeHistory sigsegv valid input", "[rpc][api]") {
const auto request = R"({"jsonrpc":"2.0","id":1,"method":"eth_feeHistory","params":["0x5","0x2",[95,99]]})"_json;
Channel::Response reply;
std::string reply;
run<&test::RequestHandler_ForTest::request_and_create_reply>(request, reply);
CHECK(nlohmann::json::parse(reply.content) == R"({
CHECK(nlohmann::json::parse(reply) == R"({
"jsonrpc":"2.0",
"id":1,
"result":{
Expand Down
15 changes: 7 additions & 8 deletions silkworm/rpc/commands/rpc_api_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#include <nlohmann/json.hpp>

#include <silkworm/infra/test_util/log.hpp>
#include <silkworm/rpc/http/request_handler.hpp>
#include <silkworm/rpc/test/api_test_database.hpp>

namespace silkworm::rpc::commands {
Expand Down Expand Up @@ -70,7 +69,7 @@ static const std::vector<std::string> tests_to_ignore = {
"eth_getProof", // not implemented
"eth_feeHistory", // history not stored, needs fixing
"eth_sendRawTransaction", // call to oracle fails, needs fixing or mocking
"eth_createAccessList", // expected value doesn't contains gas optimzation
"eth_createAccessList", // expected value doesn't contain gas optimization
};

// Exclude tests from sanitizer builds due to ASAN/TSAN warnings inside gRPC library
Expand Down Expand Up @@ -108,16 +107,16 @@ TEST_CASE("rpc_api io (all files)", "[rpc][rpc_api]") {
auto request = nlohmann::json::parse(line_out.substr(3));
auto expected = nlohmann::json::parse(line_in.substr(3));

Channel::Response response;
std::string response;
test_base.run<&test::RequestHandler_ForTest::request_and_create_reply>(request, response);
INFO("Request: " << request.dump())
INFO("Actual response: " << response.content)
INFO("Actual response: " << response)
INFO("Expected response: " << expected.dump())

if (absl::StrContains(test_name, "invalid")) {
CHECK(nlohmann::json::parse(response.content).contains("error"));
CHECK(nlohmann::json::parse(response).contains("error"));
} else {
CHECK(are_equivalent(nlohmann::json::parse(response.content), expected));
CHECK(are_equivalent(nlohmann::json::parse(response), expected));
}
}
}
Expand All @@ -132,10 +131,10 @@ TEST_CASE("rpc_api io (individual)", "[rpc][rpc_api][ignore]") {

SECTION("sample test") {
auto request = R"({"jsonrpc":"2.0","id":1,"method":"debug_getRawTransaction","params":["0x74e41d593675913d6d5521f46523f1bd396dff1891bdb35f59be47c7e5e0b34b"]})"_json;
Channel::Response response;
std::string response;

test_base.run<&test::RequestHandler_ForTest::request_and_create_reply>(request, response);
CHECK(nlohmann::json::parse(response.content) == R"({"jsonrpc":"2.0","id":1,"result":"0xf8678084342770c182520894658bdf435d810c91414ec09147daa6db624063798203e880820a95a0af5fc351b9e457a31f37c84e5cd99dd3c5de60af3de33c6f4160177a2c786a60a0201da7a21046af55837330a2c52fc1543cd4d9ead00ddf178dd96935b607ff9b"})"_json);
CHECK(nlohmann::json::parse(response) == R"({"jsonrpc":"2.0","id":1,"result":"0xf8678084342770c182520894658bdf435d810c91414ec09147daa6db624063798203e880820a95a0af5fc351b9e457a31f37c84e5cd99dd3c5de60af3de33c6f4160177a2c786a60a0201da7a21046af55837330a2c52fc1543cd4d9ead00ddf178dd96935b607ff9b"})"_json);
}
}
#endif // SILKWORM_SANITIZE
Expand Down
5 changes: 0 additions & 5 deletions silkworm/rpc/common/constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,4 @@ inline constexpr const std::chrono::milliseconds kDefaultTimeout{10000};

inline constexpr const std::size_t kHttpIncomingBufferSize{8192};

inline constexpr const std::size_t kRequestContentInitialCapacity{1024};
inline constexpr const std::size_t kRequestHeadersInitialCapacity{8};
inline constexpr const std::size_t kRequestMethodInitialCapacity{64};
inline constexpr const std::size_t kRequestUriInitialCapacity{64};

} // namespace silkworm
27 changes: 1 addition & 26 deletions silkworm/rpc/http/channel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,39 +22,14 @@ namespace silkworm::rpc {

class Channel : public StreamWriter {
public:
enum class ResponseStatus {
processing_continue,
accepted,
ok,
created,
no_content,
multiple_choices,
moved_permanently,
moved_temporarily,
not_modified,
bad_request,
unauthorized,
forbidden,
not_found,
internal_server_error,
not_implemented,
bad_gateway,
service_unavailable
};

struct Response {
ResponseStatus status{ResponseStatus::ok};
std::string content;
};

Channel() = default;
~Channel() override = default;

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

virtual Task<void> open_stream() = 0;
virtual Task<void> write_rsp(Response& response) = 0;
virtual Task<void> write_rsp(const std::string& content) = 0;
};

} // namespace silkworm::rpc
Loading

0 comments on commit 960c05f

Please sign in to comment.