Only hide "call" type internal transactions
pull/235/head
Jimmy Lauzau 7 years ago committed by GitHub
commit e05e8b9c25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      apps/explorer/lib/explorer/chain.ex
  2. 57
      apps/explorer/test/explorer/chain_test.exs
  3. 35
      apps/explorer/test/support/factory.ex

@ -1932,11 +1932,16 @@ defmodule Explorer.Chain do
defp where_transaction_has_multiple_internal_transactions(query) do
where(
query,
[_it, transaction],
[internal_transaction, transaction],
internal_transaction.type != ^:call or
fragment(
"(SELECT COUNT(sibling.id) FROM internal_transactions as sibling WHERE sibling.transaction_hash = ?) > 1",
"""
(SELECT COUNT(sibling.id)
FROM internal_transactions AS sibling
WHERE sibling.transaction_hash = ?)
""",
transaction.hash
)
) > 1
)
end
end

@ -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
@ -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
@ -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)
@ -653,8 +671,7 @@ 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{
@ -662,7 +679,6 @@ defmodule Explorer.ChainTest do
to_address: %Ecto.Association.NotLoaded{},
transaction: %Ecto.Association.NotLoaded{}
}
| _
] = Chain.transaction_hash_to_internal_transactions(hash).entries
assert [
@ -671,7 +687,6 @@ defmodule Explorer.ChainTest do
to_address: nil,
transaction: %Transaction{}
}
| _
] =
Chain.transaction_hash_to_internal_transactions(
hash,
@ -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
@ -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

@ -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
@ -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)

Loading…
Cancel
Save