diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/block_transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/block_transaction_controller.ex index 1e4fe3bc53..c61dff29b2 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/block_transaction_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/block_transaction_controller.ex @@ -57,7 +57,7 @@ defmodule BlockScoutWeb.BlockTransactionController do |> render( "404.html", block: nil, - block_above_tip: block_above_tip?(formatted_block_hash_or_number) + block_above_tip: block_above_tip(formatted_block_hash_or_number) ) end end @@ -79,10 +79,16 @@ defmodule BlockScoutWeb.BlockTransactionController do end end - defp block_above_tip?("0x" <> _), do: nil + defp block_above_tip("0x" <> _), do: {:error, :hash} - defp block_above_tip?(block_hash_or_number) when is_binary(block_hash_or_number) do - {block_number, ""} = Integer.parse(block_hash_or_number) - block_number > Chain.block_height() + defp block_above_tip(block_hash_or_number) when is_binary(block_hash_or_number) do + case Chain.max_consensus_block_number() do + {:ok, max_consensus_block_number} -> + {block_number, _} = Integer.parse(block_hash_or_number) + {:ok, block_number > max_consensus_block_number} + + {:error, :not_found} -> + {:ok, true} + end end end diff --git a/apps/block_scout_web/lib/block_scout_web/templates/block_transaction/404.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/block_transaction/404.html.eex index 015abcae09..68faa6fb73 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/block_transaction/404.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/block_transaction/404.html.eex @@ -6,7 +6,7 @@

<%= gettext("Block Details") %>

