From 4930fa8568cdfa2162777a8e54db6f9ce0ac42d4 Mon Sep 17 00:00:00 2001 From: hatemosphere Date: Tue, 10 Oct 2023 23:21:46 +0200 Subject: [PATCH] Handle empty id in json rpc responses --- apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex | 33 +++++++++++++++++-- .../besu/fetched_beneficiaries.ex | 1 + .../lib/ethereum_jsonrpc/blocks.ex | 1 + .../lib/ethereum_jsonrpc/fetched_balances.ex | 1 + .../lib/ethereum_jsonrpc/fetched_codes.ex | 1 + .../lib/ethereum_jsonrpc/geth.ex | 1 + .../lib/ethereum_jsonrpc/http.ex | 11 ++++--- .../parity/fetched_beneficiaries.ex | 1 + .../lib/ethereum_jsonrpc/receipts.ex | 1 + docker/Dockerfile.zksync | 2 +- 10 files changed, 45 insertions(+), 8 deletions(-) diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex index c18e6c3f1d35..de2af89466cf 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex @@ -25,6 +25,8 @@ defmodule EthereumJSONRPC do documentation for `EthereumJSONRPC.RequestCoordinator`. """ + require Logger + alias EthereumJSONRPC.{ Block, Blocks, @@ -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 @@ -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 @@ -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` """ @@ -468,7 +495,7 @@ defmodule EthereumJSONRPC do """ def timestamp_to_datetime(timestamp) do case quantity_to_integer(timestamp) do - :error -> + nil -> nil quantity -> diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/besu/fetched_beneficiaries.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/besu/fetched_beneficiaries.ex index 0cc22c19f8be..d47e5a0416a4 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/besu/fetched_beneficiaries.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/besu/fetched_beneficiaries.ex @@ -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{}, diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/blocks.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/blocks.ex index dc1740a4aaa5..4d157b317749 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/blocks.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/blocks.ex @@ -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 -> diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/fetched_balances.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/fetched_balances.ex index dc629c720a39..da769b5e5a2d 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/fetched_balances.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/fetched_balances.ex @@ -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__{}, diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/fetched_codes.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/fetched_codes.ex index 8369285194a3..257037990931 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/fetched_codes.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/fetched_codes.ex @@ -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__{}, diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex index 05e32348f24d..2c49f6e522ed 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth.ex @@ -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 diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex index b8222df2d13e..35f1129d7126 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/http.ex @@ -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 diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/parity/fetched_beneficiaries.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/parity/fetched_beneficiaries.ex index 4c8d0ca780df..4559981ea8d6 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/parity/fetched_beneficiaries.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/parity/fetched_beneficiaries.ex @@ -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{}, diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/receipts.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/receipts.ex index e5d706589cf4..8e0cffa7f2b1 100644 --- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/receipts.ex +++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/receipts.ex @@ -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 diff --git a/docker/Dockerfile.zksync b/docker/Dockerfile.zksync index 0f27349cb24f..304f2035b831 100644 --- a/docker/Dockerfile.zksync +++ b/docker/Dockerfile.zksync @@ -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 --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh && \ . $HOME/.cargo/env && \ curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && \ apt-get install -y nodejs && \