Nil out receipt fields on transactions from blocks that go non-consensus

pull/833/head
Luke Imhoff 6 years ago
parent c16ffadc13
commit 3debed6d03
  1. 51
      apps/explorer/lib/explorer/chain/import.ex
  2. 114
      apps/explorer/test/explorer/chain/import_test.exs

@ -3,7 +3,7 @@ defmodule Explorer.Chain.Import do
Bulk importing of data into `Explorer.Repo`
"""
import Ecto.Query, only: [from: 2]
import Ecto.Query, only: [from: 2, update: 2]
alias Ecto.{Changeset, Multi}
@ -380,6 +380,12 @@ defmodule Explorer.Chain.Import do
blocks_timeout = options[:blocks][:timeout] || @insert_blocks_timeout
multi
|> Multi.run(:fork_transactions, fn _ ->
fork_transactions(blocks_changes, %{
timeout: options[:transactions][:timeout] || @insert_transactions_timeout,
timestamps: timestamps
})
end)
|> Multi.run(:lose_consenus, fn _ ->
lose_consensus(blocks_changes, %{timeout: blocks_timeout, timestamps: timestamps})
end)
@ -974,6 +980,49 @@ defmodule Explorer.Chain.Import do
{:ok, inserted}
end
defp fork_transactions(blocks_changes, %{
timeout: timeout,
timestamps: %{updated_at: updated_at}
})
when is_list(blocks_changes) do
query =
Transaction
|> where_forked(blocks_changes)
|> update(
set: [
block_hash: nil,
block_number: nil,
gas_used: nil,
cumulative_gas_used: nil,
index: nil,
internal_transactions_indexed_at: nil,
status: nil,
updated_at: ^updated_at
]
)
try do
{_, result} = Repo.update_all(query, [], timeout: timeout, returning: [:hash])
{:ok, result}
rescue
postgrex_error in Postgrex.Error ->
{:error, %{exception: postgrex_error, blocks_changes: blocks_changes}}
end
end
defp where_forked(query, blocks_changes) when is_list(blocks_changes) do
Enum.reduce(blocks_changes, query, fn %{consensus: consensus, hash: hash, number: number}, acc ->
case consensus do
false ->
from(transaction in acc, or_where: transaction.block_hash == ^hash and transaction.block_number == ^number)
true ->
from(transaction in acc, or_where: transaction.block_hash != ^hash and transaction.block_number == ^number)
end
end)
end
defp lose_consensus(blocks_changes, %{timeout: timeout, timestamps: %{updated_at: updated_at}})
when is_list(blocks_changes) do
ordered_block_number =

@ -1235,7 +1235,121 @@ defmodule Explorer.Chain.ImportTest do
timestamp: timestamp,
total_difficulty: ^total_difficulty_before
} = Repo.get(Block, block_hash_before)
assert DateTime.compare(timestamp, timestamp_before) == :eq
end
test "reorganizations nils transaction receipt fields for transactions that end up in non-consensus blocks" do
block_number = 0
miner_hash_before = address_hash()
from_address_hash_before = address_hash()
block_hash_before = block_hash()
index_before = 0
transaction_hash = transaction_hash()
assert {:ok, _} =
Import.all(%{
addresses: %{
params: [
%{hash: miner_hash_before},
%{hash: from_address_hash_before}
]
},
blocks: %{
params: [
%{
consensus: true,
difficulty: 0,
gas_limit: 0,
gas_used: 0,
hash: block_hash_before,
miner_hash: miner_hash_before,
nonce: 0,
number: block_number,
parent_hash: block_hash(),
size: 0,
timestamp: Timex.parse!("2019-01-01T01:00:00Z", "{ISO:Extended:Z}"),
total_difficulty: 0
}
]
},
transactions: %{
params: [
%{
block_hash: block_hash_before,
block_number: block_number,
from_address_hash: from_address_hash_before,
gas: 21_000,
gas_price: 1,
gas_used: 21_000,
cumulative_gas_used: 21_000,
hash: transaction_hash,
index: index_before,
input: "0x",
nonce: 0,
r: 0,
s: 0,
v: 0,
value: 0,
status: :ok
}
],
on_conflict: :replace_all
}
})
%Block{consensus: true, number: ^block_number} = Repo.get(Block, block_hash_before)
transaction_before = Repo.get!(Transaction, transaction_hash)
refute transaction_before.block_hash == nil
refute transaction_before.block_number == nil
refute transaction_before.gas_used == nil
refute transaction_before.cumulative_gas_used == nil
refute transaction_before.index == nil
refute transaction_before.status == nil
miner_hash_after = address_hash()
from_address_hash_after = address_hash()
block_hash_after = block_hash()
assert {:ok, _} =
Import.all(%{
addresses: %{
params: [
%{hash: miner_hash_after},
%{hash: from_address_hash_after}
]
},
blocks: %{
params: [
%{
consensus: true,
difficulty: 1,
gas_limit: 1,
gas_used: 1,
hash: block_hash_after,
miner_hash: miner_hash_after,
nonce: 1,
number: block_number,
parent_hash: block_hash(),
size: 1,
timestamp: Timex.parse!("2019-01-01T02:00:00Z", "{ISO:Extended:Z}"),
total_difficulty: 1
}
]
}
})
transaction_after = Repo.get!(Transaction, transaction_hash)
assert transaction_after.block_hash == nil
assert transaction_after.block_number == nil
assert transaction_after.gas_used == nil
assert transaction_after.cumulative_gas_used == nil
assert transaction_after.index == nil
assert transaction_after.status == nil
end
end
end

Loading…
Cancel
Save