diff --git a/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/parity/fetched_beneficiaries_test.exs b/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/parity/fetched_beneficiaries_test.exs new file mode 100644 index 0000000000..769432b7f4 --- /dev/null +++ b/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/parity/fetched_beneficiaries_test.exs @@ -0,0 +1,247 @@ +defmodule EthereumJSONRPC.Parity.FetchedBeneficiariesTest do + use ExUnit.Case, async: true + + alias EthereumJSONRPC + alias EthereumJSONRPC.Parity.FetchedBeneficiaries + + describe "from_responses/2" do + test "when block is not found" do + block_quantity = EthereumJSONRPC.integer_to_quantity(1_000) + responses = [%{id: 0, result: nil}] + id_to_params = %{0 => %{block_quantity: block_quantity}} + + expected_output = %EthereumJSONRPC.FetchedBeneficiaries{ + errors: [%{code: 404, data: %{block_quantity: block_quantity}, message: "Not Found"}], + params_set: MapSet.new([]) + } + + assert FetchedBeneficiaries.from_responses(responses, id_to_params) == expected_output + end + + test "with an error result" do + block_number = 1_000 + block_quantity = EthereumJSONRPC.integer_to_quantity(block_number) + error_code = -32603 + error_message = "Internal error occurred: {}, this should not be the case with eth_call, most likely a bug." + + responses = [%{id: 0, error: %{code: error_code, message: error_message}}] + + id_to_params = %{0 => %{block_quantity: block_quantity}} + + expected_output = %EthereumJSONRPC.FetchedBeneficiaries{ + errors: [%{code: error_code, data: %{block_quantity: block_quantity}, message: error_message}], + params_set: MapSet.new() + } + + assert FetchedBeneficiaries.from_responses(responses, id_to_params) == expected_output + end + + test "when reward type is external" do + block_hash = "0x52a8d2185282506ce681364d2aa0c085ba45fdeb5d6c0ddec1131617a71ee2ca" + block_number = 1_000 + block_quantity = EthereumJSONRPC.integer_to_quantity(block_number) + hash1 = "0xef481b4e2c3ed62265617f2e9dfcdf3cf3efc11a" + hash2 = "0x523b6539ff08d72a6c8bb598af95bf50c1ea839c" + reward = "0xde0b6b3a7640000" + + responses = [ + %{ + id: 0, + result: [ + %{ + "action" => %{"author" => hash1, "rewardType" => "external", "value" => reward}, + "blockHash" => block_hash, + "blockNumber" => block_number, + "result" => nil, + "subtraces" => 0, + "traceAddress" => [], + "transactionHash" => nil, + "transactionPosition" => nil, + "type" => "reward" + }, + %{ + "action" => %{"author" => hash2, "rewardType" => "external", "value" => reward}, + "blockHash" => "0x52a8d2185282506ce681364d2aa0c085ba45fdeb5d6c0ddec1131617a71ee2ca", + "blockNumber" => block_number, + "result" => nil, + "subtraces" => 0, + "traceAddress" => [], + "transactionHash" => nil, + "transactionPosition" => nil, + "type" => "reward" + } + ] + } + ] + + id_to_params = %{0 => %{block_quantity: block_quantity}} + + expected_output = %EthereumJSONRPC.FetchedBeneficiaries{ + errors: [], + params_set: + MapSet.new([ + %{ + address_hash: hash1, + address_type: :validator, + block_hash: block_hash, + block_number: block_number, + reward: reward + }, + %{ + address_hash: hash2, + address_type: :emission_funds, + block_hash: block_hash, + block_number: block_number, + reward: reward + } + ]) + } + + assert FetchedBeneficiaries.from_responses(responses, id_to_params) == expected_output + end + + test "when reward type is block with uncles" do + block_hash = "0x52a8d2185282506ce681364d2aa0c085ba45fdeb5d6c0ddec1131617a71ee2ca" + block_number = 1_000 + block_quantity = EthereumJSONRPC.integer_to_quantity(block_number) + hash1 = "0xef481b4e2c3ed62265617f2e9dfcdf3cf3efc11a" + hash2 = "0x523b6539ff08d72a6c8bb598af95bf50c1ea839c" + reward = "0xde0b6b3a7640000" + + responses = [ + %{ + id: 0, + result: [ + %{ + "action" => %{"author" => hash1, "rewardType" => "block", "value" => reward}, + "blockHash" => block_hash, + "blockNumber" => block_number, + "result" => nil, + "subtraces" => 0, + "traceAddress" => [], + "transactionHash" => nil, + "transactionPosition" => nil, + "type" => "reward" + }, + %{ + "action" => %{"author" => hash2, "rewardType" => "uncle", "value" => reward}, + "blockHash" => block_hash, + "blockNumber" => block_number, + "result" => nil, + "subtraces" => 0, + "traceAddress" => [], + "transactionHash" => nil, + "transactionPosition" => nil, + "type" => "reward" + } + ] + } + ] + + id_to_params = %{0 => %{block_quantity: block_quantity}} + + expected_output = %EthereumJSONRPC.FetchedBeneficiaries{ + errors: [], + params_set: + MapSet.new([ + %{ + address_hash: hash1, + address_type: :validator, + block_hash: block_hash, + block_number: block_number, + reward: reward + }, + %{ + address_hash: hash2, + address_type: :uncle, + block_hash: block_hash, + block_number: block_number, + reward: reward + } + ]) + } + + assert FetchedBeneficiaries.from_responses(responses, id_to_params) == expected_output + end + + test "ignores non-reward responses" do + block_hash = "0x52a8d2185282506ce681364d2aa0c085ba45fdeb5d6c0ddec1131617a71ee2ca" + block_number = 1_000 + block_quantity = EthereumJSONRPC.integer_to_quantity(block_number) + hash1 = "0xef481b4e2c3ed62265617f2e9dfcdf3cf3efc11a" + hash2 = "0x523b6539ff08d72a6c8bb598af95bf50c1ea839c" + reward = "0xde0b6b3a7640000" + + responses = [ + %{ + id: 0, + result: [ + %{ + "action" => %{ + "callType" => "call", + "from" => hash1, + "gas" => "0x0", + "input" => "0x", + "to" => hash2, + "value" => "0x4a817c800" + }, + "blockHash" => block_hash, + "blockNumber" => block_number, + "result" => %{"gasUsed" => "0x0", "output" => "0x"}, + "subtraces" => 0, + "traceAddress" => [], + "transactionHash" => "0x5acf90f846b8216bdbc309cf4eb24adc69d730bf29304dc0e740cf6df850666e", + "transactionPosition" => 0, + "type" => "call" + }, + %{ + "action" => %{"author" => hash1, "rewardType" => "block", "value" => reward}, + "blockHash" => block_hash, + "blockNumber" => block_number, + "result" => nil, + "subtraces" => 0, + "traceAddress" => [], + "transactionHash" => nil, + "transactionPosition" => nil, + "type" => "reward" + } + ] + } + ] + + id_to_params = %{0 => %{block_quantity: block_quantity}} + + expected_output = %EthereumJSONRPC.FetchedBeneficiaries{ + errors: [], + params_set: + MapSet.new([ + %{ + address_hash: hash1, + address_type: :validator, + block_hash: block_hash, + block_number: block_number, + reward: reward + } + ]) + } + + assert FetchedBeneficiaries.from_responses(responses, id_to_params) == expected_output + end + end + + describe "requests/1" do + test "maps multiple ids to request params map" do + input = %{ + 0 => %{block_quantity: EthereumJSONRPC.integer_to_quantity(0)}, + 1 => %{block_quantity: EthereumJSONRPC.integer_to_quantity(1)} + } + + expected_output = [ + %{id: 0, jsonrpc: "2.0", method: "trace_block", params: [EthereumJSONRPC.integer_to_quantity(0)]}, + %{id: 1, jsonrpc: "2.0", method: "trace_block", params: [EthereumJSONRPC.integer_to_quantity(1)]} + ] + + assert FetchedBeneficiaries.requests(input) == expected_output + end + end +end diff --git a/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/parity_test.exs b/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/parity_test.exs index 33dbbc1c9b..fe52efa6a6 100644 --- a/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/parity_test.exs +++ b/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/parity_test.exs @@ -241,6 +241,7 @@ defmodule EthereumJSONRPC.ParityTest do test "with valid block range, returns {:ok, addresses}", %{ json_rpc_named_arguments: json_rpc_named_arguments } do + block_hash = "0x52a8d2185282506ce681364d2aa0c085ba45fdeb5d6c0ddec1131617a71ee2ca" block_number = 5_080_887 block_quantity = EthereumJSONRPC.integer_to_quantity(block_number) hash1 = "0xef481b4e2c3ed62265617f2e9dfcdf3cf3efc11a" @@ -259,7 +260,7 @@ defmodule EthereumJSONRPC.ParityTest do "rewardType" => "block", "value" => "0xde0b6b3a7640000" }, - "blockHash" => "0x52a8d2185282506ce681364d2aa0c085ba45fdeb5d6c0ddec1131617a71ee2ca", + "blockHash" => block_hash, "blockNumber" => block_number, "result" => nil, "subtraces" => 0, @@ -294,14 +295,27 @@ defmodule EthereumJSONRPC.ParityTest do assert Enum.count(params_set) == 2 - assert %{block_number: block_number, address_hash: hash2, address_type: :validator, reward: "0xde0b6b3a7640000"} in params_set + assert %{ + block_number: block_number, + block_hash: block_hash, + address_hash: hash2, + address_type: :validator, + reward: "0xde0b6b3a7640000" + } in params_set - assert %{block_number: block_number, address_hash: hash1, address_type: :validator, reward: "0xde0b6b3a7640000"} in params_set + assert %{ + block_number: block_number, + block_hash: block_hash, + address_hash: hash1, + address_type: :validator, + reward: "0xde0b6b3a7640000" + } in params_set end test "with 'external' 'rewardType'", %{ json_rpc_named_arguments: json_rpc_named_arguments } do + block_hash = "0xf19a4ea2bb4f2d8839f4c3ec11e0e86c29d57799d7073713958fe1990e197cf5" block_number = 5_609_295 block_quantity = EthereumJSONRPC.integer_to_quantity(block_number) hash1 = "0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca" @@ -320,7 +334,7 @@ defmodule EthereumJSONRPC.ParityTest do "rewardType" => "external", "value" => "0xde0b6b3a7640000" }, - "blockHash" => "0xf19a4ea2bb4f2d8839f4c3ec11e0e86c29d57799d7073713958fe1990e197cf5", + "blockHash" => block_hash, "blockNumber" => 5_609_295, "result" => nil, "subtraces" => 0, @@ -355,10 +369,17 @@ defmodule EthereumJSONRPC.ParityTest do assert Enum.count(params_set) == 2 - assert %{block_number: block_number, address_hash: hash1, address_type: :validator, reward: "0xde0b6b3a7640000"} in params_set + assert %{ + block_number: block_number, + block_hash: block_hash, + address_hash: hash1, + address_type: :validator, + reward: "0xde0b6b3a7640000" + } in params_set assert %{ block_number: block_number, + block_hash: block_hash, address_hash: hash2, address_type: :emission_funds, reward: "0xde0b6b3a7640000" @@ -384,6 +405,7 @@ defmodule EthereumJSONRPC.ParityTest do test "ignores non-reward traces", %{ json_rpc_named_arguments: json_rpc_named_arguments } do + block_hash = "0x6659a4926d833a7eab74379fa647ec74c9f5e65f8029552a35264126560f300a" block_number = 5_077_429 block_quantity = EthereumJSONRPC.integer_to_quantity(block_number) hash1 = "0xcfa53498686e00d3b4b41f3bea61604038eebb58" @@ -405,7 +427,7 @@ defmodule EthereumJSONRPC.ParityTest do "to" => "0xe797a1da01eb0f951e0e400f9343de9d17a06bac", "value" => "0x4a817c800" }, - "blockHash" => "0x6659a4926d833a7eab74379fa647ec74c9f5e65f8029552a35264126560f300a", + "blockHash" => block_hash, "blockNumber" => block_number, "result" => %{"gasUsed" => "0x0", "output" => "0x"}, "subtraces" => 0, @@ -420,7 +442,7 @@ defmodule EthereumJSONRPC.ParityTest do "rewardType" => "block", "value" => "0xde0b6b3a7640000" }, - "blockHash" => "0x6659a4926d833a7eab74379fa647ec74c9f5e65f8029552a35264126560f300a", + "blockHash" => block_hash, "blockNumber" => block_number, "result" => nil, "subtraces" => 0, @@ -435,7 +457,7 @@ defmodule EthereumJSONRPC.ParityTest do "rewardType" => "block", "value" => "0xde0b6b3a7640000" }, - "blockHash" => "0x6659a4926d833a7eab74379fa647ec74c9f5e65f8029552a35264126560f300a", + "blockHash" => block_hash, "blockNumber" => block_number, "result" => nil, "subtraces" => 0, @@ -455,18 +477,34 @@ defmodule EthereumJSONRPC.ParityTest do assert Enum.count(params_set) == 2 - assert %{block_number: block_number, address_hash: hash2, address_type: :validator, reward: "0xde0b6b3a7640000"} in params_set + assert %{ + block_number: block_number, + block_hash: block_hash, + address_hash: hash2, + address_type: :validator, + reward: "0xde0b6b3a7640000" + } in params_set - assert %{block_number: block_number, address_hash: hash1, address_type: :validator, reward: "0xde0b6b3a7640000"} in params_set + assert %{ + block_number: block_number, + block_hash: block_hash, + address_hash: hash1, + address_type: :validator, + reward: "0xde0b6b3a7640000" + } in params_set end test "with multiple blocks with repeat beneficiaries", %{ json_rpc_named_arguments: json_rpc_named_arguments } do + block_hash1 = "0xd2170e27857452d130128ac94c5258828a22cc69b07ab6e7fc12f7dd9938ff1c" block_number1 = 5_080_886 block_quantity1 = EthereumJSONRPC.integer_to_quantity(block_number1) + + block_hash2 = "0x52a8d2185282506ce681364d2aa0c085ba45fdeb5d6c0ddec1131617a71ee2ca" block_number2 = 5_080_887 block_quantity2 = EthereumJSONRPC.integer_to_quantity(block_number2) + hash1 = "0xadc702c4bb09fbc502dd951856b9c7a1528a88de" hash2 = "0xef481b4e2c3ed62265617f2e9dfcdf3cf3efc11a" hash3 = "0x523b6539ff08d72a6c8bb598af95bf50c1ea839c" @@ -485,6 +523,7 @@ defmodule EthereumJSONRPC.ParityTest do "rewardType" => "block", "value" => "0xde0b6b3a7640000" }, + "blockHash" => block_hash1, "blockNumber" => block_number1, "result" => nil, "subtraces" => 0, @@ -499,6 +538,7 @@ defmodule EthereumJSONRPC.ParityTest do "rewardType" => "block", "value" => "0xde0b6b3a7640000" }, + "blockHash" => block_hash1, "blockNumber" => block_number1, "result" => nil, "subtraces" => 0, @@ -520,6 +560,7 @@ defmodule EthereumJSONRPC.ParityTest do "rewardType" => "block", "value" => "0xde0b6b3a7640000" }, + "blockHash" => block_hash2, "blockNumber" => block_number2, "result" => nil, "subtraces" => 0, @@ -534,6 +575,7 @@ defmodule EthereumJSONRPC.ParityTest do "rewardType" => "block", "value" => "0xde0b6b3a7640000" }, + "blockHash" => block_hash2, "blockNumber" => block_number2, "result" => nil, "subtraces" => 0, @@ -551,17 +593,44 @@ defmodule EthereumJSONRPC.ParityTest do end assert {:ok, %FetchedBeneficiaries{params_set: params_set}} = - EthereumJSONRPC.Parity.fetch_beneficiaries(5_080_886..5_080_887, json_rpc_named_arguments) + EthereumJSONRPC.Parity.fetch_beneficiaries( + block_number1..block_number2, + json_rpc_named_arguments + ) assert Enum.count(params_set) == 4 - assert %{block_number: block_number1, address_hash: hash3, address_type: :validator, reward: "0xde0b6b3a7640000"} in params_set + assert %{ + block_number: block_number1, + block_hash: block_hash1, + address_hash: hash1, + address_type: :validator, + reward: "0xde0b6b3a7640000" + } in params_set - assert %{block_number: block_number2, address_hash: hash3, address_type: :validator, reward: "0xde0b6b3a7640000"} in params_set + assert %{ + block_number: block_number1, + block_hash: block_hash1, + address_hash: hash3, + address_type: :validator, + reward: "0xde0b6b3a7640000" + } in params_set - assert %{block_number: block_number2, address_hash: hash2, address_type: :validator, reward: "0xde0b6b3a7640000"} in params_set + assert %{ + block_number: block_number2, + block_hash: block_hash2, + address_hash: hash2, + address_type: :validator, + reward: "0xde0b6b3a7640000" + } in params_set - assert %{block_number: block_number1, address_hash: hash1, address_type: :validator, reward: "0xde0b6b3a7640000"} in params_set + assert %{ + block_number: block_number2, + block_hash: block_hash2, + address_hash: hash3, + address_type: :validator, + reward: "0xde0b6b3a7640000" + } in params_set end test "with error, returns {:error, reason}", %{