Skip to content

Commit

Permalink
Handle empty id in json rpc responses (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
hatemosphere authored Oct 10, 2023
1 parent 671ba18 commit 958b4d3
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 8 deletions.
33 changes: 30 additions & 3 deletions apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ defmodule EthereumJSONRPC do
documentation for `EthereumJSONRPC.RequestCoordinator`.
"""

require Logger

alias EthereumJSONRPC.{
Block,
Blocks,
Expand Down Expand Up @@ -361,6 +363,29 @@ defmodule EthereumJSONRPC do
|> Enum.into(%{}, fn {params, id} -> {id, params} end)
end

@doc """
Assigns not matched ids between requests and responses to responses with incorrect ids
"""
def sanitize_responses(responses, id_to_params) do
responses
|> Enum.reduce(
{[], Map.keys(id_to_params) -- Enum.map(responses, & &1.id)},
fn
%{id: nil} = res, {result_res, [id | rest]} ->
Logger.error(
"Empty id in response: #{inspect(res)}, stacktrace: #{inspect(Process.info(self(), :current_stacktrace))}"
)

{[%{res | id: id} | result_res], rest}

res, {result_res, non_matched} ->
{[res | result_res], non_matched}
end
)
|> elem(0)
|> Enum.reverse()
end

@doc """
1. POSTs JSON `payload` to `url`
2. Decodes the response
Expand All @@ -386,7 +411,7 @@ defmodule EthereumJSONRPC do
@doc """
Converts `t:quantity/0` to `t:non_neg_integer/0`.
"""
@spec quantity_to_integer(quantity) :: non_neg_integer() | :error
@spec quantity_to_integer(quantity) :: non_neg_integer() | nil
def quantity_to_integer("0x" <> hexadecimal_digits) do
String.to_integer(hexadecimal_digits, 16)
end
Expand All @@ -396,10 +421,12 @@ defmodule EthereumJSONRPC do
def quantity_to_integer(string) when is_binary(string) do
case Integer.parse(string) do
{integer, ""} -> integer
_ -> :error
_ -> nil
end
end

def quantity_to_integer(_), do: nil

@doc """
Converts `t:non_neg_integer/0` to `t:quantity/0`
"""
Expand Down Expand Up @@ -468,7 +495,7 @@ defmodule EthereumJSONRPC do
"""
def timestamp_to_datetime(timestamp) do
case quantity_to_integer(timestamp) do
:error ->
nil ->
nil

quantity ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ defmodule EthereumJSONRPC.Besu.FetchedBeneficiaries do
"""
def from_responses(responses, id_to_params) when is_list(responses) and is_map(id_to_params) do
responses
|> EthereumJSONRPC.sanitize_responses(id_to_params)
|> Enum.map(&response_to_params_set(&1, id_to_params))
|> Enum.reduce(
%EthereumJSONRPC.FetchedBeneficiaries{},
Expand Down
1 change: 1 addition & 0 deletions apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/blocks.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ defmodule EthereumJSONRPC.Blocks do
def from_responses(responses, id_to_params) when is_list(responses) and is_map(id_to_params) do
%{errors: errors, blocks: blocks} =
responses
|> EthereumJSONRPC.sanitize_responses(id_to_params)
|> Enum.map(&Block.from_response(&1, id_to_params))
|> Enum.reduce(%{errors: [], blocks: []}, fn
{:ok, block}, %{blocks: blocks} = acc ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ defmodule EthereumJSONRPC.FetchedBalances do
"""
def from_responses(responses, id_to_params) do
responses
|> EthereumJSONRPC.sanitize_responses(id_to_params)
|> Enum.map(&FetchedBalance.from_response(&1, id_to_params))
|> Enum.reduce(
%__MODULE__{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ defmodule EthereumJSONRPC.FetchedCodes do
"""
def from_responses(responses, id_to_params) do
responses
|> EthereumJSONRPC.sanitize_responses(id_to_params)
|> Enum.map(&FetchedCode.from_response(&1, id_to_params))
|> Enum.reduce(
%__MODULE__{},
Expand Down
1 change: 1 addition & 0 deletions apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ defmodule EthereumJSONRPC.Geth do
)
when is_list(responses) and is_map(id_to_params) do
responses
|> EthereumJSONRPC.sanitize_responses(id_to_params)
|> Enum.map(&debug_trace_transaction_response_to_internal_transactions_params(&1, id_to_params))
|> reduce_internal_transactions_params()
end
Expand Down
11 changes: 7 additions & 4 deletions apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,18 @@ defmodule EthereumJSONRPC.HTTP do

standardized = %{jsonrpc: jsonrpc, id: id}

case unstandardized do
%{"result" => _, "error" => _} ->
case {id, unstandardized} do
{_id, %{"result" => _, "error" => _}} ->
raise ArgumentError,
"result and error keys are mutually exclusive in JSONRPC 2.0 response objects, but got #{inspect(unstandardized)}"

%{"result" => result} ->
{nil, %{"result" => error}} ->
Map.put(standardized, :error, standardize_error(error))

{_id, %{"result" => result}} ->
Map.put(standardized, :result, result)

%{"error" => error} ->
{_id, %{"error" => error}} ->
Map.put(standardized, :error, standardize_error(error))
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ defmodule EthereumJSONRPC.Parity.FetchedBeneficiaries do
"""
def from_responses(responses, id_to_params) when is_list(responses) and is_map(id_to_params) do
responses
|> EthereumJSONRPC.sanitize_responses(id_to_params)
|> Enum.map(&response_to_params_set(&1, id_to_params))
|> Enum.reduce(
%EthereumJSONRPC.FetchedBeneficiaries{},
Expand Down
1 change: 1 addition & 0 deletions apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/receipts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ defmodule EthereumJSONRPC.Receipts do
defp reduce_responses(responses, id_to_transaction_params)
when is_list(responses) and is_map(id_to_transaction_params) do
responses
|> EthereumJSONRPC.sanitize_responses(id_to_transaction_params)
|> Stream.map(&response_to_receipt(&1, id_to_transaction_params))
|> Enum.reduce({:ok, []}, &reduce_receipt(&1, &2))
end
Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile.zksync
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ ADD . .
RUN apt-get update -y && apt-get install -y curl build-essential git && \
# Get Rust \
apt-get update -y && apt-get install -y curl && \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && \
curl https://sh.rustup.rs -sSf | sh -s -- -y && \
. $HOME/.cargo/env && \
curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && \
apt-get install -y nodejs && \
Expand Down

0 comments on commit 958b4d3

Please sign in to comment.