Improve marking of failed internal transactions (#9306)

* fix: marking parent transaction reverts

* chore: changelog

* fix: don't count itself as a parent
pull/9389/head
Kirill Fedoseev 9 months ago committed by GitHub
parent 6ae6692d02
commit 74cceb5d84
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 47
      apps/indexer/lib/indexer/fetcher/internal_transaction.ex

@ -22,6 +22,7 @@
- [#9346](https://github.com/blockscout/blockscout/pull/9346) - Process integer balance in genesis.json
- [#9317](https://github.com/blockscout/blockscout/pull/9317) - Include null gas price txs in fee calculations
- [#9315](https://github.com/blockscout/blockscout/pull/9315) - Fix manual uncle reward calculation
- [#9306](https://github.com/blockscout/blockscout/pull/9306) - Improve marking of failed internal transactions
- [#9305](https://github.com/blockscout/blockscout/pull/9305) - Add effective gas price calculation as fallback
- [#9300](https://github.com/blockscout/blockscout/pull/9300) - Fix read contract bug

@ -254,11 +254,11 @@ defmodule Indexer.Fetcher.InternalTransaction do
end
defp import_internal_transaction(internal_transactions_params, unique_numbers) do
internal_transactions_params_without_failed_creations = remove_failed_creations(internal_transactions_params)
internal_transactions_params_marked = mark_failed_transactions(internal_transactions_params)
addresses_params =
Addresses.extract_addresses(%{
internal_transactions: internal_transactions_params_without_failed_creations
internal_transactions: internal_transactions_params_marked
})
address_hash_to_block_number =
@ -269,11 +269,10 @@ defmodule Indexer.Fetcher.InternalTransaction do
empty_block_numbers =
unique_numbers
|> MapSet.new()
|> MapSet.difference(MapSet.new(internal_transactions_params_without_failed_creations, & &1.block_number))
|> MapSet.difference(MapSet.new(internal_transactions_params_marked, & &1.block_number))
|> Enum.map(&%{block_number: &1})
internal_transactions_and_empty_block_numbers =
internal_transactions_params_without_failed_creations ++ empty_block_numbers
internal_transactions_and_empty_block_numbers = internal_transactions_params_marked ++ empty_block_numbers
imports =
Chain.import(%{
@ -310,34 +309,42 @@ defmodule Indexer.Fetcher.InternalTransaction do
end
end
defp remove_failed_creations(internal_transactions_params) do
defp mark_failed_transactions(internal_transactions_params) do
# we store reversed trace addresses for more efficient list head-tail decomposition in has_failed_parent?
failed_parent_paths =
internal_transactions_params
|> Enum.filter(& &1[:error])
|> Enum.map(&Enum.reverse([&1.transaction_hash | &1.trace_address]))
|> MapSet.new()
internal_transactions_params
|> Enum.map(fn internal_transaction_param ->
transaction_index = internal_transaction_param[:transaction_index]
block_number = internal_transaction_param[:block_number]
failed_parent =
internal_transactions_params
|> Enum.filter(fn internal_transactions_param ->
internal_transactions_param[:block_number] == block_number &&
internal_transactions_param[:transaction_index] == transaction_index &&
internal_transactions_param[:trace_address] == [] && !is_nil(internal_transactions_param[:error])
end)
|> Enum.at(0)
if failed_parent do
if has_failed_parent?(
failed_parent_paths,
internal_transaction_param.trace_address,
[internal_transaction_param.transaction_hash]
) do
# TODO: consider keeping these deleted fields in the reverted transactions
internal_transaction_param
|> Map.delete(:created_contract_address_hash)
|> Map.delete(:created_contract_code)
|> Map.delete(:gas_used)
|> Map.delete(:output)
|> Map.put(:error, internal_transaction_param[:error] || failed_parent[:error])
|> Map.put(:error, internal_transaction_param[:error] || "Parent reverted")
else
internal_transaction_param
end
end)
end
defp has_failed_parent?(failed_parent_paths, [head | tail], reverse_path_acc) do
MapSet.member?(failed_parent_paths, reverse_path_acc) or
has_failed_parent?(failed_parent_paths, tail, [head | reverse_path_acc])
end
# don't count itself as a parent
defp has_failed_parent?(_failed_parent_paths, [], _reverse_path_acc), do: false
defp handle_unique_key_violation(%{exception: %{postgres: %{code: :unique_violation}}}, block_numbers) do
BlocksRunner.invalidate_consensus_blocks(block_numbers)

Loading…
Cancel
Save