Merge branch 'master' into vb-force-show-not-found-address

pull/2425/head
Victor Baranov 5 years ago committed by GitHub
commit 671cba495a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 17
      CHANGELOG.md
  2. 3
      apps/block_scout_web/assets/css/components/_tile.scss
  3. 2
      apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex
  4. 11
      apps/block_scout_web/lib/block_scout_web/controllers/api/v1/health_controller.ex
  5. 167
      apps/block_scout_web/lib/block_scout_web/templates/chain/_block.html.eex
  6. 2
      apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex
  7. 10
      apps/block_scout_web/lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex
  8. 4
      apps/block_scout_web/lib/block_scout_web/templates/transaction_log/_logs.html.eex
  9. 1
      apps/block_scout_web/lib/block_scout_web/views/internal_transaction_view.ex
  10. 133
      apps/block_scout_web/priv/gettext/default.pot
  11. 134
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  12. 46
      apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs
  13. 12
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/call.ex
  14. 6
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/geth/tracer.ex
  15. 40
      apps/ethereum_jsonrpc/priv/js/ethereum_jsonrpc/geth/debug_traceTransaction/tracer.js
  16. 29
      apps/explorer/lib/explorer/chain.ex
  17. 6
      apps/explorer/lib/explorer/chain/internal_transaction.ex
  18. 15
      apps/explorer/lib/explorer/chain/internal_transaction/type.ex
  19. 22
      apps/explorer/test/explorer/chain_test.exs

