fix: add fields for contrat filter performance

pull/1966/head
zachdaniel 6 years ago
parent 5fa2dd670a
commit d2336bccc8
  1. 1
      CHANGELOG.md
  2. 4
      apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/contract_controller.ex
  3. 19
      apps/block_scout_web/lib/block_scout_web/etherscan.ex
  4. 12
      apps/block_scout_web/lib/block_scout_web/views/api/rpc/contract_view.ex
  5. 18
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs
  6. 20
      apps/block_scout_web/test/block_scout_web/controllers/api/v1/decompiled_smart_contract_controller_test.exs
  7. 137
      apps/explorer/lib/explorer/chain.ex
  8. 4
      apps/explorer/lib/explorer/chain/address.ex
  9. 14
      apps/explorer/lib/explorer/chain/import/runner/addresses.ex
  10. 2
      apps/explorer/lib/explorer/smart_contract/solc_downloader.ex
  11. 14
      apps/explorer/priv/repo/migrations/20190516140202_add_address_hash_index_to_decompiled_smart_contracts.exs
  12. 18
      apps/explorer/priv/repo/migrations/20190516160535_add_decompiled_and_verified_flag_to_addresses.exs
  13. 6
      apps/explorer/test/explorer/chain_test.exs
  14. 5
      apps/explorer/test/support/factory.ex