-
+
<%= block_not_found_message(@block_above_tip) %>
diff --git a/apps/block_scout_web/lib/block_scout_web/views/block_transaction_view.ex b/apps/block_scout_web/lib/block_scout_web/views/block_transaction_view.ex index be0e4a3d02..aef7f4124d 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/block_transaction_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/block_transaction_view.ex @@ -3,16 +3,15 @@ defmodule BlockScoutWeb.BlockTransactionView do import BlockScoutWeb.Gettext, only: [gettext: 1] - def block_not_found_message(block_above_tip) do - case block_above_tip do - true -> - gettext("Easy Cowboy! This block does not exist yet!") + def block_not_found_message({:ok, true}) do + gettext("Easy Cowboy! This block does not exist yet!") + end - false -> - gettext("This block has not been processed yet.") + def block_not_found_message({:ok, false}) do + gettext("This block has not been processed yet.") + end - _ -> - gettext("Block not found, please try again later.") - end + def block_not_found_message({:error, :hash}) do + gettext("Block not found, please try again later.") end end diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index e5a36abd74..e2513bf670 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -1254,12 +1254,12 @@ msgid "Block not found, please try again later." msgstr "" #, elixir-format -#: lib/block_scout_web/views/block_transaction_view.ex:9 +#: lib/block_scout_web/views/block_transaction_view.ex:7 msgid "Easy Cowboy! This block does not exist yet!" msgstr "" #, elixir-format -#: lib/block_scout_web/views/block_transaction_view.ex:12 +#: lib/block_scout_web/views/block_transaction_view.ex:11 msgid "This block has not been processed yet." msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index 68ad37cee8..05c4540264 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -1254,12 +1254,12 @@ msgid "Block not found, please try again later." msgstr "" #, elixir-format -#: lib/block_scout_web/views/block_transaction_view.ex:9 +#: lib/block_scout_web/views/block_transaction_view.ex:7 msgid "Easy Cowboy! This block does not exist yet!" msgstr "" #, elixir-format -#: lib/block_scout_web/views/block_transaction_view.ex:12 +#: lib/block_scout_web/views/block_transaction_view.ex:11 msgid "This block has not been processed yet." msgstr "" diff --git a/apps/block_scout_web/test/block_scout_web/controllers/block_transaction_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/block_transaction_controller_test.exs index bedd644ba4..6a4e2ebf32 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/block_transaction_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/block_transaction_controller_test.exs @@ -45,16 +45,29 @@ defmodule BlockScoutWeb.BlockTransactionControllerTest do assert 2 == Enum.count(conn.assigns.transactions) end - test "does not return transactions for non-consensus block number", %{conn: conn} do + test "non-consensus block number without consensus blocks is treated as consensus number above tip", %{conn: conn} do block = insert(:block, consensus: false) - :transaction - |> insert() - |> with_block(block) + transaction = insert(:transaction) + insert(:transaction_fork, hash: transaction.hash, uncle_hash: block.hash) conn = get(conn, block_transaction_path(conn, :index, block.number)) - assert html_response(conn, 404) =~ "This block has not been processed yet." + assert_block_above_tip(conn) + end + + test "non-consensus block number above consensus block number is treated as consensus number above tip", %{ + conn: conn + } do + consensus_block = insert(:block, consensus: true, number: 1) + block = insert(:block, consensus: false, number: consensus_block.number + 1) + + transaction = insert(:transaction) + insert(:transaction_fork, hash: transaction.hash, uncle_hash: block.hash) + + conn = get(conn, block_transaction_path(conn, :index, block.number)) + + assert_block_above_tip(conn) end test "returns transactions for consensus block hash", %{conn: conn} do @@ -70,17 +83,16 @@ defmodule BlockScoutWeb.BlockTransactionControllerTest do assert Enum.count(conn.assigns.transactions) == 1 end - test "returns transactions for non-consensus block hash", %{conn: conn} do + test "does not return transactions for non-consensus block hash", %{conn: conn} do block = insert(:block, consensus: false) - :transaction - |> insert() - |> with_block(block) + transaction = insert(:transaction) + insert(:transaction_fork, hash: transaction.hash, uncle_hash: block.hash) conn = get(conn, block_transaction_path(conn, :index, block.hash)) assert html_response(conn, 200) - assert Enum.count(conn.assigns.transactions) == 1 + assert Enum.count(conn.assigns.transactions) == 0 end test "does not return transactions for invalid block hash", %{conn: conn} do @@ -149,4 +161,12 @@ defmodule BlockScoutWeb.BlockTransactionControllerTest do assert html_response(conn, 200) =~ miner_name end end + + defp assert_block_above_tip(conn) do + assert conn + |> html_response(404) + |> Floki.find(~S|[data-selector="block-not-found-message"|) + |> Floki.text() + |> String.trim() == "Easy Cowboy! This block does not exist yet!" + end end diff --git a/apps/block_scout_web/test/block_scout_web/features/viewing_blocks_test.exs b/apps/block_scout_web/test/block_scout_web/features/viewing_blocks_test.exs index eb5e24e8c4..208fe1bd65 100644 --- a/apps/block_scout_web/test/block_scout_web/features/viewing_blocks_test.exs +++ b/apps/block_scout_web/test/block_scout_web/features/viewing_blocks_test.exs @@ -149,9 +149,8 @@ defmodule BlockScoutWeb.ViewingBlocksTest do uncle = insert(:block, consensus: false) insert(:block_second_degree_relation, uncle_hash: uncle.hash) - :transaction - |> insert() - |> with_block(uncle) + transaction = insert(:transaction) + insert(:transaction_fork, hash: transaction.hash, uncle_hash: uncle.hash) uncle end diff --git a/apps/explorer/lib/explorer/chain/block.ex b/apps/explorer/lib/explorer/chain/block.ex index a9069aa828..f636447f2e 100644 --- a/apps/explorer/lib/explorer/chain/block.ex +++ b/apps/explorer/lib/explorer/chain/block.ex @@ -88,6 +88,7 @@ defmodule Explorer.Chain.Block do has_many(:uncles, through: [:uncle_relations, :uncle]) has_many(:transactions, Transaction) + has_many(:transaction_forks, Transaction.Fork, foreign_key: :uncle_hash) has_many(:rewards, Reward, foreign_key: :block_hash) end diff --git a/apps/explorer/test/support/factory.ex b/apps/explorer/test/support/factory.ex index 05ea2b4749..ba907424db 100644 --- a/apps/explorer/test/support/factory.ex +++ b/apps/explorer/test/support/factory.ex @@ -176,7 +176,9 @@ defmodule Explorer.Factory do with_block(transaction, block, []) end - def with_block(transactions, %Block{} = block) when is_list(transactions) do + # The `transaction.block` must be consensus. Non-consensus blocks can only be associated with the + # `transaction_forks`. + def with_block(transactions, %Block{consensus: true} = block) when is_list(transactions) do Enum.map(transactions, &with_block(&1, block)) end @@ -187,7 +189,9 @@ defmodule Explorer.Factory do def with_block( %Transaction{index: nil} = transaction, - %Block{hash: block_hash, number: block_number}, + # The `transaction.block` must be consensus. Non-consensus blocks can only be associated with the + # `transaction_forks`. + %Block{consensus: true, hash: block_hash, number: block_number}, collated_params ) when is_list(collated_params) do