Skip to content

Commit

Permalink
rpcdaemon: JsonRpcValidator perf improvements (#1755)
Browse files Browse the repository at this point in the history
  • Loading branch information
JacekGlen authored Jan 13, 2024
1 parent 84983ea commit fd6a882
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 13 deletions.
30 changes: 17 additions & 13 deletions silkworm/rpc/http/json_rpc_validator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,17 +102,17 @@ void JsonRpcValidator::check_request_fields(const nlohmann::json& request, JsonR
}

void JsonRpcValidator::validate_params(const nlohmann::json& request, JsonRpcValidationResult& result) {
const auto method = request.find(kRequestFieldMethod).value().get<std::string>();
const auto params_field = request.find(kRequestFieldParameters);
const auto params = params_field != request.end() ? params_field.value() : nlohmann::json::array();
const auto& method = request.find(kRequestFieldMethod).value().get<std::string>();
const auto& params_field = request.find(kRequestFieldParameters);
const auto& params = params_field != request.end() ? params_field.value() : nlohmann::json::array();

const auto method_spec_field = method_specs_.find(method);
const auto& method_spec_field = method_specs_.find(method);
if (method_spec_field == method_specs_.end()) {
result.is_valid = accept_unknown_methods_;
result.error_message = "Method not found in spec";
return;
}
const auto method_spec = method_spec_field->second;
const auto& method_spec = method_spec_field->second;

if (params.size() > method_spec.size()) {
result.is_valid = false;
Expand All @@ -122,7 +122,7 @@ void JsonRpcValidator::validate_params(const nlohmann::json& request, JsonRpcVal

unsigned long idx = 0;
for (const auto& spec : method_spec) {
const auto spec_name = spec["name"].get<std::string>();
const auto& spec_name = spec["name"].get<std::string>();
const auto& spec_schema = spec["schema"];

if (params.size() <= idx) {
Expand Down Expand Up @@ -169,7 +169,7 @@ void JsonRpcValidator::validate_schema(const nlohmann::json& value, const nlohma
}

void JsonRpcValidator::validate_type(const nlohmann::json& value, const nlohmann::json& schema, JsonRpcValidationResult& result) {
const auto schema_type = schema["type"].get<std::string>();
const auto& schema_type = schema["type"].get<std::string>();

if (schema_type == "string") {
validate_string(value, schema, result);
Expand All @@ -196,26 +196,30 @@ void JsonRpcValidator::validate_string(const nlohmann::json& string, const nlohm
return;
}

const auto schema_pattern_field = schema.find("pattern");
const auto& schema_pattern_field = schema.find("pattern");
if (schema_pattern_field != schema.end()) {
boost::regex pattern;
const auto schema_pattern = schema_pattern_field.value().get<std::string>();
if (patterns_.find(schema_pattern) != patterns_.end()) {
pattern = patterns_[schema_pattern];
const auto& schema_pattern = schema_pattern_field.value().get<std::string>();

const auto& pattern_field = patterns_.find(schema_pattern);
if (pattern_field != patterns_.end()) {
pattern = pattern_field->second;
} else {
pattern = boost::regex(schema_pattern, boost::regex::optimize);
patterns_[schema_pattern] = pattern;
}

if (!boost::regex_match(string.get<std::string>(), pattern)) {
result.is_valid = false;
result.error_message = "Invalid string pattern";
return;
}
}

if (schema.find("enum") != schema.end()) {
const auto& enum_field = schema.find("enum");
if (enum_field != schema.end()) {
bool is_valid = false;
for (const auto& enum_value : schema["enum"]) {
for (const auto& enum_value : enum_field.value()) {
if (string == enum_value) {
is_valid = true;
break;
Expand Down
45 changes: 45 additions & 0 deletions silkworm/rpc/http/json_rpc_validator_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,51 @@ TEST_CASE("rpc::http::JsonRpcValidator detects missing request field", "[rpc][ht
CHECK(result.error_message == "Request not valid, required fields: jsonrpc,id,method,params");
}

TEST_CASE("rpc::http::JsonRpcValidator validates invalid request fields", "[rpc][http][json_rpc_validator]") {
JsonRpcValidator validator{};

nlohmann::json request = {
{"jsonrpc", 2},
{"method", "eth_getBlockByNumber"},
{"params", {"0x0", true}},
{"id", 1},
};

JsonRpcValidationResult result = validator.validate(request);
CHECK(!result.is_valid);
CHECK(result.error_message == "Invalid field: jsonrpc");

request = {
{"jsonrpc", "2.0"},
{"method", 1},
{"params", {"0x0", true}},
{"id", 1},
};
result = validator.validate(request);
CHECK(!result.is_valid);
CHECK(result.error_message == "Invalid field: method");

request = {
{"jsonrpc", "2.0"},
{"method", "eth_getBlockByNumber"},
{"params", "params"},
{"id", 1},
};
result = validator.validate(request);
CHECK(!result.is_valid);
CHECK(result.error_message == "Invalid field: params");

request = {
{"jsonrpc", "2.0"},
{"method", "eth_getBlockByNumber"},
{"params", {"0x0", true}},
{"id", "1"},
};
result = validator.validate(request);
CHECK(!result.is_valid);
CHECK(result.error_message == "Invalid field: id");
}

TEST_CASE("rpc::http::JsonRpcValidator accepts missing params field", "[rpc][http][json_rpc_validator]") {
JsonRpcValidator validator{};

Expand Down

0 comments on commit fd6a882

Please sign in to comment.