|
|
|
@ -22,6 +22,133 @@ defmodule Explorer.Chain.Import.Runner.InternalTransactionsTest do |
|
|
|
|
assert :error == Repo.get(Transaction, transaction.hash).status |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
test "simple coin transfer's status becomes :error when its internal_transaction has an error" do |
|
|
|
|
transaction = insert(:transaction) |> with_block(status: :ok) |
|
|
|
|
insert(:pending_block_operation, block_hash: transaction.block_hash, fetch_internal_transactions: true) |
|
|
|
|
|
|
|
|
|
assert :ok == transaction.status |
|
|
|
|
|
|
|
|
|
index = 0 |
|
|
|
|
error = "Out of gas" |
|
|
|
|
|
|
|
|
|
internal_transaction_changes = |
|
|
|
|
make_internal_transaction_changes_for_simple_coin_transfers(transaction, index, error) |
|
|
|
|
|
|
|
|
|
assert {:ok, _} = run_internal_transactions([internal_transaction_changes]) |
|
|
|
|
|
|
|
|
|
assert :error == Repo.get(Transaction, transaction.hash).status |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
test "for block with 2 simple coin transfer's statuses become :error when its both internal_transactions has an error" do |
|
|
|
|
a_block = insert(:block, number: 1000) |
|
|
|
|
transaction1 = insert(:transaction) |> with_block(a_block, status: :ok) |
|
|
|
|
transaction2 = insert(:transaction) |> with_block(a_block, status: :ok) |
|
|
|
|
|
|
|
|
|
insert(:pending_block_operation, block_hash: a_block.hash, fetch_internal_transactions: true) |
|
|
|
|
|
|
|
|
|
assert :ok == transaction1.status |
|
|
|
|
assert :ok == transaction2.status |
|
|
|
|
|
|
|
|
|
index = 0 |
|
|
|
|
error = "Out of gas" |
|
|
|
|
|
|
|
|
|
internal_transaction_changes_1 = |
|
|
|
|
make_internal_transaction_changes_for_simple_coin_transfers(transaction1, index, error) |
|
|
|
|
|
|
|
|
|
internal_transaction_changes_2 = |
|
|
|
|
make_internal_transaction_changes_for_simple_coin_transfers(transaction2, index, error) |
|
|
|
|
|
|
|
|
|
assert {:ok, _} = run_internal_transactions([internal_transaction_changes_1, internal_transaction_changes_2]) |
|
|
|
|
|
|
|
|
|
assert :error == Repo.get(Transaction, transaction1.hash).status |
|
|
|
|
assert :error == Repo.get(Transaction, transaction2.hash).status |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
test "for block with 2 simple coin transfer's only status become :error for tx where internal_transactions has an error" do |
|
|
|
|
a_block = insert(:block, number: 1000) |
|
|
|
|
transaction1 = insert(:transaction) |> with_block(a_block, status: :ok) |
|
|
|
|
transaction2 = insert(:transaction) |> with_block(a_block, status: :ok) |
|
|
|
|
insert(:pending_block_operation, block_hash: a_block.hash, fetch_internal_transactions: true) |
|
|
|
|
|
|
|
|
|
assert :ok == transaction1.status |
|
|
|
|
assert :ok == transaction2.status |
|
|
|
|
|
|
|
|
|
index = 0 |
|
|
|
|
error = "Out of gas" |
|
|
|
|
|
|
|
|
|
internal_transaction_changes_1 = |
|
|
|
|
make_internal_transaction_changes_for_simple_coin_transfers(transaction1, index, error) |
|
|
|
|
|
|
|
|
|
internal_transaction_changes_2 = |
|
|
|
|
make_internal_transaction_changes_for_simple_coin_transfers(transaction2, index, nil) |
|
|
|
|
|
|
|
|
|
assert {:ok, _} = run_internal_transactions([internal_transaction_changes_1, internal_transaction_changes_2]) |
|
|
|
|
|
|
|
|
|
assert :error == Repo.get(Transaction, transaction1.hash).status |
|
|
|
|
assert :ok == Repo.get(Transaction, transaction2.hash).status |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
test "for block with simple coin transfer and method calls, method calls internal txs have correct block_index" do |
|
|
|
|
a_block = insert(:block, number: 1000) |
|
|
|
|
transaction0 = insert(:transaction) |> with_block(a_block, status: :ok) |
|
|
|
|
transaction1 = insert(:transaction) |> with_block(a_block, status: :ok) |
|
|
|
|
transaction2 = insert(:transaction) |> with_block(a_block, status: :ok) |
|
|
|
|
insert(:pending_block_operation, block_hash: a_block.hash, fetch_internal_transactions: true) |
|
|
|
|
|
|
|
|
|
assert :ok == transaction0.status |
|
|
|
|
assert :ok == transaction1.status |
|
|
|
|
assert :ok == transaction2.status |
|
|
|
|
|
|
|
|
|
index = 0 |
|
|
|
|
|
|
|
|
|
internal_transaction_changes_0 = make_internal_transaction_changes(transaction0, index, nil) |
|
|
|
|
internal_transaction_changes_0_1 = make_internal_transaction_changes(transaction0, 1, nil) |
|
|
|
|
|
|
|
|
|
internal_transaction_changes_1 = |
|
|
|
|
make_internal_transaction_changes_for_simple_coin_transfers(transaction1, index, nil) |
|
|
|
|
|
|
|
|
|
internal_transaction_changes_2 = make_internal_transaction_changes(transaction2, index, nil) |
|
|
|
|
internal_transaction_changes_2_1 = make_internal_transaction_changes(transaction2, 1, nil) |
|
|
|
|
|
|
|
|
|
assert {:ok, _} = |
|
|
|
|
run_internal_transactions([ |
|
|
|
|
internal_transaction_changes_0, |
|
|
|
|
internal_transaction_changes_0_1, |
|
|
|
|
internal_transaction_changes_1, |
|
|
|
|
internal_transaction_changes_2, |
|
|
|
|
internal_transaction_changes_2_1 |
|
|
|
|
]) |
|
|
|
|
|
|
|
|
|
assert from(i in InternalTransaction, where: i.transaction_hash == ^transaction0.hash, where: i.index == 0) |
|
|
|
|
|> Repo.one() |
|
|
|
|
|> is_nil() |
|
|
|
|
|
|
|
|
|
assert 1 == Repo.get_by!(InternalTransaction, transaction_hash: transaction0.hash, index: 1).block_index |
|
|
|
|
assert from(i in InternalTransaction, where: i.transaction_hash == ^transaction1.hash) |> Repo.one() |> is_nil() |
|
|
|
|
|
|
|
|
|
assert from(i in InternalTransaction, where: i.transaction_hash == ^transaction2.hash, where: i.index == 0) |
|
|
|
|
|> Repo.one() |
|
|
|
|
|> is_nil() |
|
|
|
|
|
|
|
|
|
assert 4 == Repo.get_by!(InternalTransaction, transaction_hash: transaction2.hash, index: 1).block_index |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
test "simple coin transfer has no internal transaction inserted" do |
|
|
|
|
transaction = insert(:transaction) |> with_block(status: :ok) |
|
|
|
|
insert(:pending_block_operation, block_hash: transaction.block_hash, fetch_internal_transactions: true) |
|
|
|
|
|
|
|
|
|
assert :ok == transaction.status |
|
|
|
|
|
|
|
|
|
index = 0 |
|
|
|
|
|
|
|
|
|
internal_transaction_changes = |
|
|
|
|
make_internal_transaction_changes_for_simple_coin_transfers(transaction, index, nil) |
|
|
|
|
|
|
|
|
|
assert {:ok, _} = run_internal_transactions([internal_transaction_changes]) |
|
|
|
|
|
|
|
|
|
assert !Repo.exists?(from(i in InternalTransaction, where: i.transaction_hash == ^transaction.hash)) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
test "pending transactions don't get updated not its internal_transactions inserted" do |
|
|
|
|
transaction = insert(:transaction) |> with_block(status: :ok) |
|
|
|
|
pending = insert(:transaction) |
|
|
|
@ -31,7 +158,7 @@ defmodule Explorer.Chain.Import.Runner.InternalTransactionsTest do |
|
|
|
|
assert :ok == transaction.status |
|
|
|
|
assert is_nil(pending.block_hash) |
|
|
|
|
|
|
|
|
|
index = 0 |
|
|
|
|
index = 1 |
|
|
|
|
|
|
|
|
|
transaction_changes = make_internal_transaction_changes(transaction, index, nil) |
|
|
|
|
pending_changes = make_internal_transaction_changes(pending, index, nil) |
|
|
|
@ -62,7 +189,7 @@ defmodule Explorer.Chain.Import.Runner.InternalTransactionsTest do |
|
|
|
|
|
|
|
|
|
assert full_block.hash == inserted.block_hash |
|
|
|
|
|
|
|
|
|
index = 0 |
|
|
|
|
index = 1 |
|
|
|
|
|
|
|
|
|
pending_transaction_changes = |
|
|
|
|
pending |
|
|
|
@ -142,17 +269,23 @@ defmodule Explorer.Chain.Import.Runner.InternalTransactionsTest do |
|
|
|
|
|
|
|
|
|
assert full_block.hash == inserted.block_hash |
|
|
|
|
|
|
|
|
|
index = 0 |
|
|
|
|
|
|
|
|
|
transaction_changes = make_internal_transaction_changes(inserted, index, nil) |
|
|
|
|
transaction_changes = make_internal_transaction_changes(inserted, 0, nil) |
|
|
|
|
transaction_changes_2 = make_internal_transaction_changes(inserted, 1, nil) |
|
|
|
|
empty_changes = make_empty_block_changes(empty_block.number) |
|
|
|
|
|
|
|
|
|
assert {:ok, _} = run_internal_transactions([empty_changes, transaction_changes]) |
|
|
|
|
assert {:ok, _} = run_internal_transactions([empty_changes, transaction_changes, transaction_changes_2]) |
|
|
|
|
|
|
|
|
|
assert %{consensus: true} = Repo.get(Block, empty_block.hash) |
|
|
|
|
assert PendingBlockOperation |> Repo.get(empty_block.hash) |> is_nil() |
|
|
|
|
|
|
|
|
|
assert from(i in InternalTransaction, where: i.transaction_hash == ^inserted.hash) |> Repo.one() |> is_nil() == |
|
|
|
|
assert from(i in InternalTransaction, where: i.transaction_hash == ^inserted.hash, where: i.index == 0) |
|
|
|
|
|> Repo.one() |
|
|
|
|
|> is_nil() == |
|
|
|
|
true |
|
|
|
|
|
|
|
|
|
assert from(i in InternalTransaction, where: i.transaction_hash == ^inserted.hash, where: i.index == 1) |
|
|
|
|
|> Repo.one() |
|
|
|
|
|> is_nil() == |
|
|
|
|
false |
|
|
|
|
|
|
|
|
|
assert %{consensus: true} = Repo.get(Block, full_block.hash) |
|
|
|
@ -199,4 +332,28 @@ defmodule Explorer.Chain.Import.Runner.InternalTransactionsTest do |
|
|
|
|
block_number: transaction.block_number |
|
|
|
|
} |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp make_internal_transaction_changes_for_simple_coin_transfers(transaction, index, error) do |
|
|
|
|
%{ |
|
|
|
|
from_address_hash: insert(:address).hash, |
|
|
|
|
to_address_hash: insert(:address).hash, |
|
|
|
|
call_type: :call, |
|
|
|
|
gas: 0, |
|
|
|
|
gas_used: nil, |
|
|
|
|
input: %Data{bytes: <<>>}, |
|
|
|
|
output: |
|
|
|
|
if is_nil(error) do |
|
|
|
|
%Data{bytes: <<0>>} |
|
|
|
|
else |
|
|
|
|
nil |
|
|
|
|
end, |
|
|
|
|
index: index, |
|
|
|
|
trace_address: [], |
|
|
|
|
transaction_hash: transaction.hash, |
|
|
|
|
type: :call, |
|
|
|
|
value: Wei.from(Decimal.new(1), :wei), |
|
|
|
|
error: error, |
|
|
|
|
block_number: transaction.block_number |
|
|
|
|
} |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|