@ -55,6 +55,7 @@
- [#1960](https://github.com/poanetwork/blockscout/pull/1960) - do not remove bold text in decompiled contacts - [#1960](https://github.com/poanetwork/blockscout/pull/1960) - do not remove bold text in decompiled contacts
- [#1917](https://github.com/poanetwork/blockscout/pull/1917) - Force block refetch if transaction is re-collated in a different block - [#1917](https://github.com/poanetwork/blockscout/pull/1917) - Force block refetch if transaction is re-collated in a different block
- [#1992](https://github.com/poanetwork/blockscout/pull/1992) - fix: support https for wobserver polling - [#1992](https://github.com/poanetwork/blockscout/pull/1992) - fix: support https for wobserver polling
- [#1966](https://github.com/poanetwork/blockscout/pull/1966) - fix: add fields for contract filter performance
### Chore ### Chore

@ -98,10 +98,10 @@ defmodule BlockScoutWeb.API.RPC.ContractController do
Chain.list_decompiled_contracts(page_size, offset, not_decompiled_with_version) Chain.list_decompiled_contracts(page_size, offset, not_decompiled_with_version)
:unverified -> :unverified ->
Chain.list_unverified_contracts(page_size, offset) Chain.list_unordered_unverified_contracts(page_size, offset)
:not_decompiled -> :not_decompiled ->
Chain.list_not_decompiled_contracts(page_size, offset) Chain.list_unordered_not_decompiled_contracts(page_size, offset)
:empty -> :empty ->
Chain.list_empty_contracts(page_size, offset) Chain.list_empty_contracts(page_size, offset)

@ -862,11 +862,6 @@ defmodule BlockScoutWeb.Etherscan do
name: "Contract", name: "Contract",
fields: %{ fields: %{
"Address" => @address_hash_type, "Address" => @address_hash_type,
"DecompilerVersion" => %{
type: "decompiler version",
definition: "When decompiled source code is present, the decompiler version with which it was generated.",
example: "decompiler.version"
},
"ABI" => %{ "ABI" => %{
type: "ABI", type: "ABI",
definition: "JSON string for the contract's Application Binary Interface (ABI)", definition: "JSON string for the contract's Application Binary Interface (ABI)",
@ -938,9 +933,16 @@ defmodule BlockScoutWeb.Etherscan do
""" """
} }
@contract_decompiler_version_type %{
type: "decompiler version",
definition: "When decompiled source code is present, the decompiler version with which it was generated.",
example: "decompiler.version"
}
@contract_with_sourcecode_model @contract_model @contract_with_sourcecode_model @contract_model
|> put_in([:fields, "SourceCode"], @contract_source_code_type) |> put_in([:fields, "SourceCode"], @contract_source_code_type)
|> put_in([:fields, "DecompiledSourceCode"], @contract_decompiled_source_code_type) |> put_in([:fields, "DecompiledSourceCode"], @contract_decompiled_source_code_type)
|> put_in([:fields, "DecompilerVersion"], @contract_decompiler_version_type)
@transaction_receipt_status_model %{ @transaction_receipt_status_model %{
name: "TransactionReceiptStatus", name: "TransactionReceiptStatus",
@ -1831,7 +1833,12 @@ defmodule BlockScoutWeb.Etherscan do
@contract_listcontracts_action %{ @contract_listcontracts_action %{
name: "listcontracts", name: "listcontracts",
description: "Get a list of contracts, sorted ascending by the time they were first seen by the explorer.", description: """
Get a list of contracts, sorted ascending by the time they were first seen by the explorer.
If you provide the filters `not_decompiled`(`4`) or `not_verified(4)` the results will not
be sorted for performance reasons.
""",
required_params: [], required_params: [],
optional_params: [ optional_params: [
%{ %{

@ -76,16 +76,12 @@ defmodule BlockScoutWeb.API.RPC.ContractView do
defp prepare_contract(%Address{ defp prepare_contract(%Address{
hash: hash, hash: hash,
smart_contract: nil, smart_contract: nil
decompiled_smart_contracts: decompiled_smart_contracts
}) do }) do
decompiled_smart_contract = latest_decompiled_smart_contract(decompiled_smart_contracts)
%{ %{
"Address" => to_string(hash), "Address" => to_string(hash),
"ABI" => "Contract source code not verified", "ABI" => "Contract source code not verified",
"ContractName" => "", "ContractName" => "",
"DecompilerVersion" => decompiler_version(decompiled_smart_contract),
"CompilerVersion" => "", "CompilerVersion" => "",
"OptimizationUsed" => "" "OptimizationUsed" => ""
} }
@ -93,16 +89,12 @@ defmodule BlockScoutWeb.API.RPC.ContractView do
defp prepare_contract(%Address{ defp prepare_contract(%Address{
hash: hash, hash: hash,
smart_contract: %SmartContract{} = contract, smart_contract: %SmartContract{} = contract
decompiled_smart_contracts: decompiled_smart_contracts
}) do }) do
decompiled_smart_contract = latest_decompiled_smart_contract(decompiled_smart_contracts)
%{ %{
"Address" => to_string(hash), "Address" => to_string(hash),
"ABI" => Jason.encode!(contract.abi), "ABI" => Jason.encode!(contract.abi),
"ContractName" => contract.name, "ContractName" => contract.name,
"DecompilerVersion" => decompiler_version(decompiled_smart_contract),
"CompilerVersion" => contract.compiler_version, "CompilerVersion" => contract.compiler_version,
"OptimizationUsed" => if(contract.optimization, do: "1", else: "0") "OptimizationUsed" => if(contract.optimization, do: "1", else: "0")
} }

@ -47,7 +47,6 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"Address" => to_string(contract.address_hash), "Address" => to_string(contract.address_hash),
"CompilerVersion" => contract.compiler_version, "CompilerVersion" => contract.compiler_version,
"ContractName" => contract.name, "ContractName" => contract.name,
"DecompilerVersion" => "",
"OptimizationUsed" => if(contract.optimization, do: "1", else: "0") "OptimizationUsed" => if(contract.optimization, do: "1", else: "0")
} }
] ]
@ -70,7 +69,6 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"Address" => to_string(address.hash), "Address" => to_string(address.hash),
"CompilerVersion" => "", "CompilerVersion" => "",
"ContractName" => "", "ContractName" => "",
"DecompilerVersion" => "",
"OptimizationUsed" => "" "OptimizationUsed" => ""
} }
] ]
@ -94,7 +92,6 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"Address" => to_string(address.hash), "Address" => to_string(address.hash),
"CompilerVersion" => "", "CompilerVersion" => "",
"ContractName" => "", "ContractName" => "",
"DecompilerVersion" => "",
"OptimizationUsed" => "" "OptimizationUsed" => ""
} }
] ]
@ -122,7 +119,6 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"Address" => to_string(address.hash), "Address" => to_string(address.hash),
"CompilerVersion" => "", "CompilerVersion" => "",
"ContractName" => "", "ContractName" => "",
"DecompilerVersion" => "",
"OptimizationUsed" => "" "OptimizationUsed" => ""
} }
] ]
@ -145,7 +141,6 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"ABI" => Jason.encode!(contract.abi), "ABI" => Jason.encode!(contract.abi),
"Address" => to_string(contract.address_hash), "Address" => to_string(contract.address_hash),
"CompilerVersion" => contract.compiler_version, "CompilerVersion" => contract.compiler_version,
"DecompilerVersion" => "",
"ContractName" => contract.name, "ContractName" => contract.name,
"OptimizationUsed" => if(contract.optimization, do: "1", else: "0") "OptimizationUsed" => if(contract.optimization, do: "1", else: "0")
} }
@ -170,7 +165,6 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"Address" => to_string(decompiled_smart_contract.address_hash), "Address" => to_string(decompiled_smart_contract.address_hash),
"CompilerVersion" => "", "CompilerVersion" => "",
"ContractName" => "", "ContractName" => "",
"DecompilerVersion" => "test_decompiler",
"OptimizationUsed" => "" "OptimizationUsed" => ""
} }
] ]
@ -194,7 +188,6 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"Address" => to_string(smart_contract.address_hash), "Address" => to_string(smart_contract.address_hash),
"CompilerVersion" => "", "CompilerVersion" => "",
"ContractName" => "", "ContractName" => "",
"DecompilerVersion" => "bizbuz",
"OptimizationUsed" => "" "OptimizationUsed" => ""
} }
] ]
@ -214,16 +207,15 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["message"] == "OK" assert response["message"] == "OK"
assert response["status"] == "1" assert response["status"] == "1"
assert response["result"] == [ assert %{
%{
"ABI" => "Contract source code not verified", "ABI" => "Contract source code not verified",
"Address" => to_string(smart_contract.address_hash), "Address" => to_string(smart_contract.address_hash),
"CompilerVersion" => "", "CompilerVersion" => "",
"ContractName" => "", "ContractName" => "",
"DecompilerVersion" => "bizbuz",
"OptimizationUsed" => "" "OptimizationUsed" => ""
} } in response["result"]
]
refute to_string(non_match.address_hash) in Enum.map(response["result"], &Map.get(&1, "Address"))
end end
test "filtering for only not_decompiled (and by extension not verified contracts)", %{params: params, conn: conn} do test "filtering for only not_decompiled (and by extension not verified contracts)", %{params: params, conn: conn} do
@ -245,7 +237,6 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"Address" => to_string(contract_address.hash), "Address" => to_string(contract_address.hash),
"CompilerVersion" => "", "CompilerVersion" => "",
"ContractName" => "", "ContractName" => "",
"DecompilerVersion" => "",
"OptimizationUsed" => "" "OptimizationUsed" => ""
} }
] ]
@ -274,7 +265,6 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"Address" => to_string(contract_address.hash), "Address" => to_string(contract_address.hash),
"CompilerVersion" => "", "CompilerVersion" => "",
"ContractName" => "", "ContractName" => "",
"DecompilerVersion" => "",
"OptimizationUsed" => "" "OptimizationUsed" => ""
} }
] ]

