diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ba8881ece..c7c78d1b66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - [#2470](https://github.com/poanetwork/blockscout/pull/2470) - Allow Realtime Fetcher to wait for small skips ### Fixes +- [#2777](https://github.com/poanetwork/blockscout/pull/2777) - Remove duplicate blocks from changes_list before import - [#2755](https://github.com/poanetwork/blockscout/pull/2755) - various token instance fetcher fixes - [#2770](https://github.com/poanetwork/blockscout/pull/2770) - do not re-fetch token instances without uris - [#2761](https://github.com/poanetwork/blockscout/pull/2761) - add indexes for token instances fetching queries diff --git a/apps/explorer/lib/explorer/chain/import/runner/blocks.ex b/apps/explorer/lib/explorer/chain/import/runner/blocks.ex index ff970faad6..61fb6973c9 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/blocks.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/blocks.ex @@ -224,7 +224,10 @@ defmodule Explorer.Chain.Import.Runner.Blocks do on_conflict = Map.get_lazy(options, :on_conflict, &default_on_conflict/0) # Enforce Block ShareLocks order (see docs: sharelocks.md) - ordered_changes_list = Enum.sort_by(changes_list, & &1.hash) + ordered_changes_list = + changes_list + |> Enum.sort_by(& &1.hash) + |> Enum.dedup_by(& &1.hash) Import.insert_changes_list( repo, diff --git a/apps/explorer/test/explorer/chain/import/runner/blocks_test.exs b/apps/explorer/test/explorer/chain/import/runner/blocks_test.exs index 3cbd7f4834..c47204e749 100644 --- a/apps/explorer/test/explorer/chain/import/runner/blocks_test.exs +++ b/apps/explorer/test/explorer/chain/import/runner/blocks_test.exs @@ -382,6 +382,20 @@ defmodule Explorer.Chain.Import.Runner.BlocksTest do insert_transaction(transaction2, options) assert Chain.missing_block_number_ranges(range) == [(block_number + 1)..(block_number + 1)] end + + test "removes duplicate blocks (by hash) before inserting", + %{consensus_block: %{number: block_number, hash: block_hash, miner_hash: miner_hash}, options: options} do + new_block = params_for(:block, miner_hash: miner_hash, consensus: true) + + %Ecto.Changeset{valid?: true, changes: block_changes} = Block.changeset(%Block{}, new_block) + + result = + Multi.new() + |> Blocks.run([block_changes, block_changes], options) + |> Repo.transaction() + + assert {:ok, %{blocks: [%{hash: block_hash, consensus: true}]}} = result + end end defp insert_block(block_params, options) do