Skip to content

Commit 48fe3a4

Browse files
authored
Merge pull request blockscout#1184 from poanetwork/wsa-save-emission-reward-data-from-blockchain-call
Save reward data from blockchain call
2 parents 17292ad + e1b3d43 commit 48fe3a4

File tree

21 files changed

+786
-79
lines changed

21 files changed

+786
-79
lines changed

apps/block_scout_web/test/block_scout_web/controllers/api/rpc/address_controller_test.exs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2053,7 +2053,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
20532053
end
20542054

20552055
test "returns all the required fields", %{conn: conn} do
2056-
%{block_range: range} = block_reward = insert(:block_reward)
2056+
%{block_range: range} = emission_reward = insert(:emission_reward)
20572057

20582058
block = insert(:block, number: Enum.random(Range.new(range.from, range.to)))
20592059

@@ -2062,7 +2062,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
20622062
|> with_block(block, gas_used: 1)
20632063

20642064
expected_reward =
2065-
block_reward.reward
2065+
emission_reward.reward
20662066
|> Wei.to(:wei)
20672067
|> Decimal.add(Decimal.new(1))
20682068
|> Wei.from(:wei)
@@ -2092,7 +2092,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
20922092
end
20932093

20942094
test "with a block with one transaction", %{conn: conn} do
2095-
%{block_range: range} = block_reward = insert(:block_reward)
2095+
%{block_range: range} = emission_reward = insert(:emission_reward)
20962096

20972097
block = insert(:block, number: Enum.random(Range.new(range.from, range.to)))
20982098

@@ -2101,7 +2101,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
21012101
|> with_block(block, gas_used: 1)
21022102

21032103
expected_reward =
2104-
block_reward.reward
2104+
emission_reward.reward
21052105
|> Wei.to(:wei)
21062106
|> Decimal.add(Decimal.new(1))
21072107
|> Wei.from(:wei)
@@ -2131,7 +2131,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
21312131
end
21322132

21332133
test "with pagination options", %{conn: conn} do
2134-
%{block_range: range} = block_reward = insert(:block_reward)
2134+
%{block_range: range} = emission_reward = insert(:emission_reward)
21352135

21362136
block_numbers = Range.new(range.from, range.to)
21372137

@@ -2147,7 +2147,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
21472147
|> with_block(block2, gas_used: 2)
21482148

21492149
expected_reward =
2150-
block_reward.reward
2150+
emission_reward.reward
21512151
|> Wei.to(:wei)
21522152
|> Decimal.add(Decimal.new(4))
21532153
|> Wei.from(:wei)

apps/block_scout_web/test/block_scout_web/controllers/api/rpc/block_controller_test.exs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ defmodule BlockScoutWeb.API.RPC.BlockControllerTest do
4141
end
4242

4343
test "with a valid block", %{conn: conn} do
44-
%{block_range: range} = block_reward = insert(:block_reward)
44+
%{block_range: range} = emission_reward = insert(:emission_reward)
4545
block = insert(:block, number: Enum.random(Range.new(range.from, range.to)))
4646

4747
:transaction
4848
|> insert(gas_price: 1)
4949
|> with_block(block, gas_used: 1)
5050

5151
expected_reward =
52-
block_reward.reward
52+
emission_reward.reward
5353
|> Wei.to(:wei)
5454
|> Decimal.add(Decimal.new(1))
5555
|> Decimal.to_string(:normal)

apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/fetched_beneficiary.ex

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@ defmodule EthereumJSONRPC.FetchedBeneficiary do
33
A single balance request params for the beneficiary of a block.
44
"""
55

6-
@type params :: %{address_hash: EthereumJSONRPC.hash(), block_number: non_neg_integer()}
6+
alias Explorer.Chain.Block.Reward.AddressType
7+
alias Explorer.Chain.Hash
8+
9+
@type params :: %{
10+
address_hash: EthereumJSONRPC.hash(),
11+
address_type: AddressType.t(),
12+
block_hash: Hash.Full.t(),
13+
block_number: non_neg_integer(),
14+
reward: String.t()
15+
}
716
@type error :: %{code: integer(), message: String.t(), data: %{block_number: non_neg_integer()}}
817
end

apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/parity/fetched_beneficiaries.ex

Lines changed: 96 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,64 @@ defmodule EthereumJSONRPC.Parity.FetchedBeneficiaries do
66
import EthereumJSONRPC, only: [quantity_to_integer: 1]
77

88
@doc """
9-
Converts `responses` to `t/0`.
9+
Converts `responses` to `EthereumJSONRPC.FetchedBeneficiaries.t()`.
10+
11+
responses - List with trace_block responses
12+
id_to_params - Maps request id to query params
13+
14+
## Examples
15+
iex> EthereumJSONRPC.Parity.FetchedBeneficiaries.from_responses(
16+
...> [
17+
...> %{
18+
...> id: 0,
19+
...> result: [
20+
...> %{
21+
...> "action" => %{"author" => "0x1", "rewardType" => "external", "value" => "0x0"},
22+
...> "blockHash" => "0xFFF",
23+
...> "blockNumber" => 12,
24+
...> "result" => nil,
25+
...> "subtraces" => 0,
26+
...> "traceAddress" => [],
27+
...> "transactionHash" => nil,
28+
...> "transactionPosition" => nil,
29+
...> "type" => "reward"
30+
...> },
31+
...> %{
32+
...> "action" => %{"author" => "0x2", "rewardType" => "external", "value" => "0x0"},
33+
...> "blockHash" => "0x52a8d2185282506ce681364d2aa0c085ba45fdeb5d6c0ddec1131617a71ee2ca",
34+
...> "blockHash" => "0xFFF",
35+
...> "blockNumber" => 12,
36+
...> "result" => nil,
37+
...> "subtraces" => 0,
38+
...> "traceAddress" => [],
39+
...> "transactionHash" => nil,
40+
...> "transactionPosition" => nil,
41+
...> "type" => "reward"
42+
...> }
43+
...> ]
44+
...> }
45+
...> ],
46+
...> %{0 => %{block_quantity: "0xC"}}
47+
...> )
48+
%EthereumJSONRPC.FetchedBeneficiaries{
49+
errors: [],
50+
params_set: #MapSet<[
51+
%{
52+
address_hash: "0x1",
53+
address_type: :validator,
54+
block_hash: "0xFFF",
55+
block_number: 12,
56+
reward: "0x0"
57+
},
58+
%{
59+
address_hash: "0x2",
60+
address_type: :emission_funds,
61+
block_hash: "0xFFF",
62+
block_number: 12,
63+
reward: "0x0"
64+
}
65+
]>
66+
}
1067
"""
1168
def from_responses(responses, id_to_params) when is_list(responses) and is_map(id_to_params) do
1269
responses
@@ -69,26 +126,52 @@ defmodule EthereumJSONRPC.Parity.FetchedBeneficiaries do
69126
end
70127

71128
defp traces_to_params_set(traces, block_number) when is_list(traces) and is_integer(block_number) do
72-
Enum.reduce(traces, MapSet.new(), fn trace, acc ->
73-
MapSet.union(acc, trace_to_params_set(trace, block_number))
129+
traces
130+
|> Stream.filter(&(&1["type"] == "reward"))
131+
|> Stream.with_index()
132+
|> Enum.reduce(MapSet.new(), fn {trace, index}, acc ->
133+
MapSet.union(acc, trace_to_params_set(trace, block_number, index))
74134
end)
75135
end
76136

77-
defp trace_to_params_set(%{"action" => %{"callType" => _}, "blockNumber" => block_number}, block_number),
78-
do: MapSet.new()
79-
80-
defp trace_to_params_set(%{"type" => type, "blockNumber" => block_number}, block_number)
81-
when type in ~w(create suicide),
82-
do: MapSet.new()
83-
84137
defp trace_to_params_set(
85138
%{
86-
"action" => %{"rewardType" => reward_type, "author" => address_hash_data},
139+
"action" => %{
140+
"rewardType" => reward_type,
141+
"author" => address_hash_data,
142+
"value" => reward_value
143+
},
144+
"blockHash" => block_hash,
87145
"blockNumber" => block_number
88146
},
89-
block_number
147+
block_number,
148+
index
90149
)
91150
when is_integer(block_number) and reward_type in ~w(block external uncle) do
92-
MapSet.new([%{address_hash: address_hash_data, block_number: block_number}])
151+
MapSet.new([
152+
%{
153+
address_hash: address_hash_data,
154+
block_hash: block_hash,
155+
block_number: block_number,
156+
reward: reward_value,
157+
address_type: get_address_type(reward_type, index)
158+
}
159+
])
93160
end
161+
162+
# Beneficiary's address type will depend on the responses' action.rewardType,
163+
# which will vary depending on which network is being indexed
164+
#
165+
# On POA networks, rewardType will always be external and the type of the address being
166+
# rewarded will depend on its position.
167+
# First address will always be the validator's while the second will be the EmissionsFunds address
168+
#
169+
# On PoW networks, like Ethereum, the reward type will already specify the type for the
170+
# address being rewarded
171+
# The rewardType "block" will show the reward for the consensus block validator
172+
# The rewardType "uncle" will show reward for validating an uncle block
173+
defp get_address_type(reward_type, index) when reward_type == "external" and index == 0, do: :validator
174+
defp get_address_type(reward_type, index) when reward_type == "external" and index == 1, do: :emission_funds
175+
defp get_address_type(reward_type, _index) when reward_type == "block", do: :validator
176+
defp get_address_type(reward_type, _index) when reward_type == "uncle", do: :uncle
94177
end

apps/ethereum_jsonrpc/mix.exs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ defmodule EthereumJsonrpc.MixProject do
8787
# `:verify_fun` for `Socket.Web.connect`
8888
{:ssl_verify_fun, "~> 1.1"},
8989
# `EthereumJSONRPC.WebSocket`
90-
{:websocket_client, "~> 1.3"}
90+
{:websocket_client, "~> 1.3"},
91+
{:decimal, "~> 1.0"},
92+
{:decorator, "~> 1.2"}
9193
]
9294
end
9395
end

0 commit comments

Comments
 (0)