Calculate gas payments for all blocks in batch in SQL

pull/1376/head
Luke Imhoff 6 years ago
parent 4c634eb9a6
commit 00e136e20c
  1. 21
      apps/explorer/lib/explorer/chain.ex
  2. 46
      apps/explorer/test/explorer/chain_test.exs
  3. 25
      apps/indexer/lib/indexer/block/uncataloged_rewards/importer.ex

@ -352,6 +352,27 @@ defmodule Explorer.Chain do
Repo.one!(query)
end
@doc """
The `t:Explorer.Chain.Wei.t/0` paid to the miners of the `t:Explorer.Chain.Block.t/0`s with `hash`
`Explorer.Chain.Hash.Full.t/0` by the signers of the transactions in those blocks to cover the gas fee
(`gas_used * gas_price`).
"""
@spec gas_payment_by_block_hash([Hash.Full.t()]) :: %{Hash.Full.t() => Wei.t()}
def gas_payment_by_block_hash(block_hashes) when is_list(block_hashes) do
query =
from(
block in Block,
left_join: transaction in assoc(block, :transactions),
where: block.hash in ^block_hashes and block.consensus == true,
group_by: block.hash,
select: {block.hash, %Wei{value: coalesce(sum(transaction.gas_used * transaction.gas_price), 0)}}
)
query
|> Repo.all()
|> Enum.into(%{})
end
@doc """
Finds all `t:Explorer.Chain.Transaction.t/0`s in the `t:Explorer.Chain.Block.t/0`.

@ -2279,6 +2279,52 @@ defmodule Explorer.ChainTest do
end
end
describe "gas_payment_by_block_hash/1" do
setup do
number = 1
%{consensus_block: insert(:block, number: number, consensus: true), number: number}
end
test "without consensus block hash has no key", %{consensus_block: consensus_block, number: number} do
non_consensus_block = insert(:block, number: number, consensus: false)
:transaction
|> insert(gas_price: 1)
|> with_block(consensus_block, gas_used: 1)
:transaction
|> insert(gas_price: 1)
|> with_block(consensus_block, gas_used: 2)
assert Chain.gas_payment_by_block_hash([non_consensus_block.hash]) == %{}
end
test "with consensus block hash without transactions has key with 0 value", %{
consensus_block: %Block{hash: consensus_block_hash}
} do
assert Chain.gas_payment_by_block_hash([consensus_block_hash]) == %{
consensus_block_hash => %Wei{value: Decimal.new(0)}
}
end
test "with consensus block hash with transactions has key with value", %{
consensus_block: %Block{hash: consensus_block_hash} = consensus_block
} do
:transaction
|> insert(gas_price: 1)
|> with_block(consensus_block, gas_used: 2)
:transaction
|> insert(gas_price: 3)
|> with_block(consensus_block, gas_used: 4)
assert Chain.gas_payment_by_block_hash([consensus_block_hash]) == %{
consensus_block_hash => %Wei{value: Decimal.new(14)}
}
end
end
describe "missing_block_number_ranges/1" do
# 0000
test "0..0 without blocks" do

@ -48,13 +48,16 @@ defmodule Indexer.Block.UncatalogedRewards.Importer do
end
defp add_gas_payments(beneficiaries) do
Enum.map(beneficiaries, fn beneficiary ->
case beneficiary.address_type do
:validator ->
gas_payment = gas_payment(beneficiary)
gas_payment_by_block_hash =
beneficiaries
|> Stream.filter(&(&1.address_type == :validator))
|> Enum.map(& &1.block_hash)
|> Chain.gas_payment_by_block_hash()
Enum.map(beneficiaries, fn %{block_hash: block_hash} = beneficiary ->
case gas_payment_by_block_hash do
%{^block_hash => gas_payment} ->
{:ok, minted} = Wei.cast(beneficiary.reward)
%{beneficiary | reward: Wei.sum(minted, gas_payment)}
_ ->
@ -63,18 +66,6 @@ defmodule Indexer.Block.UncatalogedRewards.Importer do
end)
end
defp gas_payment(beneficiary) do
{:ok, initial} = Wei.cast(0)
beneficiary.block_number
|> Chain.get_transactions_of_block_number()
|> Enum.reduce(initial, fn %Transaction{gas_price: gas_price, gas_used: gas_used}, acc ->
gas_price
|> Wei.mult(gas_used)
|> Wei.sum(acc)
end)
end
defp insert_reward_group([]), do: :empty
defp insert_reward_group(rewards) do

Loading…
Cancel
Save