From 9819522ea1bd8e25645fa1195838f188d2a45bfe Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Mon, 4 Mar 2024 13:45:13 +0300 Subject: [PATCH] Optimism chain type (#9460) * Transaction page L1 fields * Path fix * Reduce the number of files from 19 to 5 in logs rotate config * Customize optimism-goerli deployment * Optimism branding * Remove testnet logo text. OG uses customized label * Fix Circles theme * L1 tx fields fix for Optimism BedRock update * Remove redundant line * Add gas_price handling for elixir_to_params and change function ordering * Remove l1TxOrigin handling for another version of RPC * Add GA * Fix realtime fetcher test * Update Changelog * Fix internal transactions processing for non-consensus blocks * Lose consensus only for consensus=true blocks * Fix handling transaction RPC responses without some fields * Fix tests except for indexer module * Add Optimism BedRock support (Txn Batches, Output Roots, Deposits, Withdrawals) (#6980) * Add op_output_roots table * Add OptimismOutputRoots runner * Add initial code for output roots fetcher * Add checks to init function * Partially add logs and L1 reorgs handling * Add reorgs handling * Add RPC retries * Write output roots to database * Log output roots handling * Update indexer README * Add API v2 for Optimism Output Roots * Add op_withdrawals table * Add OptimismWithdrawals runner * Prepare realtime optimism withdrawals fetching * Add realtime optimism withdrawals fetching * Define checks in init function * log.first_topic can be nil * Show total count of output roots in API v2 * Add msg_nonce gaps filler * Refactoring * Intermediate refactoring * Add historical withdrawals handling and refactor * Finish op_withdrawals table filling * Small refactoring * Add op_withdrawal_events table * Add OptimismWithdrawalEvents runner * Add OptimismWithdrawalEvent fetcher * Update indexer README * Add API v2 for Optimism Withdrawals * Add env variables to common-blockscout.env and Makefile * Set `from` as address object instead of just address hash for withdrawal * mix format * Add op_transaction_batches table * Add OptimismTxnBatches runner * Add a draft for OptimismTxnBatch fetcher * Add a draft for OptimismTxnBatch * Extend a draft for OptimismTxnBatch * Extend OptimismTxnBatch * Finish OptimismTxnBatch (without reorgs handling yet) * Optimize OptimismTxnBatch fetcher * Remove duplicated txn batches * Add zlib_inflate_handler for empty case * Add reorgs handling for txn batches * Fix reorgs handling for txn batches * Small refactor * Finish Indexer.Fetcher.OptimismTxnBatch (without refactoring yet) * Apply new ex_rlp version * Add API v2 for Optimism Txn Batches * Add env variables to common-blockscout.env and Makefile * Refactor OptimismTxnBatch fetcher for mix credo * Replace binary_slice with binary_part function to run with Elixir 1.13 * Update changelog * Update indexer readme * Rename op_withdrawals.l2_tx_hash field to l2_transaction_hash * Rename l1_tx_hash fields to l1_transaction_hash * Rename *tx* fields to *transaction* fields * Rename env variables * Rename env variables * Add an indexer helper * Add an indexer helper * Small refactoring * Fix tx_count for txn batches view * Use EthereumJSONRPC.Block.ByHash instead of the raw call * Infinity timeout for blocks query * Small refactoring * Refactor init function for two modules * Small refactoring * Rename l1_transaction_timestamp field to l1_timestamp * Rename withdrawal_hash field to hash * Refactor for decode_data function * Refactor for mix credo * Add INDEXER_OPTIMISM_L1_BATCH_BLOCKS_CHUNK_SIZE env and small refactoring * Add INDEXER_OPTIMISM_L1_BATCH_BLOCKS_CHUNK_SIZE env to other files * Add an index for l1_block_number field * Add an index for l1_block_number field * Remove redundant :ok * Use faster way to count rows in a table * Refactor reorgs monitor functions * Clarify frame structure * Reduce storage consumption for optimism transaction batches * Reuse CacheHelper.estimated_count_from function * Bedrock optimism deposits (#6993) * Create `op_deposits` table * Add OptimismDeposit runner * WIP Fetcher * Finish fetcher * Integrate deposits into APIv2 * Add envs * Fix requests * Remove debug * Update envs names * Rename `tx` -> `transaction` * Reuse `decode_data/2` * Fix review * Add `uninstall_filter` * Fix formatting * Switch to realtime mode more carefully * Fix review Allow nil in timestamp Add progress logging Improve check_interval calculation * Fix logging and env * Fix Association.NotLoaded error * Replace switching to realtime mode log * Remove excess start_block * Fix reorg logging * Fix `from_block` > `to_block` and add realtime logging * Fix block boundaries --------- Co-authored-by: POA <33550681+poa@users.noreply.github.com> * mix format * Return total count of L2 entity by a separate API request * Filter by consensus blocks * Parallelize tx count operation and small refactoring * Use read replica for L2 entities in API * Parse block_number and tx_hash for Optimism Deposits module * Return page_size back to 50 * Small fixes and refactoring * Update apps/block_scout_web/lib/block_scout_web/api_router.ex Co-authored-by: Maxim Filonov <53992153+sl1depengwyn@users.noreply.github.com> * Small optimization * Use ecto association instead of explicit join for txn batches * Refactoring * Use Stream inspead of Enum * Small refactoring * Add assoc for transaction batches in OptimismFrameSequence * Use common reorg monitor for Optimism modules * Rename Explorer.Helpers to Explorer.Helper * Don't start an optimism module unless the main optimism module is not started * Don't start reorg monitor for optimism modules when it is not needed * Small refactoring * Remove debug broadcasting * Add Optimism BedRock Deposits to the main page in API (#7200) * Add Optimism BedRock Deposits to the main page in API * Update changelog * Pass the number of deposits instead of only one item per once --------- Co-authored-by: POA <33550681+poa@users.noreply.github.com> * Refactor for credo * Output L1 fields in API v2 for transaction page * Update changelog * Use helper * Refactor Indexer.Fetcher.Optimism * Fix l1_timestamp issue in OptimismTxnBatch fetcher * Reset Logger metadata before Indexer.Transform.OptimismWithdrawals.parse function finishes * Fix IDs ordering in remove_duplicates function of Indexer.Fetcher.OptimismTxnBatch * Consider rewriting of the first frame in Indexer.Fetcher.OptimismTxnBatch * Fix Indexer.Fetcher.OptimismTxnBatch (consider chunking) * Fix Indexer.Fetcher.OptimismTxnBatch * Fix handling invalid frame sequences in Indexer.Fetcher.OptimismTxnBatch * Read Optimism finalization period from a smart contract * Fixes for dialyzer * Fix for EthereumJSONRPC tests * Fixes for Explorer tests * Fixes for Explorer tests * Fix of block/realtime/fetcher_test.exs * mix format and small fixes for block_scout_web tests * Reset GA cache * Fix handling nil in PendingBlockOperation.estimated_count() --------- Co-authored-by: POA <33550681+poa@users.noreply.github.com> Co-authored-by: Maxim Filonov <53992153+sl1depengwyn@users.noreply.github.com> * Fix autocomplete * Fix merging conflicts * Add exit handler to Indexer.Fetcher.OptimismWithdrawal * Fix transactions ordering in Indexer.Fetcher.OptimismTxnBatch * Update changelog * Refactor to fix credo * Mix credo fix * Fix transaction batches module for L2 OP stack (#7827) * Fix mixed transactions handling in Indexer.Fetcher.OptimismTxnBatch * Ignore duplicated frame * Update changelog * Add sorting to the future frames list * Change list order --------- Co-authored-by: POA <33550681+poa@users.noreply.github.com> * Remove unused aliases * Ignore previously handled frame by OP transaction batches module (#8122) * Ignore duplicated frame * Update changelog --------- Co-authored-by: POA <33550681+poa@users.noreply.github.com> * Return alias for Explorer.Chain.Cache.Helper in chain.ex * Ignore invalid frame by OP transaction batches module (#8208) * Update changelog * Ignore invalid frame * Update changelog --------- Co-authored-by: POA <33550681+poa@users.noreply.github.com> * Fix Indexer.Fetcher.OptimismTxnBatch * Fix API v2 for OP Withdrawals * Refactor optimism fetchers init * Add log for switching from fallback url * Fix for Indexer.Fetcher.OptimismTxnBatch * Add OP withdrawal status to transaction page in API (#8702) * Add OP withdrawal status to transaction page in API * Update changelog * Small refactoring * Update .dialyzer-ignore --------- Co-authored-by: POA <33550681+poa@users.noreply.github.com> * Add start pause to `Indexer.Fetcher.OptimismTxnBatch` * Small refactor of `Indexer.Fetcher.OptimismTxnBatch` * Consider consensus block only when retrieving OP withdrawal transaction status (#8811) * Consider consensus block only when retrieving OP withdrawal transaction status * Update changelog * Clear GA cache --------- Co-authored-by: POA <33550681+poa@users.noreply.github.com> * Hotfix for optimism_withdrawal_transaction_status function * Return all OP Withdrawals bound to L2 transaction * Try to import config * Remove unused functions from Explorer.Chain * Refactor for mix credo * Fix order of proxy standards: 1167, 1967 * Fixes in Optimism due to changed log topics type * Fix for EthereumJSONRPC tests * Clear GA cache and update cspell.json * Fix indexer tests * Return current exchange rate in api/v2/stats * Fix log decoding bug * Temp disable build of image for arm64 * Rewrite Indexer.Fetcher.OptimismTxnBatch module * Add handling of span batches * Add support of latest block for Optimism modules * Update changelog and spelling * Rewrite Indexer.Fetcher.OptimismTxnBatch module * Add handling of span batches * Add support of latest block for Optimism modules * Refactoring * Partially add specs and docs for public functions * Refactoring * add an entry to CHANEGELOG.md * apply review (use origin entity instead of joined entity in with tx status) * Fixes after rebase * Remove old UI sustomizations * Optimism chain type * Change structure of folders * Fixes after review * Fix CHANGELOG * Fixes after 2nd review * Process 3d review: add tests for fee/2 function * Process 4th review * Review fix: move Op related functions from chain.ex * Review fix: make OptimismFinalizationPeriod configurable * Process review comment * System.get_env("CHAIN_TYPE") => Application.get_env(:explorer, :chain_type) --------- Co-authored-by: POA <33550681+poa@users.noreply.github.com> Co-authored-by: Qwerty5Uiop Co-authored-by: varasev <33550681+varasev@users.noreply.github.com> Co-authored-by: Maxim Filonov <53992153+sl1depengwyn@users.noreply.github.com> Co-authored-by: rlgns98kr --- .github/workflows/config.yml | 2 +- .../publish-docker-image-for-optimism.yml | 3 +- .github/workflows/release-optimism.yml | 45 + CHANGELOG.md | 24 +- .../lib/block_scout_web/api_router.ex | 33 +- .../lib/block_scout_web/chain.ex | 43 + .../channels/optimism_deposit_channel.ex | 22 + .../block_scout_web/channels/user_socket.ex | 1 + .../channels/user_socket_v2.ex | 1 + .../api/v2/main_page_controller.ex | 16 +- .../controllers/api/v2/optimism_controller.ex | 111 +++ .../lib/block_scout_web/notifier.ex | 8 + .../block_scout_web/realtime_event_handler.ex | 1 + .../templates/block/_tile.html.eex | 2 +- .../templates/chain/show.html.eex | 32 +- .../internal_transaction/_tile.html.eex | 2 +- .../templates/layout/_topnav.html.eex | 20 +- .../transaction/_pending_tile.html.eex | 2 +- .../templates/transaction/_tile.html.eex | 4 +- .../templates/transaction/overview.html.eex | 95 +- .../views/api/v2/optimism_view.ex | 149 +++ .../views/api/v2/transaction_view.ex | 36 + .../views/cldr_helper/number.ex | 2 + .../block_scout_web/views/transaction_view.ex | 14 + apps/block_scout_web/mix.exs | 10 +- apps/block_scout_web/priv/gettext/default.pot | 351 +++++--- .../priv/gettext/en/LC_MESSAGES/default.po | 353 +++++--- apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex | 10 + .../lib/ethereum_jsonrpc/block/by_hash.ex | 6 +- .../lib/ethereum_jsonrpc/receipt.ex | 25 +- .../lib/ethereum_jsonrpc/receipts.ex | 6 + .../lib/ethereum_jsonrpc/transaction.ex | 103 ++- .../utility/endpoint_availability_checker.ex | 5 +- .../utility/endpoint_availability_observer.ex | 3 + .../lib/ethereum_jsonrpc/variant.ex | 1 + apps/explorer/config/dev.exs | 3 + apps/explorer/config/prod.exs | 4 + apps/explorer/config/test.exs | 1 + apps/explorer/lib/explorer/application.ex | 2 + apps/explorer/lib/explorer/chain.ex | 19 +- .../lib/explorer/chain/address/counters.ex | 2 +- .../lib/explorer/chain/cache/block.ex | 10 +- .../lib/explorer/chain/cache/helper.ex | 2 +- .../cache/optimism_finalization_period.ex | 54 ++ .../chain/cache/pending_block_operation.ex | 2 +- .../lib/explorer/chain/cache/transaction.ex | 2 +- .../lib/explorer/chain/events/publisher.ex | 2 +- .../lib/explorer/chain/events/subscriber.ex | 2 +- .../chain/import/runner/optimism/deposits.ex | 106 +++ .../import/runner/optimism/frame_sequences.ex | 102 +++ .../import/runner/optimism/output_roots.ex | 108 +++ .../import/runner/optimism/txn_batches.ex | 100 +++ .../runner/optimism/withdrawal_events.ex | 105 +++ .../import/runner/optimism/withdrawals.ex | 104 +++ .../chain/import/runner/transactions.ex | 406 +++++---- .../chain/import/stage/block_referencing.ex | 16 +- .../lib/explorer/chain/optimism/deposit.ex | 86 ++ .../explorer/chain/optimism/frame_sequence.ex | 33 + .../explorer/chain/optimism/output_root.ex | 67 ++ .../lib/explorer/chain/optimism/txn_batch.ex | 61 ++ .../lib/explorer/chain/optimism/withdrawal.ex | 163 ++++ .../chain/optimism/withdrawal_event.ex | 34 + .../lib/explorer/chain/transaction.ex | 78 +- apps/explorer/lib/explorer/helper.ex | 17 +- apps/explorer/lib/explorer/repo.ex | 10 + ...0243_transaction_columns_to_support_l2.exs | 14 + ...230131115105_add_op_output_roots_table.exs | 16 + ...0230206123308_add_op_withdrawals_table.exs | 14 + ...2162845_add_op_withdrawal_events_table.exs | 22 + ...35703_add_op_transaction_batches_table.exs | 14 + .../20230220202107_create_op_deposits.exs | 17 + .../20230301105051_rename_fields.exs | 12 + .../20230303125841_add_op_indexes.exs | 8 + ...307090655_add_op_frame_sequences_table.exs | 24 + ...3_modify_collated_gas_price_constraint.exs | 15 + ...20231025102325_add_op_withdrawal_index.exs | 7 + ...124124644_remove_op_epoch_number_field.exs | 9 + .../test/explorer/chain/transaction_test.exs | 46 + apps/indexer/README.md | 6 + apps/indexer/lib/indexer/block/fetcher.ex | 10 + .../lib/indexer/block/realtime/fetcher.ex | 12 + .../indexer/fetcher/coin_balance/realtime.ex | 1 - apps/indexer/lib/indexer/fetcher/optimism.ex | 406 +++++++++ .../lib/indexer/fetcher/optimism/deposit.ex | 565 ++++++++++++ .../indexer/fetcher/optimism/output_root.ex | 187 ++++ .../lib/indexer/fetcher/optimism/txn_batch.ex | 850 ++++++++++++++++++ .../indexer/fetcher/optimism/withdrawal.ex | 361 ++++++++ .../fetcher/optimism/withdrawal_event.ex | 226 +++++ .../lib/indexer/fetcher/polygon_edge.ex | 32 +- .../indexer/fetcher/polygon_edge/deposit.ex | 3 +- .../fetcher/polygon_edge/deposit_execute.ex | 7 +- .../fetcher/polygon_edge/withdrawal.ex | 7 +- .../fetcher/polygon_zkevm/bridge_l1.ex | 4 +- .../fetcher/polygon_zkevm/bridge_l2.ex | 4 +- .../lib/indexer/fetcher/shibarium/l1.ex | 21 +- .../lib/indexer/fetcher/shibarium/l2.ex | 10 +- .../lib/indexer/fetcher/transaction_action.ex | 7 +- apps/indexer/lib/indexer/helper.ex | 27 +- apps/indexer/lib/indexer/supervisor.ex | 12 + .../lib/indexer/transform/addresses.ex | 8 +- .../indexer/transform/optimism/withdrawals.ex | 49 + .../indexer/transform/polygon_zkevm/bridge.ex | 6 +- .../lib/indexer/transform/shibarium/bridge.ex | 6 +- .../lib/indexer/transform/token_transfers.ex | 15 +- apps/indexer/mix.exs | 15 +- config/config_helper.exs | 1 + config/runtime.exs | 35 + config/runtime/dev.exs | 7 + config/runtime/prod.exs | 6 + cspell.json | 5 + docker-compose/envs/common-blockscout.env | 14 + mix.lock | 1 + 112 files changed, 5754 insertions(+), 632 deletions(-) create mode 100644 .github/workflows/release-optimism.yml create mode 100644 apps/block_scout_web/lib/block_scout_web/channels/optimism_deposit_channel.ex create mode 100644 apps/block_scout_web/lib/block_scout_web/controllers/api/v2/optimism_controller.ex create mode 100644 apps/block_scout_web/lib/block_scout_web/views/api/v2/optimism_view.ex create mode 100644 apps/explorer/lib/explorer/chain/cache/optimism_finalization_period.ex create mode 100644 apps/explorer/lib/explorer/chain/import/runner/optimism/deposits.ex create mode 100644 apps/explorer/lib/explorer/chain/import/runner/optimism/frame_sequences.ex create mode 100644 apps/explorer/lib/explorer/chain/import/runner/optimism/output_roots.ex create mode 100644 apps/explorer/lib/explorer/chain/import/runner/optimism/txn_batches.ex create mode 100644 apps/explorer/lib/explorer/chain/import/runner/optimism/withdrawal_events.ex create mode 100644 apps/explorer/lib/explorer/chain/import/runner/optimism/withdrawals.ex create mode 100644 apps/explorer/lib/explorer/chain/optimism/deposit.ex create mode 100644 apps/explorer/lib/explorer/chain/optimism/frame_sequence.ex create mode 100644 apps/explorer/lib/explorer/chain/optimism/output_root.ex create mode 100644 apps/explorer/lib/explorer/chain/optimism/txn_batch.ex create mode 100644 apps/explorer/lib/explorer/chain/optimism/withdrawal.ex create mode 100644 apps/explorer/lib/explorer/chain/optimism/withdrawal_event.ex create mode 100644 apps/explorer/priv/optimism/migrations/20220204060243_transaction_columns_to_support_l2.exs create mode 100644 apps/explorer/priv/optimism/migrations/20230131115105_add_op_output_roots_table.exs create mode 100644 apps/explorer/priv/optimism/migrations/20230206123308_add_op_withdrawals_table.exs create mode 100644 apps/explorer/priv/optimism/migrations/20230212162845_add_op_withdrawal_events_table.exs create mode 100644 apps/explorer/priv/optimism/migrations/20230216135703_add_op_transaction_batches_table.exs create mode 100644 apps/explorer/priv/optimism/migrations/20230220202107_create_op_deposits.exs create mode 100644 apps/explorer/priv/optimism/migrations/20230301105051_rename_fields.exs create mode 100644 apps/explorer/priv/optimism/migrations/20230303125841_add_op_indexes.exs create mode 100644 apps/explorer/priv/optimism/migrations/20230307090655_add_op_frame_sequences_table.exs create mode 100644 apps/explorer/priv/optimism/migrations/20230731130103_modify_collated_gas_price_constraint.exs create mode 100644 apps/explorer/priv/optimism/migrations/20231025102325_add_op_withdrawal_index.exs create mode 100644 apps/explorer/priv/optimism/migrations/20240124124644_remove_op_epoch_number_field.exs create mode 100644 apps/indexer/lib/indexer/fetcher/optimism.ex create mode 100644 apps/indexer/lib/indexer/fetcher/optimism/deposit.ex create mode 100644 apps/indexer/lib/indexer/fetcher/optimism/output_root.ex create mode 100644 apps/indexer/lib/indexer/fetcher/optimism/txn_batch.ex create mode 100644 apps/indexer/lib/indexer/fetcher/optimism/withdrawal.ex create mode 100644 apps/indexer/lib/indexer/fetcher/optimism/withdrawal_event.ex create mode 100644 apps/indexer/lib/indexer/transform/optimism/withdrawals.ex diff --git a/.github/workflows/config.yml b/.github/workflows/config.yml index 4f22355b41..f0dc78055c 100644 --- a/.github/workflows/config.yml +++ b/.github/workflows/config.yml @@ -48,7 +48,7 @@ jobs: run: | echo "matrix=$matrixStringifiedObject" >> $GITHUB_OUTPUT env: - matrixStringifiedObject: '{"chain-type": ["ethereum", "polygon_edge", "polygon_zkevm", "rsk", "suave", "stability", "filecoin"]}' + matrixStringifiedObject: '{"chain-type": ["ethereum", "polygon_edge", "polygon_zkevm", "rsk", "suave", "stability", "filecoin", "optimism"]}' build-and-cache: name: Build and Cache deps diff --git a/.github/workflows/publish-docker-image-for-optimism.yml b/.github/workflows/publish-docker-image-for-optimism.yml index c47114afc5..1336180876 100644 --- a/.github/workflows/publish-docker-image-for-optimism.yml +++ b/.github/workflows/publish-docker-image-for-optimism.yml @@ -39,4 +39,5 @@ jobs: ADMIN_PANEL_ENABLED=false CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-beta.+commit.${{ env.SHORT_SHA }} - RELEASE_VERSION=${{ env.RELEASE_VERSION }} \ No newline at end of file + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=optimism \ No newline at end of file diff --git a/.github/workflows/release-optimism.yml b/.github/workflows/release-optimism.yml new file mode 100644 index 0000000000..ed99f43726 --- /dev/null +++ b/.github/workflows/release-optimism.yml @@ -0,0 +1,45 @@ +name: Release for Ethereum + +on: + release: + types: [published] + +env: + OTP_VERSION: ${{ vars.OTP_VERSION }} + ELIXIR_VERSION: ${{ vars.ELIXIR_VERSION }} + +jobs: + push_to_registry: + name: Push Docker image to Docker Hub + runs-on: ubuntu-latest + env: + RELEASE_VERSION: ${{ vars.RELEASE_VERSION }} + steps: + - uses: actions/checkout@v4 + - name: Setup repo + uses: ./.github/actions/setup-repo + with: + docker-username: ${{ secrets.DOCKER_USERNAME }} + docker-password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push Docker image for Optimism + uses: docker/build-push-action@v5 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: blockscout/blockscout-optimism:latest, blockscout/blockscout-optimism:${{ env.RELEASE_VERSION }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + CACHE_EXCHANGE_RATES_PERIOD= + API_V1_READ_METHODS_DISABLED=false + DISABLE_WEBAPP=false + API_V1_WRITE_METHODS_DISABLED=false + CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= + ADMIN_PANEL_ENABLED=false + CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-beta + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=optimism \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index cad25b874a..0c4440da5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,32 @@ ### Features - [#9461](https://github.com/blockscout/blockscout/pull/9461) - Fetch blocks without internal transactions backwards +- [#9460](https://github.com/blockscout/blockscout/pull/9460) - Optimism chain type +- [#8702](https://github.com/blockscout/blockscout/pull/8702) - Add OP withdrawal status to transaction page in API +- [#7200](https://github.com/blockscout/blockscout/pull/7200) - Add Optimism BedRock Deposits to the main page in API +- [#6980](https://github.com/blockscout/blockscout/pull/6980) - Add Optimism BedRock support (Txn Batches, Output Roots, Deposits, Withdrawals) ### Fixes - [#9512](https://github.com/blockscout/blockscout/pull/9512) - Docker-compose 2.24.6 compatibility - -### Chore +- [#9262](https://github.com/blockscout/blockscout/pull/9262) - Fix withdrawal status +- [#9123](https://github.com/blockscout/blockscout/pull/9123) - Fixes in Optimism due to changed log topics type +- [#8831](https://github.com/blockscout/blockscout/pull/8831) - Return all OP Withdrawals bound to L2 transaction +- [#8822](https://github.com/blockscout/blockscout/pull/8822) - Hotfix for optimism_withdrawal_transaction_status function +- [#8811](https://github.com/blockscout/blockscout/pull/8811) - Consider consensus block only when retrieving OP withdrawal transaction status +- [#8364](https://github.com/blockscout/blockscout/pull/8364) - Fix API v2 for OP Withdrawals +- [#8229](https://github.com/blockscout/blockscout/pull/8229) - Fix Indexer.Fetcher.OptimismTxnBatch +- [#8208](https://github.com/blockscout/blockscout/pull/8208) - Ignore invalid frame by OP transaction batches module +- [#8122](https://github.com/blockscout/blockscout/pull/8122) - Ignore previously handled frame by OP transaction batches module +- [#7827](https://github.com/blockscout/blockscout/pull/7827) - Fix transaction batches module for L2 OP stack +- [#7776](https://github.com/blockscout/blockscout/pull/7776) - Fix transactions ordering in Indexer.Fetcher.OptimismTxnBatch +- [#7219](https://github.com/blockscout/blockscout/pull/7219) - Output L1 fields in API v2 for transaction page and fix transaction fee calculation +- [#6699](https://github.com/blockscout/blockscout/pull/6699) - L1 tx fields fix for Goerli Optimism BedRock update + +### Chore + +- [#9260](https://github.com/blockscout/blockscout/pull/9260) - Optimism Delta upgrade support by Indexer.Fetcher.OptimismTxnBatch module +- [#8740](https://github.com/blockscout/blockscout/pull/8740) - Add delay to Indexer.Fetcher.OptimismTxnBatch module initialization ## 6.2.2 diff --git a/apps/block_scout_web/lib/block_scout_web/api_router.ex b/apps/block_scout_web/lib/block_scout_web/api_router.ex index 9b3e12dd76..403d78d3a4 100644 --- a/apps/block_scout_web/lib/block_scout_web/api_router.ex +++ b/apps/block_scout_web/lib/block_scout_web/api_router.ex @@ -203,11 +203,11 @@ defmodule BlockScoutWeb.ApiRouter do get("/", V2.TransactionController, :transactions) get("/watchlist", V2.TransactionController, :watchlist_transactions) - if System.get_env("CHAIN_TYPE") == "polygon_zkevm" do + if Application.compile_env(:explorer, :chain_type) == "polygon_zkevm" do get("/zkevm-batch/:batch_number", V2.TransactionController, :polygon_zkevm_batch) end - if System.get_env("CHAIN_TYPE") == "suave" do + if Application.compile_env(:explorer, :chain_type) == "suave" do get("/execution-node/:execution_node_hash_param", V2.TransactionController, :execution_node) end @@ -219,7 +219,7 @@ defmodule BlockScoutWeb.ApiRouter do get("/:transaction_hash_param/state-changes", V2.TransactionController, :state_changes) get("/:transaction_hash_param/summary", V2.TransactionController, :summary) - if System.get_env("CHAIN_TYPE") == "ethereum" do + if Application.compile_env(:explorer, :chain_type) == "ethereum" do get("/:transaction_hash_param/blobs", V2.TransactionController, :blobs) end end @@ -273,7 +273,11 @@ defmodule BlockScoutWeb.ApiRouter do get("/transactions/watchlist", V2.MainPageController, :watchlist_transactions) get("/indexing-status", V2.MainPageController, :indexing_status) - if System.get_env("CHAIN_TYPE") == "polygon_zkevm" do + if Application.compile_env(:explorer, :chain_type) == "optimism" do + get("/optimism-deposits", V2.MainPageController, :optimism_deposits) + end + + if Application.compile_env(:explorer, :chain_type) == "polygon_zkevm" do get("/zkevm/batches/confirmed", V2.PolygonZkevmController, :batches_confirmed) get("/zkevm/batches/latest-number", V2.PolygonZkevmController, :batch_latest_number) end @@ -288,8 +292,21 @@ defmodule BlockScoutWeb.ApiRouter do end end + scope "/optimism" do + if Application.compile_env(:explorer, :chain_type) == "optimism" do + get("/txn-batches", V2.OptimismController, :txn_batches) + get("/txn-batches/count", V2.OptimismController, :txn_batches_count) + get("/output-roots", V2.OptimismController, :output_roots) + get("/output-roots/count", V2.OptimismController, :output_roots_count) + get("/deposits", V2.OptimismController, :deposits) + get("/deposits/count", V2.OptimismController, :deposits_count) + get("/withdrawals", V2.OptimismController, :withdrawals) + get("/withdrawals/count", V2.OptimismController, :withdrawals_count) + end + end + scope "/polygon-edge" do - if System.get_env("CHAIN_TYPE") == "polygon_edge" do + if Application.compile_env(:explorer, :chain_type) == "polygon_edge" do get("/deposits", V2.PolygonEdgeController, :deposits) get("/deposits/count", V2.PolygonEdgeController, :deposits_count) get("/withdrawals", V2.PolygonEdgeController, :withdrawals) @@ -298,7 +315,7 @@ defmodule BlockScoutWeb.ApiRouter do end scope "/shibarium" do - if System.get_env("CHAIN_TYPE") == "shibarium" do + if Application.compile_env(:explorer, :chain_type) == "shibarium" do get("/deposits", V2.ShibariumController, :deposits) get("/deposits/count", V2.ShibariumController, :deposits_count) get("/withdrawals", V2.ShibariumController, :withdrawals) @@ -312,7 +329,7 @@ defmodule BlockScoutWeb.ApiRouter do end scope "/zkevm" do - if System.get_env("CHAIN_TYPE") == "polygon_zkevm" do + if Application.compile_env(:explorer, :chain_type) == "polygon_zkevm" do get("/batches", V2.PolygonZkevmController, :batches) get("/batches/count", V2.PolygonZkevmController, :batches_count) get("/batches/:batch_number", V2.PolygonZkevmController, :batch) @@ -348,7 +365,7 @@ defmodule BlockScoutWeb.ApiRouter do end scope "/blobs" do - if System.get_env("CHAIN_TYPE") == "ethereum" do + if Application.compile_env(:explorer, :chain_type) == "ethereum" do get("/:blob_hash_param", V2.BlobController, :blob) end end diff --git a/apps/block_scout_web/lib/block_scout_web/chain.ex b/apps/block_scout_web/lib/block_scout_web/chain.ex index 5dff1d691b..8db363d135 100644 --- a/apps/block_scout_web/lib/block_scout_web/chain.ex +++ b/apps/block_scout_web/lib/block_scout_web/chain.ex @@ -41,6 +41,9 @@ defmodule BlockScoutWeb.Chain do Wei } + alias Explorer.Chain.Optimism.Deposit, as: OptimismDeposit + alias Explorer.Chain.Optimism.OutputRoot, as: OptimismOutputRoot + alias Explorer.Chain.PolygonZkevm.TransactionBatch alias Explorer.PagingOptions @@ -337,6 +340,16 @@ defmodule BlockScoutWeb.Chain do [paging_options: %{@default_paging_options | key: {index}}] end + def paging_options(%{"nonce" => nonce_string}) when is_binary(nonce_string) do + case Integer.parse(nonce_string) do + {nonce, ""} -> + [paging_options: %{@default_paging_options | key: {nonce}}] + + _ -> + [paging_options: @default_paging_options] + end + end + def paging_options(%{"number" => number_string}) when is_binary(number_string) do case Integer.parse(number_string) do {number, ""} -> @@ -347,6 +360,10 @@ defmodule BlockScoutWeb.Chain do end end + def paging_options(%{"nonce" => nonce}) when is_integer(nonce) do + [paging_options: %{@default_paging_options | key: {nonce}}] + end + def paging_options(%{"number" => number}) when is_integer(number) do [paging_options: %{@default_paging_options | key: {number}}] end @@ -404,6 +421,16 @@ defmodule BlockScoutWeb.Chain do end end + def paging_options(%{"l1_block_number" => block_number, "tx_hash" => tx_hash}) do + with {block_number, ""} <- Integer.parse(block_number), + {:ok, tx_hash} <- string_to_transaction_hash(tx_hash) do + [paging_options: %{@default_paging_options | key: {block_number, tx_hash}}] + else + _ -> + [paging_options: @default_paging_options] + end + end + # clause for Polygon Edge Deposits and Withdrawals and for account's entities pagination def paging_options(%{"id" => id_string}) when is_binary(id_string) do case Integer.parse(id_string) do @@ -602,6 +629,14 @@ defmodule BlockScoutWeb.Chain do %{"smart_contract_id" => smart_contract.id} end + defp paging_params(%OptimismDeposit{l1_block_number: l1_block_number, l2_transaction_hash: l2_tx_hash}) do + %{"l1_block_number" => l1_block_number, "tx_hash" => l2_tx_hash} + end + + defp paging_params(%OptimismOutputRoot{l2_output_index: index}) do + %{"index" => index} + end + defp paging_params(%SmartContract{} = smart_contract) do %{ "smart_contract_id" => smart_contract.id, @@ -615,6 +650,14 @@ defmodule BlockScoutWeb.Chain do %{"index" => index} end + defp paging_params(%{msg_nonce: nonce}) do + %{"nonce" => nonce} + end + + defp paging_params(%{l2_block_number: block_number}) do + %{"block_number" => block_number} + end + # clause for zkEVM batches pagination defp paging_params(%TransactionBatch{number: number}) do %{"number" => number} diff --git a/apps/block_scout_web/lib/block_scout_web/channels/optimism_deposit_channel.ex b/apps/block_scout_web/lib/block_scout_web/channels/optimism_deposit_channel.ex new file mode 100644 index 0000000000..3f2c513f9b --- /dev/null +++ b/apps/block_scout_web/lib/block_scout_web/channels/optimism_deposit_channel.ex @@ -0,0 +1,22 @@ +defmodule BlockScoutWeb.OptimismDepositChannel do + @moduledoc """ + Establishes pub/sub channel for live updates of Optimism deposit events. + """ + use BlockScoutWeb, :channel + + intercept(["deposits"]) + + def join("optimism_deposits:new_deposits", _params, socket) do + {:ok, %{}, socket} + end + + def handle_out( + "deposits", + %{deposits: deposits}, + %Phoenix.Socket{handler: BlockScoutWeb.UserSocketV2} = socket + ) do + push(socket, "deposits", %{deposits: Enum.count(deposits)}) + + {:noreply, socket} + end +end diff --git a/apps/block_scout_web/lib/block_scout_web/channels/user_socket.ex b/apps/block_scout_web/lib/block_scout_web/channels/user_socket.ex index 6060428a79..e357674a3c 100644 --- a/apps/block_scout_web/lib/block_scout_web/channels/user_socket.ex +++ b/apps/block_scout_web/lib/block_scout_web/channels/user_socket.ex @@ -5,6 +5,7 @@ defmodule BlockScoutWeb.UserSocket do channel("addresses:*", BlockScoutWeb.AddressChannel) channel("blocks:*", BlockScoutWeb.BlockChannel) channel("exchange_rate:*", BlockScoutWeb.ExchangeRateChannel) + channel("optimism_deposits:*", BlockScoutWeb.OptimismDepositChannel) channel("rewards:*", BlockScoutWeb.RewardChannel) channel("transactions:*", BlockScoutWeb.TransactionChannel) channel("tokens:*", BlockScoutWeb.TokenChannel) diff --git a/apps/block_scout_web/lib/block_scout_web/channels/user_socket_v2.ex b/apps/block_scout_web/lib/block_scout_web/channels/user_socket_v2.ex index ec3e5460ec..740b716dc3 100644 --- a/apps/block_scout_web/lib/block_scout_web/channels/user_socket_v2.ex +++ b/apps/block_scout_web/lib/block_scout_web/channels/user_socket_v2.ex @@ -7,6 +7,7 @@ defmodule BlockScoutWeb.UserSocketV2 do channel("addresses:*", BlockScoutWeb.AddressChannel) channel("blocks:*", BlockScoutWeb.BlockChannel) channel("exchange_rate:*", BlockScoutWeb.ExchangeRateChannel) + channel("optimism_deposits:*", BlockScoutWeb.OptimismDepositChannel) channel("rewards:*", BlockScoutWeb.RewardChannel) channel("transactions:*", BlockScoutWeb.TransactionChannel) channel("tokens:*", BlockScoutWeb.TokenChannel) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/main_page_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/main_page_controller.ex index 0e06f6e058..e6fdbe0996 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/main_page_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/main_page_controller.ex @@ -2,8 +2,9 @@ defmodule BlockScoutWeb.API.V2.MainPageController do use Phoenix.Controller alias Explorer.{Chain, PagingOptions} - alias BlockScoutWeb.API.V2.{BlockView, TransactionView} + alias BlockScoutWeb.API.V2.{BlockView, OptimismView, TransactionView} alias Explorer.{Chain, Repo} + alias Explorer.Chain.Optimism.Deposit import BlockScoutWeb.Account.AuthController, only: [current_user: 1] import Explorer.MicroserviceInterfaces.BENS, only: [maybe_preload_ens: 1] @@ -36,6 +37,19 @@ defmodule BlockScoutWeb.API.V2.MainPageController do |> render(:blocks, %{blocks: blocks |> maybe_preload_ens()}) end + def optimism_deposits(conn, _params) do + recent_deposits = + Deposit.list( + paging_options: %PagingOptions{page_size: 6}, + api?: true + ) + + conn + |> put_status(200) + |> put_view(OptimismView) + |> render(:optimism_deposits, %{deposits: recent_deposits}) + end + def transactions(conn, _params) do recent_transactions = Chain.recent_collated_transactions(false, @transactions_options) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/optimism_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/optimism_controller.ex new file mode 100644 index 0000000000..ef3bfe0d68 --- /dev/null +++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/optimism_controller.ex @@ -0,0 +1,111 @@ +defmodule BlockScoutWeb.API.V2.OptimismController do + use BlockScoutWeb, :controller + + import BlockScoutWeb.Chain, + only: [ + next_page_params: 3, + paging_options: 1, + split_list_by_page: 1 + ] + + alias Explorer.Chain + alias Explorer.Chain.Optimism.{Deposit, OutputRoot, TxnBatch, Withdrawal} + + action_fallback(BlockScoutWeb.API.V2.FallbackController) + + def txn_batches(conn, params) do + {batches, next_page} = + params + |> paging_options() + |> Keyword.put(:api?, true) + |> TxnBatch.list() + |> split_list_by_page() + + next_page_params = next_page_params(next_page, batches, params) + + conn + |> put_status(200) + |> render(:optimism_txn_batches, %{ + batches: batches, + next_page_params: next_page_params + }) + end + + def txn_batches_count(conn, _params) do + items_count(conn, TxnBatch) + end + + def output_roots(conn, params) do + {roots, next_page} = + params + |> paging_options() + |> Keyword.put(:api?, true) + |> OutputRoot.list() + |> split_list_by_page() + + next_page_params = next_page_params(next_page, roots, params) + + conn + |> put_status(200) + |> render(:optimism_output_roots, %{ + roots: roots, + next_page_params: next_page_params + }) + end + + def output_roots_count(conn, _params) do + items_count(conn, OutputRoot) + end + + def deposits(conn, params) do + {deposits, next_page} = + params + |> paging_options() + |> Keyword.put(:api?, true) + |> Deposit.list() + |> split_list_by_page() + + next_page_params = next_page_params(next_page, deposits, params) + + conn + |> put_status(200) + |> render(:optimism_deposits, %{ + deposits: deposits, + next_page_params: next_page_params + }) + end + + def deposits_count(conn, _params) do + items_count(conn, Deposit) + end + + def withdrawals(conn, params) do + {withdrawals, next_page} = + params + |> paging_options() + |> Keyword.put(:api?, true) + |> Withdrawal.list() + |> split_list_by_page() + + next_page_params = next_page_params(next_page, withdrawals, params) + + conn + |> put_status(200) + |> render(:optimism_withdrawals, %{ + withdrawals: withdrawals, + next_page_params: next_page_params + }) + end + + def withdrawals_count(conn, _params) do + items_count(conn, Withdrawal) + end + + defp items_count(conn, module) do + count = Chain.get_table_rows_total_count(module, api?: true) + + conn + |> put_status(200) + |> render(:optimism_items_count, %{count: count}) + end +end diff --git a/apps/block_scout_web/lib/block_scout_web/notifier.ex b/apps/block_scout_web/lib/block_scout_web/notifier.ex index b9e5df6ca6..ca7027ae89 100644 --- a/apps/block_scout_web/lib/block_scout_web/notifier.ex +++ b/apps/block_scout_web/lib/block_scout_web/notifier.ex @@ -232,6 +232,10 @@ defmodule BlockScoutWeb.Notifier do Endpoint.broadcast("addresses:#{to_string(address_hash)}", "changed_bytecode", %{}) end + def handle_event({:chain_event, :optimism_deposits, :realtime, deposits}) do + broadcast_optimism_deposits(deposits, "optimism_deposits:new_deposits", "deposits") + end + def handle_event({:chain_event, :smart_contract_was_verified = event, :on_demand, [address_hash]}) do broadcast_automatic_verification_events(event, address_hash) end @@ -400,6 +404,10 @@ defmodule BlockScoutWeb.Notifier do end end + defp broadcast_optimism_deposits(deposits, deposit_channel, event) do + Endpoint.broadcast(deposit_channel, event, %{deposits: deposits}) + end + defp broadcast_transactions_websocket_v2(transactions) do pending_transactions = Enum.filter(transactions, fn diff --git a/apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex b/apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex index 1fedc2dc3d..b08f50e48b 100644 --- a/apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex +++ b/apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex @@ -19,6 +19,7 @@ defmodule BlockScoutWeb.RealtimeEventHandler do Subscriber.to(:block_rewards, :realtime) Subscriber.to(:internal_transactions, :realtime) Subscriber.to(:internal_transactions, :on_demand) + Subscriber.to(:optimism_deposits, :realtime) Subscriber.to(:token_transfers, :realtime) Subscriber.to(:addresses, :on_demand) Subscriber.to(:address_coin_balances, :on_demand) diff --git a/apps/block_scout_web/lib/block_scout_web/templates/block/_tile.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/block/_tile.html.eex index 452c73a3fe..419ac616db 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/block/_tile.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/block/_tile.html.eex @@ -33,7 +33,7 @@ <%= Cldr.Unit.new!(:byte, @block.size) |> cldr_unit_to_string!() %> <% end %> - + <%= if !Application.get_env(:block_scout_web, :hide_block_miner) do %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex index 33b1995cfa..9216229bc4 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex @@ -92,18 +92,20 @@
- <%= case @average_block_time do %> - <% {:error, :disabled} -> %> - <%= nil %> - <% average_block_time -> %> -
- - <%= gettext "Average block time" %> - - - <%= Timex.format_duration(average_block_time, Explorer.Counters.AverageBlockTimeDurationFormat) %> - -
+ <%= unless Application.get_env(:explorer, :chain_type) == "optimism" do %> + <%= case @average_block_time do %> + <% {:error, :disabled} -> %> + <%= nil %> + <% average_block_time -> %> +
+ + <%= gettext "Average block time" %> + + + <%= Timex.format_duration(average_block_time, Explorer.Counters.AverageBlockTimeDurationFormat) %> + +
+ <% end %> <% end %>
@@ -172,7 +174,7 @@ diff --git a/apps/block_scout_web/lib/block_scout_web/templates/internal_transaction/_tile.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/internal_transaction/_tile.html.eex index 27ede917dd..3c23ba78c6 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/internal_transaction/_tile.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/internal_transaction/_tile.html.eex @@ -33,7 +33,7 @@ to: block_path(BlockScoutWeb.Endpoint, :show, @internal_transaction.block_number) ) %> - + <%= if assigns[:current_address] do %> <%= if assigns[:current_address].hash == @internal_transaction.from_address_hash do %> diff --git a/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex index 1f8707d57f..7df4369402 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex @@ -83,7 +83,7 @@ <%= gettext("Tokens") %> -