Skip to content

Commit

Permalink
Merge pull request blockscout#221 from poanetwork/always-show-create-…
Browse files Browse the repository at this point in the history
…internal-transactions-#187

Only hide "call" type internal transactions
  • Loading branch information
jimmay5469 authored May 31, 2018
2 parents 8f2458b + 2ff420a commit e05e8b9
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 24 deletions.
15 changes: 10 additions & 5 deletions apps/explorer/lib/explorer/chain.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1932,11 +1932,16 @@ defmodule Explorer.Chain do
defp where_transaction_has_multiple_internal_transactions(query) do
where(
query,
[_it, transaction],
fragment(
"(SELECT COUNT(sibling.id) FROM internal_transactions as sibling WHERE sibling.transaction_hash = ?) > 1",
transaction.hash
)
[internal_transaction, transaction],
internal_transaction.type != ^:call or
fragment(
"""
(SELECT COUNT(sibling.id)
FROM internal_transactions AS sibling
WHERE sibling.transaction_hash = ?)
""",
transaction.hash
) > 1
)
end
end
57 changes: 40 additions & 17 deletions apps/explorer/test/explorer/chain_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ defmodule Explorer.ChainTest do
%InternalTransaction{id: second_id} =
insert(:internal_transaction, index: 1, transaction_hash: transaction.hash, to_address_hash: address.hash)

result = address |> Chain.address_to_internal_transactions() |> Enum.map(fn it -> it.id end)
result = address |> Chain.address_to_internal_transactions() |> Enum.map(& &1.id)
assert Enum.member?(result, first_id)
assert Enum.member?(result, second_id)
end
Expand Down Expand Up @@ -606,18 +606,36 @@ defmodule Explorer.ChainTest do
address
|> Chain.address_to_internal_transactions()
|> Map.get(:entries, [])
|> Enum.map(fn internal_transaction -> internal_transaction.id end)
|> Enum.map(& &1.id)

assert [second_pending, first_pending, sixth, fifth, fourth, third, second, first] == result
end

test "Excludes internal transactions where they are alone in the parent transaction" do
test "Excludes internal transactions of type `call` when they are alone in the parent transaction" do
address = insert(:address)
block = insert(:block)
transaction = insert(:transaction, block_hash: block.hash, index: 0, to_address_hash: address.hash)
insert(:internal_transaction, index: 0, to_address_hash: address.hash, transaction_hash: transaction.hash)
insert(:internal_transaction_call, index: 0, to_address_hash: address.hash, transaction_hash: transaction.hash)

assert %{entries: []} = Chain.address_to_internal_transactions(address)
assert Enum.empty?(Chain.address_to_internal_transactions(address))
end

test "Includes internal transactions of type `create` even when they are alone in the parent transaction" do
address = insert(:address)
block = insert(:block)
transaction = insert(:transaction, block_hash: block.hash, index: 0, to_address_hash: address.hash)

expected =
insert(
:internal_transaction_create,
index: 0,
from_address_hash: address.hash,
transaction_hash: transaction.hash
)

actual = Enum.at(Chain.address_to_internal_transactions(address), 0)

assert actual.id == expected.id
end
end

Expand All @@ -644,7 +662,7 @@ defmodule Explorer.ChainTest do
transaction.hash
|> Chain.transaction_hash_to_internal_transactions()
|> Map.get(:entries, [])
|> Enum.map(fn it -> it.id end)
|> Enum.map(& &1.id)

assert 2 == length(results)
assert Enum.member?(results, first.id)
Expand All @@ -653,16 +671,14 @@ defmodule Explorer.ChainTest do

test "with transaction with internal transactions loads associations with in necessity_by_association" do
%Transaction{hash: hash} = insert(:transaction)
insert(:internal_transaction, transaction_hash: hash, index: 0)
insert(:internal_transaction, transaction_hash: hash, index: 1)
insert(:internal_transaction_create, transaction_hash: hash, index: 0)

assert [
%InternalTransaction{
from_address: %Ecto.Association.NotLoaded{},
to_address: %Ecto.Association.NotLoaded{},
transaction: %Ecto.Association.NotLoaded{}
}
| _
] = Chain.transaction_hash_to_internal_transactions(hash).entries

assert [
Expand All @@ -671,7 +687,6 @@ defmodule Explorer.ChainTest do
to_address: nil,
transaction: %Transaction{}
}
| _
] =
Chain.transaction_hash_to_internal_transactions(
hash,
Expand All @@ -683,16 +698,24 @@ defmodule Explorer.ChainTest do
).entries
end

test "excludes internal transaction with no siblings in the transaction" do
test "Excludes internal transactions of type call with no siblings in the transaction" do
block = insert(:block)
%Transaction{hash: hash} = insert(:transaction, block_hash: block.hash, index: 0)
insert(:internal_transaction, transaction_hash: hash, index: 0)
insert(:internal_transaction_call, transaction_hash: hash, index: 0)

result =
hash
|> Chain.transaction_hash_to_internal_transactions()
result = Chain.transaction_hash_to_internal_transactions(hash)

assert Enum.empty?(result)
end

test "Includes internal transactions of type `create` even when they are alone in the parent transaction" do
block = insert(:block)
transaction = insert(:transaction, block_hash: block.hash, index: 0)
expected = insert(:internal_transaction_create, index: 0, transaction_hash: transaction.hash)

actual = Enum.at(Chain.transaction_hash_to_internal_transactions(transaction.hash), 0)

assert %{entries: []} = result
assert actual.id == expected.id
end

test "returns the internal transactions in index order" do
Expand All @@ -704,7 +727,7 @@ defmodule Explorer.ChainTest do
result =
hash
|> Chain.transaction_hash_to_internal_transactions()
|> Enum.map(fn it -> it.id end)
|> Enum.map(& &1.id)

assert [first_id, second_id] == result
end
Expand Down
35 changes: 33 additions & 2 deletions apps/explorer/test/support/factory.ex
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,17 @@ defmodule Explorer.Factory do
internal_transaction_factory(type)
end

# TODO add call, reward, and suicide
def internal_transaction_create_factory do
internal_transaction_factory(:create)
end

def internal_transaction_call_factory do
internal_transaction_factory(:call)
end

# TODO add reward and suicide
def internal_transaction_type do
Enum.random(~w(create)a)
Enum.random(~w(call create)a)
end

def log_factory do
Expand Down Expand Up @@ -197,6 +205,29 @@ defmodule Explorer.Factory do
Repo.preload(block_transaction, [:block, :receipt])
end

defp internal_transaction_factory(:call = type) do
gas = Enum.random(21_000..100_000)
gas_used = Enum.random(0..gas)

block = insert(:block)
transaction = insert(:transaction, block_hash: block.hash, index: 0)
receipt = insert(:receipt, transaction_hash: transaction.hash, transaction_index: transaction.index)

%InternalTransaction{
from_address_hash: insert(:address).hash,
to_address_hash: insert(:address).hash,
call_type: :delegatecall,
gas: gas,
gas_used: gas_used,
output: %Data{bytes: <<1>>},
# caller MUST suppy `index`
trace_address: [],
transaction_hash: receipt.transaction_hash,
type: type,
value: sequence("internal_transaction_value", &Decimal.new(&1))
}
end

defp internal_transaction_factory(:create = type) do
gas = Enum.random(21_000..100_000)
gas_used = Enum.random(0..gas)
Expand Down

0 comments on commit e05e8b9

Please sign in to comment.