@ -2,7 +2,7 @@ defmodule BlockScoutWeb.API.V1.DecompiledControllerTest do
use BlockScoutWeb.ConnCase use BlockScoutWeb.ConnCase
alias Explorer.Repo alias Explorer.Repo
alias Explorer.Chain.DecompiledSmartContract alias Explorer.Chain.{Address, DecompiledSmartContract}
import Ecto.Query, import Ecto.Query,
only: [from: 2] only: [from: 2]
@ -87,6 +87,24 @@ defmodule BlockScoutWeb.API.V1.DecompiledControllerTest do
assert decompiled_smart_contract.decompiler_version == decompiler_version assert decompiled_smart_contract.decompiler_version == decompiler_version
assert decompiled_smart_contract.decompiled_source_code == decompiled_source_code assert decompiled_smart_contract.decompiled_source_code == decompiled_source_code
end end
test "updates the address to be decompiled", %{conn: conn} do
address_hash = to_string(insert(:address, hash: "0x0000000000000000000000000000000000000001").hash)
decompiler_version = "test_decompiler"
decompiled_source_code = "hello world"
params = %{
"address_hash" => address_hash,
"decompiler_version" => decompiler_version,
"decompiled_source_code" => decompiled_source_code
}
request = post(conn, api_v1_decompiled_smart_contract_path(conn, :create), params)
assert request.status == 201
assert Repo.get!(Address, address_hash).decompiled
end
end end
describe "when user is not authorized" do describe "when user is not authorized" do