@ -1,5 +1,15 @@
## Current ## Current
### Features
### Fixes
- [#2425](https://github.com/poanetwork/blockscout/pull/2425) - Force to show address view for checksummed address even if it is not in DB
### Chore
## 2.0.2-beta
### Features ### Features
- [#2412](https://github.com/poanetwork/blockscout/pull/2412) - dark theme - [#2412](https://github.com/poanetwork/blockscout/pull/2412) - dark theme
- [#2399](https://github.com/poanetwork/blockscout/pull/2399) - decode verified smart contract's logs - [#2399](https://github.com/poanetwork/blockscout/pull/2399) - decode verified smart contract's logs
@ -13,13 +23,15 @@
- [#2324](https://github.com/poanetwork/blockscout/pull/2324) - set timeout for loading message on the main page - [#2324](https://github.com/poanetwork/blockscout/pull/2324) - set timeout for loading message on the main page
### Fixes ### Fixes
- [#2425](https://github.com/poanetwork/blockscout/pull/2425) - Force to show address view for checksummed address even if it is not in DB - [#2421](https://github.com/poanetwork/blockscout/pull/2421) - Fix hiding of loader for txs on the main page
- [#2420](https://github.com/poanetwork/blockscout/pull/2420) - fetch data from cache in healthy endpoint
- [#2416](https://github.com/poanetwork/blockscout/pull/2416) - Fix "page not found" handling in the router - [#2416](https://github.com/poanetwork/blockscout/pull/2416) - Fix "page not found" handling in the router
- [#2413](https://github.com/poanetwork/blockscout/pull/2413) - remove outer tables for decoded data
- [#2410](https://github.com/poanetwork/blockscout/pull/2410) - preload smart contract for logs decoding - [#2410](https://github.com/poanetwork/blockscout/pull/2410) - preload smart contract for logs decoding
- [#2405](https://github.com/poanetwork/blockscout/pull/2405) - added templates for table loader and tile loader - [#2405](https://github.com/poanetwork/blockscout/pull/2405) - added templates for table loader and tile loader
- [#2398](https://github.com/poanetwork/blockscout/pull/2398) - show only one decoded candidate - [#2398](https://github.com/poanetwork/blockscout/pull/2398) - show only one decoded candidate
- [#2395](https://github.com/poanetwork/blockscout/pull/2395) - new block loading animation
- [#2389](https://github.com/poanetwork/blockscout/pull/2389) - Reduce Lodash lib size (86% of lib methods are not used) - [#2389](https://github.com/poanetwork/blockscout/pull/2389) - Reduce Lodash lib size (86% of lib methods are not used)
- [#2388](https://github.com/poanetwork/blockscout/pull/2388) - add create2 support to geth's js tracer
- [#2387](https://github.com/poanetwork/blockscout/pull/2387) - fix not existing keys in transaction json rpc - [#2387](https://github.com/poanetwork/blockscout/pull/2387) - fix not existing keys in transaction json rpc
- [#2378](https://github.com/poanetwork/blockscout/pull/2378) - Page performance: exclude moment.js localization files except EN, remove unused css - [#2378](https://github.com/poanetwork/blockscout/pull/2378) - Page performance: exclude moment.js localization files except EN, remove unused css
- [#2368](https://github.com/poanetwork/blockscout/pull/2368) - add two columns of smart contract info - [#2368](https://github.com/poanetwork/blockscout/pull/2368) - add two columns of smart contract info
@ -38,6 +50,7 @@
- [#2326](https://github.com/poanetwork/blockscout/pull/2326) - fix nested constructor arguments - [#2326](https://github.com/poanetwork/blockscout/pull/2326) - fix nested constructor arguments
### Chore ### Chore
- [#2422](https://github.com/poanetwork/blockscout/pull/2422) - check if address_id is binary in token_transfers_csv endpoint
- [#2418](https://github.com/poanetwork/blockscout/pull/2418) - Remove parentheses in market cap percentage - [#2418](https://github.com/poanetwork/blockscout/pull/2418) - Remove parentheses in market cap percentage
- [#2401](https://github.com/poanetwork/blockscout/pull/2401) - add ENV vars to manage updating period of average block time and market history cache - [#2401](https://github.com/poanetwork/blockscout/pull/2401) - add ENV vars to manage updating period of average block time and market history cache
- [#2363](https://github.com/poanetwork/blockscout/pull/2363) - add parameters example for eth rpc - [#2363](https://github.com/poanetwork/blockscout/pull/2363) - add parameters example for eth rpc

@ -340,6 +340,9 @@ $tile-body-a-color: #5959d8 !default;
padding-right: 6px; padding-right: 6px;
} }
} }
.tile-type-block {
overflow: hidden;
}
.row { .row {
@include media-breakpoint-down(lg) { @include media-breakpoint-down(lg) {
margin-left: -6px; margin-left: -6px;

@ -131,7 +131,7 @@ defmodule BlockScoutWeb.AddressTransactionController do
end end
end end
def token_transfers_csv(conn, %{"address_id" => address_hash_string}) do def token_transfers_csv(conn, %{"address_id" => address_hash_string}) when is_binary(address_hash_string) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.hash_to_address(address_hash) do {:ok, address} <- Chain.hash_to_address(address_hash) do
address address

@ -4,19 +4,22 @@ defmodule BlockScoutWeb.API.V1.HealthController do
alias Explorer.Chain alias Explorer.Chain
def health(conn, _) do def health(conn, _) do
with {:ok, number, timestamp} <- Chain.last_block_status() do with {:ok, number, timestamp} <- Chain.last_db_block_status(),
send_resp(conn, :ok, result(number, timestamp)) {:ok, cache_number, cache_timestamp} <- Chain.last_cache_block_status() do
send_resp(conn, :ok, result(number, timestamp, cache_number, cache_timestamp))
else else
status -> send_resp(conn, :internal_server_error, error(status)) status -> send_resp(conn, :internal_server_error, error(status))
end end
end end
def result(number, timestamp) do def result(number, timestamp, cache_number, cache_timestamp) do
%{ %{
"healthy" => true, "healthy" => true,
"data" => %{ "data" => %{
"latest_block_number" => to_string(number), "latest_block_number" => to_string(number),
"latest_block_inserted_at" => to_string(timestamp) "latest_block_inserted_at" => to_string(timestamp),
"cache_latest_block_number" => to_string(cache_number),
"cache_latest_block_inserted_at" => to_string(cache_timestamp)
} }
} }
|> Jason.encode!() |> Jason.encode!()

@ -1,172 +1,5 @@
<div class="col-lg-3 fade-up-blocks-chain" data-selector="chain-block" data-block-number="<%= @block.number %>"> <div class="col-lg-3 fade-up-blocks-chain" data-selector="chain-block" data-block-number="<%= @block.number %>">
<div class="tile tile-type-block n-p d-flex flex-column"> <div class="tile tile-type-block n-p d-flex flex-column">
<div class="tile-type-block-animation">
<div class="tile-type-line-up"></div>
<span class="cube-animation-title">Block Validated, processing...</span>
<div class="cube-animation-wrapper">
<div class="cube-animation-center">
<div class="cube-animation-row">
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
</div>
<div class="cube-animation-row">
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
</div>
<div class="cube-animation-row">
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
<div class="cube-animation-column">
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
<svg class="cube" viewBox="0 0 86.6 100" x="0px" y="0px">
<polygon class="side" points="43.3,0 0,25 0,75 43.3,100 86.6,75 86.6,25 "></polygon>
<polygon class="side" points="86.6,25 43.3,50 43.3,100 86.6,75 "></polygon>
<polygon class="side" points="0,25 43.3,0 86.6,25 43.3,50 "></polygon>
</svg>
</div>
</div>
</div>
</div>
</div>
<%= link( <%= link(
@block, @block,
class: "tile-title", class: "tile-title",

@ -117,7 +117,9 @@
<%= gettext "Something went wrong, click to retry." %> <%= gettext "Something went wrong, click to retry." %>
</span> </span>
</button> </button>
<div hidden data-selector="loading-message">
<%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %> <%= render BlockScoutWeb.CommonComponentsView, "_tile-loader.html" %>
</div>
</span> </span>
</div> </div>
</div> </div>

@ -1,4 +1,5 @@
<table summary="<%= gettext "Transaction Info" %>" class="table thead-light table-bordered table-responsive transaction-info-table"> <div class="table-responsive text-center">
<table style="color: black;" summary="<%= gettext "Transaction Inputs" %>" class="table thead-light table-bordered">
<tr> <tr>
<td><%= gettext "Method Id" %></td> <td><%= gettext "Method Id" %></td>
<td colspan="3"><code>0x<%= @method_id %></code></td> <td colspan="3"><code>0x<%= @method_id %></code></td>
@ -7,10 +8,12 @@
<td>Call</td> <td>Call</td>
<td colspan="3"><code><%= @text %></code></td> <td colspan="3"><code><%= @text %></code></td>
</tr> </tr>
</table> </table>
</div>
<%= unless Enum.empty?(@mapping) do %> <%= unless Enum.empty?(@mapping) do %>
<table summary="<%= gettext "Transaction Inputs" %>" class="table thead-light table-bordered table-responsive"> <div class="table-responsive text-center">
<table style="color: black;" summary="<%= gettext "Transaction Inputs" %>" class="table thead-light table-bordered">
<tr> <tr>
<th scope="col"></th> <th scope="col"></th>
<th scope="col"><%= gettext "Name" %></th> <th scope="col"><%= gettext "Name" %></th>
@ -52,4 +55,5 @@
</tr> </tr>
<% end %> <% end %>
</table> </table>
</div>
<% end %> <% end %>

@ -39,7 +39,8 @@
<td colspan="3"><code><%= text %></code></td> <td colspan="3"><code><%= text %></code></td>
</tr> </tr>
</table> </table>
<table style="color: black;" summary="<%= gettext "Log Data" %>" class="table thead-light table-bordered table-responsive"> <div class="table-responsive text-center">
<table style="color: black;" summary="<%= gettext "Log Data" %>" class="table thead-light table-bordered">
<tr> <tr>
<th scope="col"></th> <th scope="col"></th>
<th scope="col"><%= gettext "Name" %></th> <th scope="col"><%= gettext "Name" %></th>
@ -76,6 +77,7 @@
</tr> </tr>
<% end %> <% end %>
</table> </table>
</div>
<% _ -> %> <% _ -> %>
<%= nil %> <%= nil %>
<% end %> <% end %>

@ -23,6 +23,7 @@ defmodule BlockScoutWeb.InternalTransactionView do
def type(%InternalTransaction{type: :call, call_type: :delegatecall}), do: gettext("Delegate Call") def type(%InternalTransaction{type: :call, call_type: :delegatecall}), do: gettext("Delegate Call")
def type(%InternalTransaction{type: :call, call_type: :staticcall}), do: gettext("Static Call") def type(%InternalTransaction{type: :call, call_type: :staticcall}), do: gettext("Static Call")
def type(%InternalTransaction{type: :create}), do: gettext("Create") def type(%InternalTransaction{type: :create}), do: gettext("Create")
def type(%InternalTransaction{type: :create2}), do: gettext("Create2")
def type(%InternalTransaction{type: :selfdestruct}), do: gettext("Self-Destruct") def type(%InternalTransaction{type: :selfdestruct}), do: gettext("Self-Destruct")
def type(%InternalTransaction{type: :reward}), do: gettext("Reward") def type(%InternalTransaction{type: :reward}), do: gettext("Reward")
end end

@ -34,7 +34,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:21 #: lib/block_scout_web/templates/block/overview.html.eex:21
#: lib/block_scout_web/templates/chain/_block.html.eex:178 #: lib/block_scout_web/templates/chain/_block.html.eex:11
msgid "%{count} Transactions" msgid "%{count} Transactions"
msgstr "" msgstr ""
@ -328,15 +328,6 @@ msgstr ""
msgid "Curl" msgid "Curl"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:49
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:114
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:18
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:113
msgid "Data"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:53 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:53
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:188 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:188
@ -523,7 +514,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:38 #: lib/block_scout_web/templates/block/_tile.html.eex:38
#: lib/block_scout_web/templates/block/overview.html.eex:121 #: lib/block_scout_web/templates/block/overview.html.eex:121
#: lib/block_scout_web/templates/chain/_block.html.eex:182 #: lib/block_scout_web/templates/chain/_block.html.eex:15
msgid "Miner" msgid "Miner"
msgstr "" msgstr ""
@ -558,8 +549,8 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:46 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:46
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:19
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:45 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
msgid "Name" msgid "Name"
msgstr "" msgstr ""
@ -827,12 +818,6 @@ msgstr ""
msgid "Top Accounts - %{subnetwork} Explorer" msgid "Top Accounts - %{subnetwork} Explorer"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:84
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:83
msgid "Topics"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:67 #: lib/block_scout_web/templates/block/overview.html.eex:67
msgid "Total Difficulty" msgid "Total Difficulty"
@ -1041,14 +1026,7 @@ msgid "Delegate Call"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:47
#: lib/block_scout_web/templates/chain/_block.html.eex:190
#: lib/block_scout_web/views/internal_transaction_view.ex:27 #: lib/block_scout_web/views/internal_transaction_view.ex:27
msgid "Reward"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:26
msgid "Self-Destruct" msgid "Self-Destruct"
msgstr "" msgstr ""
@ -1136,20 +1114,7 @@ msgid "Decoded"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:48 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:4
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47
msgid "Indexed?"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:47
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:17
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
msgid "Type"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:3
msgid "Method Id" msgid "Method Id"
msgstr "" msgstr ""
@ -1160,12 +1125,8 @@ msgid "To see decoded input data, the contract must be verified."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:1 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:2
msgid "Transaction Info" #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:13
msgid "Transaction Inputs" msgid "Transaction Inputs"
msgstr "" msgstr ""
@ -1189,29 +1150,10 @@ msgid "Failed to decode input data."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:46 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:49
msgid "Error rendering value" msgid "Error rendering value"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:59
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:28
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:58
msgid "Copy Value"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:29
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29
msgid "Failed to decode log data."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:43
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:42
msgid "Log Data"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34 #: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:61 #: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:61
@ -1809,3 +1751,62 @@ msgstr ""
#: lib/block_scout_web/templates/address_contract/index.html.eex:53 #: lib/block_scout_web/templates/address_contract/index.html.eex:53
msgid "Constructor Arguments" msgid "Constructor Arguments"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:59
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:31
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:59
msgid "Copy Value"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:26
msgid "Create2"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:49
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:114
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:21
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:49
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:115
msgid "Data"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:29
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29
msgid "Failed to decode log data."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:48
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
msgid "Indexed?"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:43
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:43
msgid "Log Data"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:47
#: lib/block_scout_web/templates/chain/_block.html.eex:23
#: lib/block_scout_web/views/internal_transaction_view.ex:28
msgid "Reward"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:84
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:85
msgid "Topics"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:47
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:20
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47
msgid "Type"
msgstr ""

@ -34,7 +34,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:21 #: lib/block_scout_web/templates/block/overview.html.eex:21
#: lib/block_scout_web/templates/chain/_block.html.eex:178 #: lib/block_scout_web/templates/chain/_block.html.eex:11
msgid "%{count} Transactions" msgid "%{count} Transactions"
msgstr "" msgstr ""
@ -328,15 +328,6 @@ msgstr ""
msgid "Curl" msgid "Curl"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:49
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:114
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:18
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:113
msgid "Data"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:53 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:53
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:188 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:188
@ -523,7 +514,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:38 #: lib/block_scout_web/templates/block/_tile.html.eex:38
#: lib/block_scout_web/templates/block/overview.html.eex:121 #: lib/block_scout_web/templates/block/overview.html.eex:121
#: lib/block_scout_web/templates/chain/_block.html.eex:182 #: lib/block_scout_web/templates/chain/_block.html.eex:15
msgid "Miner" msgid "Miner"
msgstr "" msgstr ""
@ -558,8 +549,8 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:46 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:46
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:19
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:45 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
msgid "Name" msgid "Name"
msgstr "" msgstr ""
@ -827,12 +818,6 @@ msgstr ""
msgid "Top Accounts - %{subnetwork} Explorer" msgid "Top Accounts - %{subnetwork} Explorer"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:84
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:83
msgid "Topics"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:67 #: lib/block_scout_web/templates/block/overview.html.eex:67
msgid "Total Difficulty" msgid "Total Difficulty"
@ -1041,14 +1026,7 @@ msgid "Delegate Call"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:47
#: lib/block_scout_web/templates/chain/_block.html.eex:190
#: lib/block_scout_web/views/internal_transaction_view.ex:27 #: lib/block_scout_web/views/internal_transaction_view.ex:27
msgid "Reward"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:26
msgid "Self-Destruct" msgid "Self-Destruct"
msgstr "" msgstr ""
@ -1136,20 +1114,7 @@ msgid "Decoded"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:48 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:4
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47
msgid "Indexed?"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:47
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:17
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
msgid "Type"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:3
msgid "Method Id" msgid "Method Id"
msgstr "" msgstr ""
@ -1160,12 +1125,8 @@ msgid "To see decoded input data, the contract must be verified."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:1 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:2
msgid "Transaction Info" #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:13
msgid "Transaction Inputs" msgid "Transaction Inputs"
msgstr "" msgstr ""
@ -1189,28 +1150,10 @@ msgid "Failed to decode input data."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:46 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:49
msgid "Error rendering value" msgid "Error rendering value"
msgstr "" msgstr ""
""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:59
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:28
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:58
msgid "Copy Value"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:29
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29
msgid "Failed to decode log data."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:43
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:42
msgid "Log Data"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34 #: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34
@ -1809,3 +1752,62 @@ msgstr ""
#: lib/block_scout_web/templates/address_contract/index.html.eex:53 #: lib/block_scout_web/templates/address_contract/index.html.eex:53
msgid "Constructor Arguments" msgid "Constructor Arguments"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:59
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:31
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:59
msgid "Copy Value"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/internal_transaction_view.ex:26
msgid "Create2"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:49
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:114
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:21
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:49
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:115
msgid "Data"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:29
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29
msgid "Failed to decode log data."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:48
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
msgid "Indexed?"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:43
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:43
msgid "Log Data"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:47
#: lib/block_scout_web/templates/chain/_block.html.eex:23
#: lib/block_scout_web/views/internal_transaction_view.ex:28
msgid "Reward"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:84
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:85
msgid "Topics"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:47
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:20
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47
msgid "Type"
msgstr ""

@ -1,6 +1,15 @@
defmodule BlockScoutWeb.API.V1.HealthControllerTest do defmodule BlockScoutWeb.API.V1.HealthControllerTest do
use BlockScoutWeb.ConnCase use BlockScoutWeb.ConnCase
alias Explorer.{Chain, PagingOptions}
setup do
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()})
:ok
end
describe "GET last_block_status/0" do describe "GET last_block_status/0" do
test "returns error when there are no blocks in db", %{conn: conn} do test "returns error when there are no blocks in db", %{conn: conn} do
request = get(conn, api_v1_health_path(conn, :health)) request = get(conn, api_v1_health_path(conn, :health))
@ -32,19 +41,50 @@ defmodule BlockScoutWeb.API.V1.HealthControllerTest do
end end
test "returns ok when last block is not stale", %{conn: conn} do test "returns ok when last block is not stale", %{conn: conn} do
insert(:block, consensus: true, timestamp: DateTime.utc_now()) block1 = insert(:block, consensus: true, timestamp: DateTime.utc_now(), number: 2)
insert(:block, consensus: true, timestamp: DateTime.utc_now(), number: 1)
request = get(conn, api_v1_health_path(conn, :health)) request = get(conn, api_v1_health_path(conn, :health))
assert request.status == 200 assert request.status == 200
result = Poison.decode!(request.resp_body)
assert result["healthy"] == true
assert %{
"latest_block_number" => to_string(block1.number),
"latest_block_inserted_at" => to_string(block1.timestamp),
"cache_latest_block_number" => to_string(block1.number),
"cache_latest_block_inserted_at" => to_string(block1.timestamp)
} == result["data"]
end
end
test "return error when cache is stale", %{conn: conn} do
stale_block = insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50), number: 3)
state_block_hash = stale_block.hash
assert [%{hash: ^state_block_hash}] = Chain.list_blocks(paging_options: %PagingOptions{page_size: 1})
insert(:block, consensus: true, timestamp: DateTime.utc_now(), number: 1)
assert [%{hash: ^state_block_hash}] = Chain.list_blocks(paging_options: %PagingOptions{page_size: 1})
request = get(conn, api_v1_health_path(conn, :health))
assert request.status == 500
assert %{ assert %{
"healthy" => true, "healthy" => false,
"error_code" => 5001,
"error_title" => "blocks fetching is stuck",
"error_description" =>
"There are no new blocks in the DB for the last 5 mins. Check the healthiness of Ethereum archive node or the Blockscout DB instance",
"data" => %{ "data" => %{
"latest_block_number" => _, "latest_block_number" => _,
"latest_block_inserted_at" => _ "latest_block_inserted_at" => _
} }
} = Poison.decode!(request.resp_body) } = Poison.decode!(request.resp_body)
end end
end
end end

@ -426,13 +426,14 @@ defmodule EthereumJSONRPC.Geth.Call do
"transactionHash" => transaction_hash, "transactionHash" => transaction_hash,
"index" => index, "index" => index,
"traceAddress" => trace_address, "traceAddress" => trace_address,
"type" => "create" = type, "type" => type,
"from" => from_address_hash, "from" => from_address_hash,
"error" => error, "error" => error,
"gas" => gas, "gas" => gas,
"init" => init, "init" => init,
"value" => value "value" => value
}) do })
when type in ~w(create create2) do
%{ %{
block_number: block_number, block_number: block_number,
transaction_index: transaction_index, transaction_index: transaction_index,
@ -454,7 +455,7 @@ defmodule EthereumJSONRPC.Geth.Call do
"transactionHash" => transaction_hash, "transactionHash" => transaction_hash,
"index" => index, "index" => index,
"traceAddress" => trace_address, "traceAddress" => trace_address,
"type" => "create", "type" => type,
"from" => from_address_hash, "from" => from_address_hash,
"createdContractAddressHash" => created_contract_address_hash, "createdContractAddressHash" => created_contract_address_hash,
"gas" => gas, "gas" => gas,
@ -462,14 +463,15 @@ defmodule EthereumJSONRPC.Geth.Call do
"init" => init, "init" => init,
"createdContractCode" => created_contract_code, "createdContractCode" => created_contract_code,
"value" => value "value" => value
}) do })
when type in ~w(create create2) do
%{ %{
block_number: block_number, block_number: block_number,
transaction_index: transaction_index, transaction_index: transaction_index,
transaction_hash: transaction_hash, transaction_hash: transaction_hash,
index: index, index: index,
trace_address: trace_address, trace_address: trace_address,
type: "create", type: type,
from_address_hash: from_address_hash, from_address_hash: from_address_hash,
gas: gas, gas: gas,
gas_used: gas_used, gas_used: gas_used,

@ -113,6 +113,7 @@ defmodule EthereumJSONRPC.Geth.Tracer do
end end
defp op(%{"op" => "CREATE"} = log, ctx), do: create_op(log, ctx) defp op(%{"op" => "CREATE"} = log, ctx), do: create_op(log, ctx)
defp op(%{"op" => "CREATE2"} = log, ctx), do: create_op(log, ctx, "create2")
defp op(%{"op" => "SELFDESTRUCT"} = log, ctx), do: self_destruct_op(log, ctx) defp op(%{"op" => "SELFDESTRUCT"} = log, ctx), do: self_destruct_op(log, ctx)
defp op(%{"op" => "CALL"} = log, ctx), do: call_op(log, "call", ctx) defp op(%{"op" => "CALL"} = log, ctx), do: call_op(log, "call", ctx)
defp op(%{"op" => "CALLCODE"} = log, ctx), do: call_op(log, "callcode", ctx) defp op(%{"op" => "CALLCODE"} = log, ctx), do: call_op(log, "callcode", ctx)
@ -155,7 +156,8 @@ defmodule EthereumJSONRPC.Geth.Tracer do
defp create_op( defp create_op(
%{"stack" => log_stack, "memory" => log_memory}, %{"stack" => log_stack, "memory" => log_memory},
%{depth: stack_depth, stack: stack, trace_address: trace_address, calls: calls} = ctx %{depth: stack_depth, stack: stack, trace_address: trace_address, calls: calls} = ctx,
type \\ "create"
) do ) do
[value, input_offset, input_length | _] = Enum.reverse(log_stack) [value, input_offset, input_length | _] = Enum.reverse(log_stack)
@ -165,7 +167,7 @@ defmodule EthereumJSONRPC.Geth.Tracer do
|> String.slice(quantity_to_integer("0x" <> input_offset) * 2, quantity_to_integer("0x" <> input_length) * 2) |> String.slice(quantity_to_integer("0x" <> input_offset) * 2, quantity_to_integer("0x" <> input_length) * 2)
call = %{ call = %{
"type" => "create", "type" => type,
"from" => nil, "from" => nil,
"traceAddress" => Enum.reverse(trace_address), "traceAddress" => Enum.reverse(trace_address),
"init" => "0x" <> init, "init" => "0x" <> init,

@ -91,6 +91,9 @@
case 'CREATE': case 'CREATE':
this.createOp(log); this.createOp(log);
break; break;
case 'CREATE2':
this.create2Op(log);
break;
case 'SELFDESTRUCT': case 'SELFDESTRUCT':
this.selfDestructOp(log, db); this.selfDestructOp(log, db);
break; break;
@ -127,7 +130,7 @@
const ret = log.stack.peek(0); const ret = log.stack.peek(0);
if (!ret.equals(0)) { if (!ret.equals(0)) {
if (call.type === 'create') { if (call.type === 'create' || call.type === 'create2') {
call.createdContractAddressHash = toHex(toAddress(ret.toString(16))); call.createdContractAddressHash = toHex(toAddress(ret.toString(16)));
call.createdContractCode = toHex(db.getCode(toAddress(ret.toString(16)))); call.createdContractCode = toHex(db.getCode(toAddress(ret.toString(16))));
} else { } else {
@ -162,6 +165,21 @@
this.callStack.push(call); this.callStack.push(call);
}, },
create2Op(log) {
const inputOffset = log.stack.peek(1).valueOf();
const inputLength = log.stack.peek(2).valueOf();
const inputEnd = inputOffset + inputLength;
const stackValue = log.stack.peek(0);
const call = {
type: 'create2',
from: toHex(log.contract.getAddress()),
init: toHex(log.memory.slice(inputOffset, inputEnd)),
valueBigInt: bigInt(stackValue.toString(10))
};
this.callStack.push(call);
},
selfDestructOp(log, db) { selfDestructOp(log, db) {
const contractAddress = log.contract.getAddress(); const contractAddress = log.contract.getAddress();
@ -243,6 +261,9 @@
case 'CREATE': case 'CREATE':
result = this.ctxToCreate(ctx, db); result = this.ctxToCreate(ctx, db);
break; break;
case 'CREATE2':
result = this.ctxToCreate2(ctx, db);
break;
} }
return result; return result;
@ -292,6 +313,22 @@
return result; return result;
}, },
ctxToCreate2(ctx, db) {
const result = {
type: 'create2',
from: toHex(ctx.from),
init: toHex(ctx.input),
valueBigInt: bigInt(ctx.value.toString(10)),
gasBigInt: bigInt(ctx.gas),
gasUsedBigInt: bigInt(ctx.gasUsed)
};
this.putBottomChildCalls(result);
this.putErrorOrCreatedContract(result, ctx, db);
return result;
},
putBottomChildCalls(result) { putBottomChildCalls(result) {
const bottomCall = this.bottomCall(); const bottomCall = this.bottomCall();
const bottomChildCalls = bottomCall.calls; const bottomChildCalls = bottomCall.calls;
@ -422,4 +459,3 @@
call.gasUsed = '0x' + gasUsedBigInt.toString(16); call.gasUsed = '0x' + gasUsedBigInt.toString(16);
} }
} }

@ -1818,7 +1818,7 @@ defmodule Explorer.Chain do
Repo.one!(query) Repo.one!(query)
end end
def last_block_status do def last_db_block_status do
query = query =
from(block in Block, from(block in Block,
select: {block.number, block.timestamp}, select: {block.number, block.timestamp},
@ -1827,11 +1827,27 @@ defmodule Explorer.Chain do
limit: 1 limit: 1
) )
case Repo.one(query) do query
nil -> |> Repo.one()
{:error, :no_blocks} |> block_status()
end
def last_cache_block_status do
[
paging_options: %PagingOptions{page_size: 1}
]
|> list_blocks()
|> List.last()
|> case do
%{timestamp: timestamp, number: number} ->
block_status({number, timestamp})
{number, timestamp} -> _ ->
block_status(nil)
end
end
defp block_status({number, timestamp}) do
now = DateTime.utc_now() now = DateTime.utc_now()
last_block_period = DateTime.diff(now, timestamp, :millisecond) last_block_period = DateTime.diff(now, timestamp, :millisecond)
@ -1841,7 +1857,8 @@ defmodule Explorer.Chain do
{:ok, number, timestamp} {:ok, number, timestamp}
end end
end end
end
defp block_status(nil), do: {:error, :no_blocks}
@doc """ @doc """
Calculates the ranges of missing consensus blocks in `range`. Calculates the ranges of missing consensus blocks in `range`.

@ -392,7 +392,7 @@ defmodule Explorer.Chain.InternalTransaction do
@create_required_fields ~w(from_address_hash gas index init trace_address transaction_hash value)a @create_required_fields ~w(from_address_hash gas index init trace_address transaction_hash value)a
@create_allowed_fields @create_optional_fields ++ @create_required_fields @create_allowed_fields @create_optional_fields ++ @create_required_fields
defp type_changeset(changeset, attrs, :create) do defp type_changeset(changeset, attrs, type) when type in [:create, :create2] do
changeset changeset
|> cast(attrs, @create_allowed_fields) |> cast(attrs, @create_allowed_fields)
|> validate_required(@create_required_fields) |> validate_required(@create_required_fields)
@ -537,7 +537,7 @@ defmodule Explorer.Chain.InternalTransaction do
|> put_raw_call_error_or_result(transaction) |> put_raw_call_error_or_result(transaction)
end end
defp internal_transaction_to_raw(%{type: :create} = transaction) do defp internal_transaction_to_raw(%{type: type} = transaction) when type in [:create, :create2] do
%{ %{
from_address_hash: from_address_hash, from_address_hash: from_address_hash,
gas: gas, gas: gas,
@ -549,7 +549,7 @@ defmodule Explorer.Chain.InternalTransaction do
action = %{"from" => from_address_hash, "gas" => gas, "init" => init, "value" => value} action = %{"from" => from_address_hash, "gas" => gas, "init" => init, "value" => value}
%{ %{
"type" => "create", "type" => Atom.to_string(type),
"action" => Action.to_raw(action), "action" => Action.to_raw(action),
"traceAddress" => trace_address "traceAddress" => trace_address
} }

@ -11,7 +11,7 @@ defmodule Explorer.Chain.InternalTransaction.Type do
* `:reward` * `:reward`
* `:selfdestruct` * `:selfdestruct`
""" """
@type t :: :call | :create | :reward | :selfdestruct @type t :: :call | :create | :create2 | :reward | :selfdestruct
@doc """ @doc """
Casts `term` to `t:t/0` Casts `term` to `t:t/0`
@ -22,6 +22,8 @@ defmodule Explorer.Chain.InternalTransaction.Type do
{:ok, :call} {:ok, :call}
iex> Explorer.Chain.InternalTransaction.Type.cast(:create) iex> Explorer.Chain.InternalTransaction.Type.cast(:create)
{:ok, :create} {:ok, :create}
iex> Explorer.Chain.InternalTransaction.Type.cast(:create2)
{:ok, :create2}
iex> Explorer.Chain.InternalTransaction.Type.cast(:reward) iex> Explorer.Chain.InternalTransaction.Type.cast(:reward)
{:ok, :reward} {:ok, :reward}
iex> Explorer.Chain.InternalTransaction.Type.cast(:selfdestruct) iex> Explorer.Chain.InternalTransaction.Type.cast(:selfdestruct)
@ -33,6 +35,8 @@ defmodule Explorer.Chain.InternalTransaction.Type do
{:ok, :call} {:ok, :call}
iex> Explorer.Chain.InternalTransaction.Type.cast("create") iex> Explorer.Chain.InternalTransaction.Type.cast("create")
{:ok, :create} {:ok, :create}
iex> Explorer.Chain.InternalTransaction.Type.cast("create2")
{:ok, :create2}
iex> Explorer.Chain.InternalTransaction.Type.cast("reward") iex> Explorer.Chain.InternalTransaction.Type.cast("reward")
{:ok, :reward} {:ok, :reward}
iex> Explorer.Chain.InternalTransaction.Type.cast("selfdestruct") iex> Explorer.Chain.InternalTransaction.Type.cast("selfdestruct")
@ -53,9 +57,10 @@ defmodule Explorer.Chain.InternalTransaction.Type do
""" """
@impl Ecto.Type @impl Ecto.Type
@spec cast(term()) :: {:ok, t()} | :error @spec cast(term()) :: {:ok, t()} | :error
def cast(t) when t in ~w(call create selfdestruct reward)a, do: {:ok, t} def cast(t) when t in ~w(call create create2 selfdestruct reward)a, do: {:ok, t}
def cast("call"), do: {:ok, :call} def cast("call"), do: {:ok, :call}
def cast("create"), do: {:ok, :create} def cast("create"), do: {:ok, :create}
def cast("create2"), do: {:ok, :create2}
def cast("reward"), do: {:ok, :reward} def cast("reward"), do: {:ok, :reward}
def cast("selfdestruct"), do: {:ok, :selfdestruct} def cast("selfdestruct"), do: {:ok, :selfdestruct}
def cast(_), do: :error def cast(_), do: :error
@ -67,6 +72,8 @@ defmodule Explorer.Chain.InternalTransaction.Type do
{:ok, "call"} {:ok, "call"}
iex> Explorer.Chain.InternalTransaction.Type.dump(:create) iex> Explorer.Chain.InternalTransaction.Type.dump(:create)
{:ok, "create"} {:ok, "create"}
iex> Explorer.Chain.InternalTransaction.Type.dump(:create2)
{:ok, "create2"}
iex> Explorer.Chain.InternalTransaction.Type.dump(:reward) iex> Explorer.Chain.InternalTransaction.Type.dump(:reward)
{:ok, "reward"} {:ok, "reward"}
iex> Explorer.Chain.InternalTransaction.Type.dump(:selfdestruct) iex> Explorer.Chain.InternalTransaction.Type.dump(:selfdestruct)
@ -87,6 +94,7 @@ defmodule Explorer.Chain.InternalTransaction.Type do
@spec dump(term()) :: {:ok, String.t()} | :error @spec dump(term()) :: {:ok, String.t()} | :error
def dump(:call), do: {:ok, "call"} def dump(:call), do: {:ok, "call"}
def dump(:create), do: {:ok, "create"} def dump(:create), do: {:ok, "create"}
def dump(:create2), do: {:ok, "create2"}
def dump(:reward), do: {:ok, "reward"} def dump(:reward), do: {:ok, "reward"}
def dump(:selfdestruct), do: {:ok, "selfdestruct"} def dump(:selfdestruct), do: {:ok, "selfdestruct"}
def dump(_), do: :error def dump(_), do: :error
@ -98,6 +106,8 @@ defmodule Explorer.Chain.InternalTransaction.Type do
{:ok, :call} {:ok, :call}
iex> Explorer.Chain.InternalTransaction.Type.load("create") iex> Explorer.Chain.InternalTransaction.Type.load("create")
{:ok, :create} {:ok, :create}
iex> Explorer.Chain.InternalTransaction.Type.load("create2")
{:ok, :create2}
iex> Explorer.Chain.InternalTransaction.Type.load("reward") iex> Explorer.Chain.InternalTransaction.Type.load("reward")
{:ok, :reward} {:ok, :reward}
iex> Explorer.Chain.InternalTransaction.Type.load("selfdestruct") iex> Explorer.Chain.InternalTransaction.Type.load("selfdestruct")
@ -118,6 +128,7 @@ defmodule Explorer.Chain.InternalTransaction.Type do
@spec load(term()) :: {:ok, t()} | :error @spec load(term()) :: {:ok, t()} | :error
def load("call"), do: {:ok, :call} def load("call"), do: {:ok, :call}
def load("create"), do: {:ok, :create} def load("create"), do: {:ok, :create}
def load("create2"), do: {:ok, :create2}
def load("reward"), do: {:ok, :reward} def load("reward"), do: {:ok, :reward}
def load("selfdestruct"), do: {:ok, :selfdestruct} def load("selfdestruct"), do: {:ok, :selfdestruct}
# deprecated # deprecated

@ -50,21 +50,35 @@ defmodule Explorer.ChainTest do
end end
end end
describe "last_block_status/0" do describe "last_db_block_status/0" do
test "return no_blocks errors if db is empty" do test "return no_blocks errors if db is empty" do
assert {:error, :no_blocks} = Chain.last_block_status() assert {:error, :no_blocks} = Chain.last_db_block_status()
end end
test "returns {:ok, last_block_period} if block is in healthy period" do test "returns {:ok, last_block_period} if block is in healthy period" do
insert(:block, consensus: true) insert(:block, consensus: true)
assert {:ok, _, _} = Chain.last_block_status() assert {:ok, _, _} = Chain.last_db_block_status()
end end
test "return {:ok, last_block_period} if block is not in healthy period" do test "return {:ok, last_block_period} if block is not in healthy period" do
insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50)) insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50))
assert {:error, _, _} = Chain.last_block_status() assert {:error, _, _} = Chain.last_db_block_status()
end
end
describe "last_cache_block_status/0" do
test "returns success if cache is not stale" do
insert(:block, consensus: true)
assert {:ok, _, _} = Chain.last_cache_block_status()
end
test "return error if cache is stale" do
insert(:block, consensus: true, timestamp: Timex.shift(DateTime.utc_now(), hours: -50))
assert {:error, _, _} = Chain.last_cache_block_status()
end end
end end

Loading…
Cancel
Save