Merge pull request #9039 from blockscout/np-fix-decoding-in-tx-summary-request

Fix tx input decoding in tx summary microservice request
pull/9015/head
Victor Baranov 10 months ago committed by GitHub
commit 9e33fb04b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 47
      apps/block_scout_web/lib/block_scout_web/microservice_interfaces/transaction_interpretation.ex
  3. 22
      apps/block_scout_web/lib/block_scout_web/views/api/v2/transaction_view.ex
  4. 4
      apps/explorer/lib/explorer/chain.ex
  5. 12
      apps/explorer/lib/explorer/chain/transaction.ex

@ -12,6 +12,7 @@
### Fixes
- [#9039](https://github.com/blockscout/blockscout/pull/9039) - Fix tx input decoding in tx summary microservice request
- [#9013](https://github.com/blockscout/blockscout/pull/9013) - Speed up `Indexer.Fetcher.TokenInstance.LegacySanitize`
- [#8969](https://github.com/blockscout/blockscout/pull/8969) - Support legacy paging options for address transaction endpoint
- [#8965](https://github.com/blockscout/blockscout/pull/8965) - Set poll: false for internal transactions fetcher

@ -39,7 +39,7 @@ defmodule BlockScoutWeb.MicroserviceInterfaces.TransactionInterpretation do
case HTTPoison.post(url, Jason.encode!(body), headers, recv_timeout: @post_timeout) do
{:ok, %Response{body: body, status_code: 200}} ->
body |> Jason.decode() |> preload_tokens()
body |> Jason.decode() |> preload_template_variables()
error ->
old_truncate = Application.get_env(:logger, :truncate)
@ -76,10 +76,10 @@ defmodule BlockScoutWeb.MicroserviceInterfaces.TransactionInterpretation do
created_contract_address: [:names, :token, :smart_contract]
])
skip_sig_provider? = true
skip_sig_provider? = false
{decoded_input, _abi_acc, _methods_acc} = Transaction.decoded_input_data(transaction, skip_sig_provider?, @api_true)
decoded_input_data = TransactionView.decoded_input(decoded_input)
decoded_input_data = decoded_input |> TransactionView.format_decoded_input() |> TransactionView.decoded_input()
%{
data: %{
@ -148,12 +148,12 @@ defmodule BlockScoutWeb.MicroserviceInterfaces.TransactionInterpretation do
|> Enum.map(fn {log, decoded_log} -> TransactionView.prepare_log(log, transaction.hash, decoded_log, true) end)
end
defp preload_tokens({:ok, %{"success" => true, "data" => %{"summaries" => summaries} = data}}) do
defp preload_template_variables({:ok, %{"success" => true, "data" => %{"summaries" => summaries} = data}}) do
summaries_updated =
Enum.map(summaries, fn %{"summary_template_variables" => summary_template_variables} = summary ->
summary_template_variables_preloaded =
Enum.reduce(summary_template_variables, %{}, fn {key, value}, acc ->
Map.put(acc, key, preload_token(value))
Map.put(acc, key, preload_template_variable(value))
end)
Map.put(summary, "summary_template_variables", summary_template_variables_preloaded)
@ -162,17 +162,46 @@ defmodule BlockScoutWeb.MicroserviceInterfaces.TransactionInterpretation do
{:ok, %{"success" => true, "data" => Map.put(data, "summaries", summaries_updated)}}
end
defp preload_tokens(error), do: error
defp preload_template_variables(error), do: error
defp preload_token(%{"type" => "token", "value" => %{"address" => address_hash_string} = value}),
defp preload_template_variable(%{"type" => "token", "value" => %{"address" => address_hash_string} = value}),
do: %{
"type" => "token",
"value" => address_hash_string |> Chain.token_from_address_hash(@api_true) |> token_from_db() |> Map.merge(value)
}
defp preload_token(other), do: other
defp preload_template_variable(%{"type" => "address", "value" => %{"hash" => address_hash_string} = value}),
do: %{
"type" => "address",
"value" =>
address_hash_string
|> Chain.hash_to_address(
[
necessity_by_association: %{
:names => :optional,
:smart_contract => :optional
},
api?: true
],
false
)
|> address_from_db()
|> Map.merge(value)
}
defp token_from_db({:error, _}), do: %{}
defp preload_template_variable(other), do: other
defp token_from_db({:error, _}), do: %{}
defp token_from_db({:ok, token}), do: TokenView.render("token.json", %{token: token})
defp address_from_db({:error, _}), do: %{}
defp address_from_db({:ok, address}),
do:
Helper.address_with_info(
nil,
address,
address.hash,
true
)
end

@ -208,12 +208,15 @@ defmodule BlockScoutWeb.API.V2.TransactionView do
end
def decode_transactions(transactions, skip_sig_provider?) do
Enum.reduce(transactions, {[], %{}, %{}}, fn transaction, {results, abi_acc, methods_acc} ->
{result, abi_acc, methods_acc} =
Transaction.decoded_input_data(transaction, skip_sig_provider?, @api_true, abi_acc, methods_acc)
{results, abi_acc, methods_acc} =
Enum.reduce(transactions, {[], %{}, %{}}, fn transaction, {results, abi_acc, methods_acc} ->
{result, abi_acc, methods_acc} =
Transaction.decoded_input_data(transaction, skip_sig_provider?, @api_true, abi_acc, methods_acc)
{Enum.reverse([format_decoded_input(result) | Enum.reverse(results)]), abi_acc, methods_acc}
end)
{[format_decoded_input(result) | results], abi_acc, methods_acc}
end)
{Enum.reverse(results), abi_acc, methods_acc}
end
def prepare_token_transfer(token_transfer, _conn, decoded_input) do
@ -653,10 +656,11 @@ defmodule BlockScoutWeb.API.V2.TransactionView do
defp format_status({:error, reason}), do: reason
defp format_status(status), do: status
defp format_decoded_input({:error, _, []}), do: nil
defp format_decoded_input({:error, _, candidates}), do: Enum.at(candidates, 0)
defp format_decoded_input({:ok, _identifier, _text, _mapping} = decoded), do: decoded
defp format_decoded_input(_), do: nil
@spec format_decoded_input(any()) :: nil | map() | tuple()
def format_decoded_input({:error, _, []}), do: nil
def format_decoded_input({:error, _, candidates}), do: Enum.at(candidates, 0)
def format_decoded_input({:ok, _identifier, _text, _mapping} = decoded), do: decoded
def format_decoded_input(_), do: nil
defp format_decoded_log_input({:error, :could_not_decode}), do: nil
defp format_decoded_log_input({:ok, _method_id, _text, _mapping} = decoded), do: decoded

@ -1017,10 +1017,10 @@ defmodule Explorer.Chain do
Optionally it also accepts a boolean to fetch the `has_decompiled_code?` virtual field or not
"""
@spec hash_to_address(Hash.Address.t(), [necessity_by_association_option | api?], boolean()) ::
@spec hash_to_address(Hash.Address.t() | binary(), [necessity_by_association_option | api?], boolean()) ::
{:ok, Address.t()} | {:error, :not_found}
def hash_to_address(
%Hash{byte_count: unquote(Hash.Address.byte_count())} = hash,
hash,
options \\ [
necessity_by_association: %{
:contracts_creation_internal_transaction => :optional,

@ -594,6 +594,18 @@ defmodule Explorer.Chain.Transaction do
end
# Because there is no contract association, we know the contract was not verified
@spec decoded_input_data(
NotLoaded.t() | Transaction.t(),
boolean(),
[Chain.api?()],
full_abi_acc,
methods_acc
) ::
{error_type | success_type, full_abi_acc, methods_acc}
when full_abi_acc: map(),
methods_acc: map(),
error_type: {:error, any()} | {:error, :contract_not_verified | :contract_verified, list()},
success_type: {:ok | binary(), any()} | {:ok, binary(), binary(), list()}
def decoded_input_data(tx, skip_sig_provider? \\ false, options, full_abi_acc \\ %{}, methods_acc \\ %{})
def decoded_input_data(%__MODULE__{to_address: nil}, _, _, full_abi_acc, methods_acc),

Loading…
Cancel
Save