@ -554,9 +554,19 @@ defmodule Explorer.Chain do
@spec create_decompiled_smart_contract(map()) :: {:ok, Address.t()} | {:error, Ecto.Changeset.t()} @spec create_decompiled_smart_contract(map()) :: {:ok, Address.t()} | {:error, Ecto.Changeset.t()}
def create_decompiled_smart_contract(attrs) do def create_decompiled_smart_contract(attrs) do
%DecompiledSmartContract{} changeset = DecompiledSmartContract.changeset(%DecompiledSmartContract{}, attrs)
|> DecompiledSmartContract.changeset(attrs)
|> Repo.insert(on_conflict: :replace_all, conflict_target: [:decompiler_version, :address_hash]) Multi.new()
|> Multi.insert(:decompiled_smart_contract, changeset,
on_conflict: :replace_all,
conflict_target: [:decompiler_version, :address_hash]
)
|> Multi.run(:set_address_decompiled, &set_address_decompiled/2)
|> Repo.transaction()
|> case do
{:ok, %{decompiled_smart_contract: decompiled_smart_contract}} -> {:ok, decompiled_smart_contract}
{:error, _, error_value, _} -> {:error, error_value}
end
end end
@doc """ @doc """
@ -2235,6 +2245,7 @@ defmodule Explorer.Chain do
|> Multi.insert(:smart_contract, smart_contract_changeset) |> Multi.insert(:smart_contract, smart_contract_changeset)
|> Multi.run(:clear_primary_address_names, &clear_primary_address_names/2) |> Multi.run(:clear_primary_address_names, &clear_primary_address_names/2)
|> Multi.run(:insert_address_name, &create_address_name/2) |> Multi.run(:insert_address_name, &create_address_name/2)
|> Multi.run(:set_address_verified, &set_address_verified/2)
|> Repo.transaction() |> Repo.transaction()
with {:ok, %{smart_contract: smart_contract}} <- insert_result do with {:ok, %{smart_contract: smart_contract}} <- insert_result do
@ -2242,6 +2253,35 @@ defmodule Explorer.Chain do
else else
{:error, :smart_contract, changeset, _} -> {:error, :smart_contract, changeset, _} ->
{:error, changeset} {:error, changeset}
{:error, :set_address_verified, message, _} ->
{:error, message}
end
end
defp set_address_verified(repo, %{smart_contract: %SmartContract{address_hash: address_hash}}) do
query =
from(
address in Address,
where: address.hash == ^address_hash
)
case repo.update_all(query, set: [verified: true]) do
{1, _} -> {:ok, []}
_ -> {:error, "There was an error annotating that the address has been verified."}
end
end
defp set_address_decompiled(repo, %{decompiled_smart_contract: %DecompiledSmartContract{address_hash: address_hash}}) do
query =
from(
address in Address,
where: address.hash == ^address_hash
)
case repo.update_all(query, set: [decompiled: true]) do
{1, _} -> {:ok, []}
_ -> {:error, "There was an error annotating that the address has been verified."}
end end
end end
@ -2754,50 +2794,46 @@ defmodule Explorer.Chain do
query = query =
from( from(
address in Address, address in Address,
where: where: address.contract_code != <<>>,
fragment( where: not is_nil(address.contract_code),
"EXISTS (SELECT 1 FROM decompiled_smart_contracts WHERE decompiled_smart_contracts.address_hash = ?)", where: address.decompiled == true,
address.hash
),
preload: [:decompiled_smart_contracts, :smart_contract],
order_by: [asc: address.inserted_at],
limit: ^limit, limit: ^limit,
offset: ^offset offset: ^offset,
order_by: [asc: address.inserted_at],
preload: [:smart_contract]
) )
query query
|> filter_decompiled_with_version(not_decompiled_with_version) |> reject_decompiled_with_version(not_decompiled_with_version)
|> Repo.all() |> Repo.all()
end end
defp filter_decompiled_with_version(query, nil) do defp reject_decompiled_with_version(query, nil), do: query
query
end
defp filter_decompiled_with_version(query, not_decompiled_with_version) do defp reject_decompiled_with_version(query, reject_version) do
from(address in query, from(
left_join: decompiled_smart_contract in DecompiledSmartContract, address in query,
on: decompiled_smart_contract.decompiler_version == ^not_decompiled_with_version, left_join: decompiled_smart_contract in assoc(address, :decompiled_smart_contracts),
on: decompiled_smart_contract.address_hash == address.hash, on: decompiled_smart_contract.decompiler_version == ^reject_version,
where: is_nil(decompiled_smart_contract.id), where: is_nil(decompiled_smart_contract.address_hash)
distinct: [address.hash]
) )
end end
def list_verified_contracts(limit, offset) do def list_verified_contracts(limit, offset) do
query = query =
from( from(
address in Address, smart_contract in SmartContract,
where: not is_nil(address.contract_code), order_by: [asc: smart_contract.inserted_at],
join: smart_contract in SmartContract,
on: smart_contract.address_hash == address.hash,
preload: [{:smart_contract, smart_contract}, :decompiled_smart_contracts],
order_by: [asc: address.inserted_at],
limit: ^limit, limit: ^limit,
offset: ^offset offset: ^offset,
preload: [:address]
) )
Repo.all(query) query
|> Repo.all()
|> Enum.map(fn smart_contract ->
Map.put(smart_contract.address, :smart_contract, smart_contract)
end)
end end
def list_contracts(limit, offset) do def list_contracts(limit, offset) do
@ -2805,7 +2841,7 @@ defmodule Explorer.Chain do
from( from(
address in Address, address in Address,
where: not is_nil(address.contract_code), where: not is_nil(address.contract_code),
preload: [:smart_contract, :decompiled_smart_contracts], preload: [:smart_contract],
order_by: [asc: address.inserted_at], order_by: [asc: address.inserted_at],
limit: ^limit, limit: ^limit,
offset: ^offset offset: ^offset
@ -2814,22 +2850,22 @@ defmodule Explorer.Chain do
Repo.all(query) Repo.all(query)
end end
def list_unverified_contracts(limit, offset) do def list_unordered_unverified_contracts(limit, offset) do
query = query =
from( from(
address in Address, address in Address,
left_join: smart_contract in SmartContract,
on: smart_contract.address_hash == address.hash,
where: not is_nil(address.contract_code),
where: is_nil(smart_contract.address_hash),
where: address.contract_code != <<>>, where: address.contract_code != <<>>,
preload: [{:smart_contract, smart_contract}, :decompiled_smart_contracts], where: not is_nil(address.contract_code),
order_by: [asc: address.inserted_at], where: fragment("? IS NOT TRUE", address.verified),
limit: ^limit, limit: ^limit,
offset: ^offset offset: ^offset
) )
Repo.all(query) query
|> Repo.all()
|> Enum.map(fn address ->
%{address | smart_contract: nil}
end)
end end
def list_empty_contracts(limit, offset) do def list_empty_contracts(limit, offset) do
@ -2845,30 +2881,23 @@ defmodule Explorer.Chain do
Repo.all(query) Repo.all(query)
end end
def list_not_decompiled_contracts(limit, offset) do def list_unordered_not_decompiled_contracts(limit, offset) do
query = query =
from( from(
address in Address, address in Address,
where: where: fragment("? IS NOT TRUE", address.verified),
fragment( where: fragment("? IS NOT TRUE", address.decompiled),
"NOT EXISTS (SELECT 1 FROM decompiled_smart_contracts WHERE decompiled_smart_contracts.address_hash = ?)",
address.hash
),
where: address.contract_code != <<>>, where: address.contract_code != <<>>,
left_join: smart_contract in SmartContract,
on: smart_contract.address_hash == address.hash,
left_join: decompiled_smart_contract in DecompiledSmartContract,
on: decompiled_smart_contract.address_hash == address.hash,
preload: [:smart_contract, :decompiled_smart_contracts],
where: not is_nil(address.contract_code), where: not is_nil(address.contract_code),
where: is_nil(smart_contract.address_hash),
where: is_nil(decompiled_smart_contract.address_hash),
order_by: [asc: address.inserted_at],
limit: ^limit, limit: ^limit,
offset: ^offset offset: ^offset
) )
Repo.all(query) query
|> Repo.all()
|> Enum.map(fn address ->
%{address | smart_contract: nil}
end)
end end
@doc """ @doc """

@ -22,7 +22,7 @@ defmodule Explorer.Chain.Address do
Wei Wei
} }
@optional_attrs ~w(contract_code fetched_coin_balance fetched_coin_balance_block_number nonce)a @optional_attrs ~w(contract_code fetched_coin_balance fetched_coin_balance_block_number nonce decompiled verified)a
@required_attrs ~w(hash)a @required_attrs ~w(hash)a
@allowed_attrs @optional_attrs ++ @required_attrs @allowed_attrs @optional_attrs ++ @required_attrs
@ -75,6 +75,8 @@ defmodule Explorer.Chain.Address do
field(:fetched_coin_balance_block_number, :integer) field(:fetched_coin_balance_block_number, :integer)
field(:contract_code, Data) field(:contract_code, Data)
field(:nonce, :integer) field(:nonce, :integer)
field(:decompiled, :boolean, default: false)
field(:verified, :boolean, default: false)
field(:has_decompiled_code?, :boolean, virtual: true) field(:has_decompiled_code?, :boolean, virtual: true)
field(:stale?, :boolean, virtual: true) field(:stale?, :boolean, virtual: true)

@ -13,6 +13,11 @@ defmodule Explorer.Chain.Import.Runner.Addresses do
@behaviour Import.Runner @behaviour Import.Runner
@row_defaults %{
decompiled: false,
verified: false
}
# milliseconds # milliseconds
@timeout 60_000 @timeout 60_000
@ -45,9 +50,16 @@ defmodule Explorer.Chain.Import.Runner.Addresses do
update_transactions_options = %{timeout: transactions_timeout, timestamps: timestamps} update_transactions_options = %{timeout: transactions_timeout, timestamps: timestamps}
changes_list_with_defaults =
Enum.map(changes_list, fn change ->
Enum.reduce(@row_defaults, change, fn {default_key, default_value}, acc ->
Map.put_new(acc, default_key, default_value)
end)
end)
multi multi
|> Multi.run(:addresses, fn repo, _ -> |> Multi.run(:addresses, fn repo, _ ->
insert(repo, changes_list, insert_options) insert(repo, changes_list_with_defaults, insert_options)
end) end)
|> Multi.run(:created_address_code_indexed_at_transactions, fn repo, %{addresses: addresses} |> Multi.run(:created_address_code_indexed_at_transactions, fn repo, %{addresses: addresses}
when is_list(addresses) -> when is_list(addresses) ->

@ -86,7 +86,7 @@ defmodule Explorer.SmartContract.SolcDownloader do
download_path = "https://ethereum.github.io/solc-bin/bin/soljson-#{version}.js" download_path = "https://ethereum.github.io/solc-bin/bin/soljson-#{version}.js"
download_path download_path
|> HTTPoison.get!([], timeout: 60_000) |> HTTPoison.get!([], timeout: 60_000, recv_timeout: 60_000)
|> Map.get(:body) |> Map.get(:body)
end end
end end

@ -0,0 +1,14 @@
defmodule Explorer.Repo.Migrations.AddAddressHashIndexToDecompiledSmartContracts do
use Ecto.Migration
def change do
execute(
"""
CREATE INDEX IF NOT EXISTS decompiled_smart_contracts_address_hash_index ON decompiled_smart_contracts(address_hash);
""",
"""
DROP INDEX IF EXISTS decompiled_smart_contracts_address_hash_index
"""
)
end
end

@ -0,0 +1,18 @@
defmodule Explorer.Repo.Migrations.AddDecompiledAndVerifiedFlagToAddresses do
use Ecto.Migration
def change do
execute(
"""
ALTER TABLE addresses
ADD COLUMN IF NOT EXISTS decompiled BOOLEAN,
ADD COLUMN IF NOT EXISTS verified BOOLEAN;
""",
"""
ALTER TABLE addresses
DROP COLUMN IF EXISTS decompiled,
DROP COLUMN IF EXISTS verified;
"""
)
end
end

@ -2859,6 +2859,12 @@ defmodule Explorer.ChainTest do
assert {:ok, _} = Chain.create_smart_contract(attrs) assert {:ok, _} = Chain.create_smart_contract(attrs)
assert Repo.get_by(Address.Name, name: "SimpleStorage") assert Repo.get_by(Address.Name, name: "SimpleStorage")
end end
test "sets the address verified field to true", %{valid_attrs: valid_attrs} do
assert {:ok, %SmartContract{} = smart_contract} = Chain.create_smart_contract(valid_attrs)
assert Repo.get_by(Address, hash: smart_contract.address_hash).verified == true
end
end end
describe "stream_unfetched_balances/2" do describe "stream_unfetched_balances/2" do

@ -482,6 +482,7 @@ defmodule Explorer.Factory do
address = %Address{ address = %Address{
hash: address_hash(), hash: address_hash(),
verified: true,
contract_code: contract_code_info().bytecode, contract_code: contract_code_info().bytecode,
smart_contract: smart_contract smart_contract: smart_contract
} }
@ -519,7 +520,7 @@ defmodule Explorer.Factory do
contract_code_info = contract_code_info() contract_code_info = contract_code_info()
%SmartContract{ %SmartContract{
address_hash: insert(:address, contract_code: contract_code_info.bytecode).hash, address_hash: insert(:address, contract_code: contract_code_info.bytecode, verified: true).hash,
compiler_version: contract_code_info.version, compiler_version: contract_code_info.version,
name: contract_code_info.name, name: contract_code_info.name,
contract_source_code: contract_code_info.source_code, contract_source_code: contract_code_info.source_code,
@ -532,7 +533,7 @@ defmodule Explorer.Factory do
contract_code_info = contract_code_info() contract_code_info = contract_code_info()
%DecompiledSmartContract{ %DecompiledSmartContract{
address_hash: insert(:address, contract_code: contract_code_info.bytecode).hash, address_hash: insert(:address, contract_code: contract_code_info.bytecode, decompiled: true).hash,
decompiler_version: "test_decompiler", decompiler_version: "test_decompiler",
decompiled_source_code: contract_code_info.source_code decompiled_source_code: contract_code_info.source_code
} }

Loading…
Cancel
Save