From a2fb27f7f08dda9693f8f30ca90035a4d37acc24 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Tue, 8 Oct 2024 18:12:10 -0300 Subject: [PATCH 01/24] Initial assertoor test --- .github/workflows/assertoor.yml | 20 ++++++++++++++++++++ .github/workflows/assertoor/test-config.yml | 19 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 .github/workflows/assertoor.yml create mode 100644 .github/workflows/assertoor/test-config.yml diff --git a/.github/workflows/assertoor.yml b/.github/workflows/assertoor.yml new file mode 100644 index 000000000..7bba83cf0 --- /dev/null +++ b/.github/workflows/assertoor.yml @@ -0,0 +1,20 @@ +jobs: + ethereum-testnet: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Build Docker image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + load: true # Important for building without pushing + - uses: actions/checkout@v4 + - name: Setup kurtosis testnet and run assertoor tests + uses: ethpandaops/kurtosis-assertoor-github-action@v1 + with: + ethereum_package_url: 'https://github.com/lambdaclass/ethereum-package.git#lecc-integration' + ethereum_package_args: './assertoor/test-config.yml' + # Additional configurations as needed \ No newline at end of file diff --git a/.github/workflows/assertoor/test-config.yml b/.github/workflows/assertoor/test-config.yml new file mode 100644 index 000000000..a1b809ca0 --- /dev/null +++ b/.github/workflows/assertoor/test-config.yml @@ -0,0 +1,19 @@ +participants: + - el_type: geth + cl_type: teku + - el_type: nethermind + cl_type: prysm + - el_type: erigon + cl_type: nimbus + - el_type: besu + cl_type: lighthouse + - el_type: reth + cl_type: lodestar + - el_type: geth + cl_type: lambda + cl_image: lambda_ethereum_consensus:latest +additional_services: + - assertoor +assertoor_params: + run_stability_check: true + run_block_proposal_check: false \ No newline at end of file From 7382a6cd6e12346b9d0e24d8e0728876c78fc3a5 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Tue, 8 Oct 2024 18:23:02 -0300 Subject: [PATCH 02/24] Added the assertoor task to the CI --- .github/workflows/ci.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a67e74cc..d59d91b40 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -147,6 +147,27 @@ jobs: file: ./Dockerfile load: true # Important for building without pushing + ethereum-testnet: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Build Docker image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + tags: lambda_ethereum_consensus:latest + load: true # Important for building without pushing + - uses: actions/checkout@v4 + - name: Setup kurtosis testnet and run assertoor tests + uses: ethpandaops/kurtosis-assertoor-github-action@v1 + with: + ethereum_package_url: 'https://github.com/lambdaclass/ethereum-package.git#lecc-integration' + ethereum_package_args: './assertoor/test-config.yml' + # Additional configurations as needed + smoke: name: Start and stop the node needs: [compile-native, download-beacon-node-oapi] From 96fe806dc07bfdad9956eee2e9ecfbd83ed02427 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Tue, 8 Oct 2024 18:29:38 -0300 Subject: [PATCH 03/24] added branch to the ethereum package url --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d59d91b40..fb671edfd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -160,11 +160,11 @@ jobs: file: ./Dockerfile tags: lambda_ethereum_consensus:latest load: true # Important for building without pushing - - uses: actions/checkout@v4 - name: Setup kurtosis testnet and run assertoor tests uses: ethpandaops/kurtosis-assertoor-github-action@v1 with: - ethereum_package_url: 'https://github.com/lambdaclass/ethereum-package.git#lecc-integration' + ethereum_package_url: 'https://github.com/lambdaclass/ethereum-package.git' + ethereum_package_branch: 'lecc-integration' ethereum_package_args: './assertoor/test-config.yml' # Additional configurations as needed From dbab9545a868ed775799c042875b90be1fb7d4a9 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Tue, 8 Oct 2024 18:33:00 -0300 Subject: [PATCH 04/24] removed jobs from CI and put them in their own file --- .github/workflows/assertoor.yml | 18 ++++++++++++++++-- .github/workflows/ci.yml | 23 +---------------------- 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/.github/workflows/assertoor.yml b/.github/workflows/assertoor.yml index 7bba83cf0..840d4e172 100644 --- a/.github/workflows/assertoor.yml +++ b/.github/workflows/assertoor.yml @@ -1,3 +1,16 @@ +name: Assertoor tests + +on: + push: + branches: [ main ] + pull_request: + branches: [ '*' ] + paths-ignore: + - 'docs/**' + - '.all-contributorsrc' + - 'README.md' + - 'LICENSE' + - 'metrics/**' jobs: ethereum-testnet: runs-on: ubuntu-latest @@ -10,11 +23,12 @@ jobs: with: context: . file: ./Dockerfile + tags: lambda_ethereum_consensus:latest load: true # Important for building without pushing - - uses: actions/checkout@v4 - name: Setup kurtosis testnet and run assertoor tests uses: ethpandaops/kurtosis-assertoor-github-action@v1 with: - ethereum_package_url: 'https://github.com/lambdaclass/ethereum-package.git#lecc-integration' + ethereum_package_url: 'https://github.com/lambdaclass/ethereum-package.git' + ethereum_package_branch: 'lecc-integration' ethereum_package_args: './assertoor/test-config.yml' # Additional configurations as needed \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fb671edfd..3e40ba36d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -146,28 +146,7 @@ jobs: context: . file: ./Dockerfile load: true # Important for building without pushing - - ethereum-testnet: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Build Docker image - uses: docker/build-push-action@v6 - with: - context: . - file: ./Dockerfile - tags: lambda_ethereum_consensus:latest - load: true # Important for building without pushing - - name: Setup kurtosis testnet and run assertoor tests - uses: ethpandaops/kurtosis-assertoor-github-action@v1 - with: - ethereum_package_url: 'https://github.com/lambdaclass/ethereum-package.git' - ethereum_package_branch: 'lecc-integration' - ethereum_package_args: './assertoor/test-config.yml' - # Additional configurations as needed - + smoke: name: Start and stop the node needs: [compile-native, download-beacon-node-oapi] From 87ced43c5f4ac801bf6a31406e54638ffc591c5b Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Tue, 8 Oct 2024 18:41:43 -0300 Subject: [PATCH 05/24] test without our fork --- .github/workflows/assertoor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/assertoor.yml b/.github/workflows/assertoor.yml index 840d4e172..6b6d4f83b 100644 --- a/.github/workflows/assertoor.yml +++ b/.github/workflows/assertoor.yml @@ -28,7 +28,7 @@ jobs: - name: Setup kurtosis testnet and run assertoor tests uses: ethpandaops/kurtosis-assertoor-github-action@v1 with: - ethereum_package_url: 'https://github.com/lambdaclass/ethereum-package.git' - ethereum_package_branch: 'lecc-integration' + # ethereum_package_url: 'https://github.com/lambdaclass/ethereum-package.git' + # ethereum_package_branch: 'lecc-integration' ethereum_package_args: './assertoor/test-config.yml' # Additional configurations as needed \ No newline at end of file From 32f783e62839992a675f71e39cf6ba67a2f28419 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Tue, 8 Oct 2024 18:59:41 -0300 Subject: [PATCH 06/24] add our eth pkg fork again --- .github/workflows/assertoor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/assertoor.yml b/.github/workflows/assertoor.yml index 6b6d4f83b..48a5c316e 100644 --- a/.github/workflows/assertoor.yml +++ b/.github/workflows/assertoor.yml @@ -28,7 +28,7 @@ jobs: - name: Setup kurtosis testnet and run assertoor tests uses: ethpandaops/kurtosis-assertoor-github-action@v1 with: - # ethereum_package_url: 'https://github.com/lambdaclass/ethereum-package.git' + ethereum_package_url: 'github.com/lambdaclass/ethereum-package' # ethereum_package_branch: 'lecc-integration' ethereum_package_args: './assertoor/test-config.yml' # Additional configurations as needed \ No newline at end of file From b21ca2d9216e945bd8548f4d9565fe22cd0a84b0 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Wed, 9 Oct 2024 10:36:21 -0300 Subject: [PATCH 07/24] check now that branch is correctly picked up --- .github/workflows/assertoor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/assertoor.yml b/.github/workflows/assertoor.yml index 48a5c316e..7c097394b 100644 --- a/.github/workflows/assertoor.yml +++ b/.github/workflows/assertoor.yml @@ -29,6 +29,6 @@ jobs: uses: ethpandaops/kurtosis-assertoor-github-action@v1 with: ethereum_package_url: 'github.com/lambdaclass/ethereum-package' - # ethereum_package_branch: 'lecc-integration' + ethereum_package_branch: 'lecc-integration' ethereum_package_args: './assertoor/test-config.yml' # Additional configurations as needed \ No newline at end of file From cce3bbdf0337991a19f034797cdc099c028582f1 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Wed, 9 Oct 2024 10:37:42 -0300 Subject: [PATCH 08/24] Change file path to config --- .github/workflows/assertoor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/assertoor.yml b/.github/workflows/assertoor.yml index 7c097394b..f2376e20e 100644 --- a/.github/workflows/assertoor.yml +++ b/.github/workflows/assertoor.yml @@ -30,5 +30,5 @@ jobs: with: ethereum_package_url: 'github.com/lambdaclass/ethereum-package' ethereum_package_branch: 'lecc-integration' - ethereum_package_args: './assertoor/test-config.yml' + ethereum_package_args: './.github/assertoor/test-config.yml' # Additional configurations as needed \ No newline at end of file From 54495264b78a83b4390e71ae69ae10caa2bcf547 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Wed, 9 Oct 2024 11:07:30 -0300 Subject: [PATCH 09/24] changing config file to the root of the project --- .github/workflows/assertoor.yml | 2 +- .../workflows/assertoor/test-config.yml => assertoor-config.yml | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/assertoor/test-config.yml => assertoor-config.yml (100%) diff --git a/.github/workflows/assertoor.yml b/.github/workflows/assertoor.yml index f2376e20e..da0c8d572 100644 --- a/.github/workflows/assertoor.yml +++ b/.github/workflows/assertoor.yml @@ -30,5 +30,5 @@ jobs: with: ethereum_package_url: 'github.com/lambdaclass/ethereum-package' ethereum_package_branch: 'lecc-integration' - ethereum_package_args: './.github/assertoor/test-config.yml' + ethereum_package_args: './assertoor-config.yml' # Additional configurations as needed \ No newline at end of file diff --git a/.github/workflows/assertoor/test-config.yml b/assertoor-config.yml similarity index 100% rename from .github/workflows/assertoor/test-config.yml rename to assertoor-config.yml From 89abeb606e166a0e08a085f653f90f7ce51307b6 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Wed, 9 Oct 2024 11:58:41 -0300 Subject: [PATCH 10/24] Change in the ethereum-package branch --- .github/workflows/assertoor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/assertoor.yml b/.github/workflows/assertoor.yml index da0c8d572..06b38c9d6 100644 --- a/.github/workflows/assertoor.yml +++ b/.github/workflows/assertoor.yml @@ -29,6 +29,6 @@ jobs: uses: ethpandaops/kurtosis-assertoor-github-action@v1 with: ethereum_package_url: 'github.com/lambdaclass/ethereum-package' - ethereum_package_branch: 'lecc-integration' + ethereum_package_branch: 'lecc-integration-and-assertoor' ethereum_package_args: './assertoor-config.yml' # Additional configurations as needed \ No newline at end of file From 0be4b292300aed4b2c35c0cc16f11ffbe941dc6d Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Wed, 9 Oct 2024 12:40:57 -0300 Subject: [PATCH 11/24] Testing with the participant config --- assertoor-config.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/assertoor-config.yml b/assertoor-config.yml index a1b809ca0..86f99a2f0 100644 --- a/assertoor-config.yml +++ b/assertoor-config.yml @@ -7,11 +7,16 @@ participants: cl_type: nimbus - el_type: besu cl_type: lighthouse - - el_type: reth - cl_type: lodestar - el_type: geth cl_type: lambda cl_image: lambda_ethereum_consensus:latest + use_separate_vc: false + count: 1 + validator_count: 32 + cl_max_mem: 4096 + keymanager_enabled: true + - el_type: reth + cl_type: lodestar additional_services: - assertoor assertoor_params: From 7414d9be472c2ec2164e9179fa5c9d23cc2df23f Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Wed, 9 Oct 2024 12:44:21 -0300 Subject: [PATCH 12/24] Making the file more near to network_params for testing --- assertoor-config.yml | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/assertoor-config.yml b/assertoor-config.yml index 86f99a2f0..8c89259e8 100644 --- a/assertoor-config.yml +++ b/assertoor-config.yml @@ -1,12 +1,17 @@ +# participants: + # - el_type: geth + # cl_type: teku + # - el_type: nethermind + # cl_type: prysm + # - el_type: erigon + # cl_type: nimbus + # - el_type: besu + # cl_type: lighthouse participants: - el_type: geth - cl_type: teku - - el_type: nethermind - cl_type: prysm - - el_type: erigon - cl_type: nimbus - - el_type: besu cl_type: lighthouse + count: 2 + validator_count: 32 - el_type: geth cl_type: lambda cl_image: lambda_ethereum_consensus:latest @@ -15,8 +20,8 @@ participants: validator_count: 32 cl_max_mem: 4096 keymanager_enabled: true - - el_type: reth - cl_type: lodestar +# network_params: +# preset: minimal additional_services: - assertoor assertoor_params: From df8d22d18baff9dbd53dd4a0c7d93a81c22fee9c Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Wed, 9 Oct 2024 18:40:45 -0300 Subject: [PATCH 13/24] Added syncing and peers endpoint to valdiate assertoor execution --- assertoor-config.yml | 18 ++----- .../controllers/v1/node_controller.ex | 48 +++++++++++++++++-- lib/beacon_api/router.ex | 2 + .../beacon/sync_blocks.ex | 21 ++++++++ network_params.yaml | 15 +++++- 5 files changed, 83 insertions(+), 21 deletions(-) diff --git a/assertoor-config.yml b/assertoor-config.yml index 8c89259e8..cc8a7c127 100644 --- a/assertoor-config.yml +++ b/assertoor-config.yml @@ -1,27 +1,15 @@ -# participants: - # - el_type: geth - # cl_type: teku - # - el_type: nethermind - # cl_type: prysm - # - el_type: erigon - # cl_type: nimbus - # - el_type: besu - # cl_type: lighthouse participants: - - el_type: geth + - el_type: nethermind + cl_type: prysm + - el_type: reth cl_type: lighthouse - count: 2 - validator_count: 32 - el_type: geth cl_type: lambda cl_image: lambda_ethereum_consensus:latest use_separate_vc: false count: 1 - validator_count: 32 cl_max_mem: 4096 keymanager_enabled: true -# network_params: -# preset: minimal additional_services: - assertoor assertoor_params: diff --git a/lib/beacon_api/controllers/v1/node_controller.ex b/lib/beacon_api/controllers/v1/node_controller.ex index 334501d83..a42996c7f 100644 --- a/lib/beacon_api/controllers/v1/node_controller.ex +++ b/lib/beacon_api/controllers/v1/node_controller.ex @@ -3,6 +3,7 @@ defmodule BeaconApi.V1.NodeController do alias BeaconApi.ApiSpec alias BeaconApi.Utils + alias LambdaEthereumConsensus.Beacon.SyncBlocks alias LambdaEthereumConsensus.Libp2pPort alias LambdaEthereumConsensus.P2P.Metadata @@ -19,12 +20,20 @@ defmodule BeaconApi.V1.NodeController do def open_api_operation(:version), do: ApiSpec.spec().paths["/eth/v1/node/version"].get + def open_api_operation(:syncing), + do: ApiSpec.spec().paths["/eth/v1/node/syncing"].get + + def open_api_operation(:peers), + do: ApiSpec.spec().paths["/eth/v1/node/peers"].get + @spec health(Plug.Conn.t(), any) :: Plug.Conn.t() - def health(conn, params) do - # TODO: respond with syncing status if we're still syncing - _syncing_status = Map.get(params, :syncing_status, 206) + def health(conn, _params) do + %{is_syncing: syncing?} = SyncBlocks.status() + syncing_status = if syncing?, do: 206, else: 200 - send_resp(conn, 200, "") + send_resp(conn, syncing_status, "") + rescue + _ -> send_resp(conn, 503, "") end @spec identity(Plug.Conn.t(), any) :: Plug.Conn.t() @@ -62,4 +71,35 @@ defmodule BeaconApi.V1.NodeController do } }) end + + @spec syncing(Plug.Conn.t(), any) :: Plug.Conn.t() + def syncing(conn, _params) do + %{ + is_syncing: is_syncing, + is_optimistic: is_optimistic, + el_offline: el_offline, + head_slot: head_slot, + sync_distance: sync_distance + } = SyncBlocks.status() + + json(conn, %{"data" => %{ + "is_syncing" => is_syncing, + "is_optimistic" => is_optimistic, + "el_offline" => el_offline, + "head_slot" => head_slot |> Integer.to_string(), + "sync_distance" => sync_distance |> Integer.to_string() + }}) + end + + @spec peers(Plug.Conn.t(), any) :: Plug.Conn.t() + def peers(conn, _params) do + # TODO: (#1325) This is a stub. + conn + |> json(%{ + "data" => [%{}], + "meta" => %{ + "count" => 0 + } + }) + end end diff --git a/lib/beacon_api/router.ex b/lib/beacon_api/router.ex index df36dda97..1d50b8421 100644 --- a/lib/beacon_api/router.ex +++ b/lib/beacon_api/router.ex @@ -21,6 +21,8 @@ defmodule BeaconApi.Router do get("/health", NodeController, :health) get("/identity", NodeController, :identity) get("/version", NodeController, :version) + get("/syncing", NodeController, :syncing) + get("/peers", NodeController, :peers) end end diff --git a/lib/lambda_ethereum_consensus/beacon/sync_blocks.ex b/lib/lambda_ethereum_consensus/beacon/sync_blocks.ex index 6050bbb73..76778bcc2 100644 --- a/lib/lambda_ethereum_consensus/beacon/sync_blocks.ex +++ b/lib/lambda_ethereum_consensus/beacon/sync_blocks.ex @@ -8,6 +8,7 @@ defmodule LambdaEthereumConsensus.Beacon.SyncBlocks do alias LambdaEthereumConsensus.ForkChoice alias LambdaEthereumConsensus.Libp2pPort alias LambdaEthereumConsensus.P2P.BlockDownloader + alias LambdaEthereumConsensus.Store.StoreDb @blocks_per_chunk 16 @retries 50 @@ -68,4 +69,24 @@ defmodule LambdaEthereumConsensus.Beacon.SyncBlocks do Libp2pPort.notify_block_download_failed(range, reason) {:ok, store} end + + @doc """ + Returns the current syncing status. + + TODO: (#1325) This is a semi-stub. This is not the final implementation, + just in place for start using assertoor. Probably need to be moved to Libp2pPort. + """ + def status() do + {:ok, %{head_slot: head_slot}} = StoreDb.fetch_store() + initial_slot = head_slot + 1 + last_slot = ForkChoice.get_current_chain_slot() + distance = last_slot - initial_slot + 1 + syncing? = distance > 0 + + %{is_syncing: syncing?, + is_optimistic: syncing?, + el_offline: false, + head_slot: head_slot, + sync_distance: distance} + end end diff --git a/network_params.yaml b/network_params.yaml index 76f0325e1..9527a096f 100644 --- a/network_params.yaml +++ b/network_params.yaml @@ -11,5 +11,16 @@ participants: validator_count: 32 cl_max_mem: 4096 keymanager_enabled: true -network_params: - preset: minimal +# network_params: +# preset: minimal +additional_services: + - assertoor + - tx_spammer + - blob_spammer + - el_forkmon + - dora + - beacon_metrics_gazer + - prometheus_grafana +assertoor_params: + run_stability_check: true + run_block_proposal_check: false From a18768f3251bf2ff80e93d4d1a0aae40c4bd22ae Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Fri, 11 Oct 2024 17:50:29 -0300 Subject: [PATCH 14/24] Push consensus file to take it form the repo --- consensus-test.yaml | 32 ++++++++++++++++++++++++++++++++ network_params.yaml | 4 +++- 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 consensus-test.yaml diff --git a/consensus-test.yaml b/consensus-test.yaml new file mode 100644 index 000000000..9d1f40348 --- /dev/null +++ b/consensus-test.yaml @@ -0,0 +1,32 @@ +id: stability-check +name: "Check chain stability" +timeout: 2h +tasks: +- name: check_clients_are_healthy + title: "Check if all clients are ready" + timeout: 5m + config: + minClientCount: 3 + +- name: run_tasks_concurrent + title: "Check chain stability" + timeout: 1h + config: + tasks: + - name: check_consensus_finality + title: "Check consensus chain finality" + config: + minFinalizedEpochs: 2 + maxUnfinalizedEpochs: 3 + - name: check_consensus_attestation_stats + title: "Check consensus attestation stats" + config: + minTargetPercent: 98 + minHeadPercent: 80 + - name: check_consensus_reorgs + title: "Check consensus reorgs" + config: + maxReorgsPerEpoch: 2 + minCheckEpochCount: 1 + - name: check_consensus_forks + title: "Check consensus forks" \ No newline at end of file diff --git a/network_params.yaml b/network_params.yaml index 9527a096f..741e816e1 100644 --- a/network_params.yaml +++ b/network_params.yaml @@ -22,5 +22,7 @@ additional_services: - beacon_metrics_gazer - prometheus_grafana assertoor_params: - run_stability_check: true + run_stability_check: false run_block_proposal_check: false + tests: + - file: "./consensus-test.yaml" From dd3c1bb150781e6606e0c5b4e04cc838f02a927b Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Tue, 15 Oct 2024 13:08:05 -0300 Subject: [PATCH 15/24] Some fixes and logging --- lib/beacon_api/controllers/error_controller.ex | 4 ++++ lib/beacon_api/controllers/v1/beacon_controller.ex | 2 +- lib/beacon_api/controllers/v1/node_controller.ex | 6 ++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/beacon_api/controllers/error_controller.ex b/lib/beacon_api/controllers/error_controller.ex index 2b9fa950c..d7429659c 100644 --- a/lib/beacon_api/controllers/error_controller.ex +++ b/lib/beacon_api/controllers/error_controller.ex @@ -1,8 +1,10 @@ defmodule BeaconApi.ErrorController do + require Logger use BeaconApi, :controller @spec bad_request(Plug.Conn.t(), binary()) :: Plug.Conn.t() def bad_request(conn, message) do + Logger.error("Bad request: #{message}, path: #{conn.request_path}") conn |> put_status(400) |> json(%{ @@ -13,6 +15,7 @@ defmodule BeaconApi.ErrorController do @spec not_found(Plug.Conn.t(), any) :: Plug.Conn.t() def not_found(conn, _params) do + Logger.error("Not found resource, path: #{conn.request_path}") conn |> put_status(404) |> json(%{ @@ -23,6 +26,7 @@ defmodule BeaconApi.ErrorController do @spec internal_error(Plug.Conn.t(), any) :: Plug.Conn.t() def internal_error(conn, _params) do + Logger.error("Internal server error, path: #{conn.request_path}") conn |> put_status(500) |> json(%{ diff --git a/lib/beacon_api/controllers/v1/beacon_controller.ex b/lib/beacon_api/controllers/v1/beacon_controller.ex index 1f33036bf..950f3ec96 100644 --- a/lib/beacon_api/controllers/v1/beacon_controller.ex +++ b/lib/beacon_api/controllers/v1/beacon_controller.ex @@ -30,7 +30,7 @@ defmodule BeaconApi.V1.BeaconController do conn |> json(%{ "data" => %{ - "genesis_time" => StoreDb.fetch_genesis_time!(), + "genesis_time" => StoreDb.fetch_genesis_time!() |> Integer.to_string(), "genesis_validators_root" => ChainSpec.get_genesis_validators_root() |> Utils.hex_encode(), "genesis_fork_version" => ChainSpec.get("GENESIS_FORK_VERSION") |> Utils.hex_encode() diff --git a/lib/beacon_api/controllers/v1/node_controller.ex b/lib/beacon_api/controllers/v1/node_controller.ex index a42996c7f..f1b4bf295 100644 --- a/lib/beacon_api/controllers/v1/node_controller.ex +++ b/lib/beacon_api/controllers/v1/node_controller.ex @@ -1,6 +1,7 @@ defmodule BeaconApi.V1.NodeController do use BeaconApi, :controller + require Logger alias BeaconApi.ApiSpec alias BeaconApi.Utils alias LambdaEthereumConsensus.Beacon.SyncBlocks @@ -28,6 +29,7 @@ defmodule BeaconApi.V1.NodeController do @spec health(Plug.Conn.t(), any) :: Plug.Conn.t() def health(conn, _params) do + Logger.info("NODE: Health check") %{is_syncing: syncing?} = SyncBlocks.status() syncing_status = if syncing?, do: 206, else: 200 @@ -38,6 +40,7 @@ defmodule BeaconApi.V1.NodeController do @spec identity(Plug.Conn.t(), any) :: Plug.Conn.t() def identity(conn, _params) do + Logger.info("NODE: Identity check") metadata = Metadata.get_metadata() |> Utils.to_json() %{ @@ -61,6 +64,7 @@ defmodule BeaconApi.V1.NodeController do @spec version(Plug.Conn.t(), any) :: Plug.Conn.t() def version(conn, _params) do + Logger.info("NODE: Version check") version = Application.spec(:lambda_ethereum_consensus)[:vsn] arch = :erlang.system_info(:system_architecture) @@ -74,6 +78,7 @@ defmodule BeaconApi.V1.NodeController do @spec syncing(Plug.Conn.t(), any) :: Plug.Conn.t() def syncing(conn, _params) do + Logger.info("NODE: Syncing check") %{ is_syncing: is_syncing, is_optimistic: is_optimistic, @@ -93,6 +98,7 @@ defmodule BeaconApi.V1.NodeController do @spec peers(Plug.Conn.t(), any) :: Plug.Conn.t() def peers(conn, _params) do + Logger.info("NODE: Peers check") # TODO: (#1325) This is a stub. conn |> json(%{ From 0ad9cd5392aabf2121c31a84bfab477fd77debf0 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Wed, 16 Oct 2024 16:36:23 -0300 Subject: [PATCH 16/24] Added an initial implementation of the config/spec --- .../controllers/v1/config_controller.ex | 57 +++++++++++++++++++ lib/beacon_api/router.ex | 4 ++ lib/chain_spec/chain_spec.ex | 2 + 3 files changed, 63 insertions(+) create mode 100644 lib/beacon_api/controllers/v1/config_controller.ex diff --git a/lib/beacon_api/controllers/v1/config_controller.ex b/lib/beacon_api/controllers/v1/config_controller.ex new file mode 100644 index 000000000..5760fd1d0 --- /dev/null +++ b/lib/beacon_api/controllers/v1/config_controller.ex @@ -0,0 +1,57 @@ +defmodule BeaconApi.V1.ConfigController do + use BeaconApi, :controller + require Logger + + alias BeaconApi.ApiSpec + alias BeaconApi.ErrorController + alias BeaconApi.Helpers + alias BeaconApi.Utils + alias LambdaEthereumConsensus.Store.BlockBySlot + alias LambdaEthereumConsensus.Store.Blocks + alias LambdaEthereumConsensus.Store.StoreDb + + plug(OpenApiSpex.Plug.CastAndValidate, json_render_error_v2: true) + + @chain_spec_removed_keys ["ATTESTATION_SUBNET_COUNT", "KZG_COMMITMENT_INCLUSION_PROOF_DEPTH", "UPDATE_TIMEOUT"] + @chain_spec_renamed_keys [{"MAXIMUM_GOSSIP_CLOCK_DISPARITY", "MAXIMUM_GOSSIP_CLOCK_DISPARITY_MILLIS"}] + @chain_spec_hex_fields [ + "TERMINAL_BLOCK_HASH", + "GENESIS_FORK_VERSION", + "ALTAIR_FORK_VERSION", + "BELLATRIX_FORK_VERSION", + "CAPELLA_FORK_VERSION", + "DENEB_FORK_VERSION", + "ELECTRA_FORK_VERSION", + "DEPOSIT_CONTRACT_ADDRESS", + "MESSAGE_DOMAIN_INVALID_SNAPPY", + "MESSAGE_DOMAIN_VALID_SNAPPY", + ] + + # NOTE: this function is required by OpenApiSpex, and should return the information + # of each specific endpoint. We just return the specific entry from the parsed spec. + def open_api_operation(:get_spec), + do: ApiSpec.spec().paths["/eth/v1/config/spec"].get + + @spec get_spec(Plug.Conn.t(), any) :: Plug.Conn.t() + def get_spec(conn, _params), do: json(conn, %{"data" => chain_spec()}) + + defp chain_spec() do + ChainSpec.get_all() + |> Map.drop(@chain_spec_removed_keys) + |> rename_keys(@chain_spec_renamed_keys) + |> Map.new(fn + {k, v} when is_integer(v) -> {k, Integer.to_string(v)} + {k, v} when k in @chain_spec_hex_fields -> {k, Utils.hex_encode(v)} + {k, v} -> {k, v} + end) + end + + defp rename_keys(config, renamed_keys) do + renamed_keys |> Enum.reduce(config, fn {old_key, new_key}, config -> + case Map.get(config, old_key) do + nil -> config + value -> Map.put_new(config, new_key, value) |> Map.delete(old_key) + end + end) + end +end diff --git a/lib/beacon_api/router.ex b/lib/beacon_api/router.ex index 1d50b8421..d65ebdb75 100644 --- a/lib/beacon_api/router.ex +++ b/lib/beacon_api/router.ex @@ -17,6 +17,10 @@ defmodule BeaconApi.Router do get("/states/:state_id/finality_checkpoints", BeaconController, :get_finality_checkpoints) end + scope "config" do + get("/spec", ConfigController, :get_spec) + end + scope "/node" do get("/health", NodeController, :health) get("/identity", NodeController, :identity) diff --git a/lib/chain_spec/chain_spec.ex b/lib/chain_spec/chain_spec.ex index 30fc3682e..9bc89b6cd 100644 --- a/lib/chain_spec/chain_spec.ex +++ b/lib/chain_spec/chain_spec.ex @@ -19,6 +19,8 @@ defmodule ChainSpec do # NOTE: this only works correctly for Capella def get(name), do: get_config().get(name) + def get_all(), do: get_config().get_all() + def get_genesis_validators_root() do Application.fetch_env!(:lambda_ethereum_consensus, __MODULE__) |> Keyword.fetch!(:genesis_validators_root) From 147200ebccc9e10f7d2cd7a05fdd404261c70456 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Wed, 16 Oct 2024 16:44:35 -0300 Subject: [PATCH 17/24] cleanup and removed diffs --- .github/workflows/ci.yml | 2 +- consensus-test.yaml | 32 ------------------- .../controllers/v1/config_controller.ex | 2 ++ .../controllers/v1/node_controller.ex | 18 ----------- 4 files changed, 3 insertions(+), 51 deletions(-) delete mode 100644 consensus-test.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e40ba36d..4a67e74cc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -146,7 +146,7 @@ jobs: context: . file: ./Dockerfile load: true # Important for building without pushing - + smoke: name: Start and stop the node needs: [compile-native, download-beacon-node-oapi] diff --git a/consensus-test.yaml b/consensus-test.yaml deleted file mode 100644 index 9d1f40348..000000000 --- a/consensus-test.yaml +++ /dev/null @@ -1,32 +0,0 @@ -id: stability-check -name: "Check chain stability" -timeout: 2h -tasks: -- name: check_clients_are_healthy - title: "Check if all clients are ready" - timeout: 5m - config: - minClientCount: 3 - -- name: run_tasks_concurrent - title: "Check chain stability" - timeout: 1h - config: - tasks: - - name: check_consensus_finality - title: "Check consensus chain finality" - config: - minFinalizedEpochs: 2 - maxUnfinalizedEpochs: 3 - - name: check_consensus_attestation_stats - title: "Check consensus attestation stats" - config: - minTargetPercent: 98 - minHeadPercent: 80 - - name: check_consensus_reorgs - title: "Check consensus reorgs" - config: - maxReorgsPerEpoch: 2 - minCheckEpochCount: 1 - - name: check_consensus_forks - title: "Check consensus forks" \ No newline at end of file diff --git a/lib/beacon_api/controllers/v1/config_controller.ex b/lib/beacon_api/controllers/v1/config_controller.ex index 5760fd1d0..84167ac1e 100644 --- a/lib/beacon_api/controllers/v1/config_controller.ex +++ b/lib/beacon_api/controllers/v1/config_controller.ex @@ -32,6 +32,8 @@ defmodule BeaconApi.V1.ConfigController do def open_api_operation(:get_spec), do: ApiSpec.spec().paths["/eth/v1/config/spec"].get + # TODO: This is still an incomplete implementation, it should return some constants + # along with the chain spec. It's enough for assertoor. @spec get_spec(Plug.Conn.t(), any) :: Plug.Conn.t() def get_spec(conn, _params), do: json(conn, %{"data" => chain_spec()}) diff --git a/lib/beacon_api/controllers/v1/node_controller.ex b/lib/beacon_api/controllers/v1/node_controller.ex index f1b4bf295..19fb1eab7 100644 --- a/lib/beacon_api/controllers/v1/node_controller.ex +++ b/lib/beacon_api/controllers/v1/node_controller.ex @@ -1,7 +1,6 @@ defmodule BeaconApi.V1.NodeController do use BeaconApi, :controller - require Logger alias BeaconApi.ApiSpec alias BeaconApi.Utils alias LambdaEthereumConsensus.Beacon.SyncBlocks @@ -29,7 +28,6 @@ defmodule BeaconApi.V1.NodeController do @spec health(Plug.Conn.t(), any) :: Plug.Conn.t() def health(conn, _params) do - Logger.info("NODE: Health check") %{is_syncing: syncing?} = SyncBlocks.status() syncing_status = if syncing?, do: 206, else: 200 @@ -40,7 +38,6 @@ defmodule BeaconApi.V1.NodeController do @spec identity(Plug.Conn.t(), any) :: Plug.Conn.t() def identity(conn, _params) do - Logger.info("NODE: Identity check") metadata = Metadata.get_metadata() |> Utils.to_json() %{ @@ -64,7 +61,6 @@ defmodule BeaconApi.V1.NodeController do @spec version(Plug.Conn.t(), any) :: Plug.Conn.t() def version(conn, _params) do - Logger.info("NODE: Version check") version = Application.spec(:lambda_ethereum_consensus)[:vsn] arch = :erlang.system_info(:system_architecture) @@ -78,7 +74,6 @@ defmodule BeaconApi.V1.NodeController do @spec syncing(Plug.Conn.t(), any) :: Plug.Conn.t() def syncing(conn, _params) do - Logger.info("NODE: Syncing check") %{ is_syncing: is_syncing, is_optimistic: is_optimistic, @@ -95,17 +90,4 @@ defmodule BeaconApi.V1.NodeController do "sync_distance" => sync_distance |> Integer.to_string() }}) end - - @spec peers(Plug.Conn.t(), any) :: Plug.Conn.t() - def peers(conn, _params) do - Logger.info("NODE: Peers check") - # TODO: (#1325) This is a stub. - conn - |> json(%{ - "data" => [%{}], - "meta" => %{ - "count" => 0 - } - }) - end end From 13a5bc1abd83ec94f8bc3b2f134840e04c0b98e2 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Wed, 16 Oct 2024 16:53:26 -0300 Subject: [PATCH 18/24] format --- .../controllers/error_controller.ex | 3 +++ .../controllers/v1/config_controller.ex | 20 ++++++++++--------- .../controllers/v1/node_controller.ex | 16 ++++++++------- .../beacon/sync_blocks.ex | 6 ++++-- 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/lib/beacon_api/controllers/error_controller.ex b/lib/beacon_api/controllers/error_controller.ex index d7429659c..3faad5bc1 100644 --- a/lib/beacon_api/controllers/error_controller.ex +++ b/lib/beacon_api/controllers/error_controller.ex @@ -5,6 +5,7 @@ defmodule BeaconApi.ErrorController do @spec bad_request(Plug.Conn.t(), binary()) :: Plug.Conn.t() def bad_request(conn, message) do Logger.error("Bad request: #{message}, path: #{conn.request_path}") + conn |> put_status(400) |> json(%{ @@ -16,6 +17,7 @@ defmodule BeaconApi.ErrorController do @spec not_found(Plug.Conn.t(), any) :: Plug.Conn.t() def not_found(conn, _params) do Logger.error("Not found resource, path: #{conn.request_path}") + conn |> put_status(404) |> json(%{ @@ -27,6 +29,7 @@ defmodule BeaconApi.ErrorController do @spec internal_error(Plug.Conn.t(), any) :: Plug.Conn.t() def internal_error(conn, _params) do Logger.error("Internal server error, path: #{conn.request_path}") + conn |> put_status(500) |> json(%{ diff --git a/lib/beacon_api/controllers/v1/config_controller.ex b/lib/beacon_api/controllers/v1/config_controller.ex index 84167ac1e..727442ea0 100644 --- a/lib/beacon_api/controllers/v1/config_controller.ex +++ b/lib/beacon_api/controllers/v1/config_controller.ex @@ -3,17 +3,18 @@ defmodule BeaconApi.V1.ConfigController do require Logger alias BeaconApi.ApiSpec - alias BeaconApi.ErrorController - alias BeaconApi.Helpers alias BeaconApi.Utils - alias LambdaEthereumConsensus.Store.BlockBySlot - alias LambdaEthereumConsensus.Store.Blocks - alias LambdaEthereumConsensus.Store.StoreDb plug(OpenApiSpex.Plug.CastAndValidate, json_render_error_v2: true) - @chain_spec_removed_keys ["ATTESTATION_SUBNET_COUNT", "KZG_COMMITMENT_INCLUSION_PROOF_DEPTH", "UPDATE_TIMEOUT"] - @chain_spec_renamed_keys [{"MAXIMUM_GOSSIP_CLOCK_DISPARITY", "MAXIMUM_GOSSIP_CLOCK_DISPARITY_MILLIS"}] + @chain_spec_removed_keys [ + "ATTESTATION_SUBNET_COUNT", + "KZG_COMMITMENT_INCLUSION_PROOF_DEPTH", + "UPDATE_TIMEOUT" + ] + @chain_spec_renamed_keys [ + {"MAXIMUM_GOSSIP_CLOCK_DISPARITY", "MAXIMUM_GOSSIP_CLOCK_DISPARITY_MILLIS"} + ] @chain_spec_hex_fields [ "TERMINAL_BLOCK_HASH", "GENESIS_FORK_VERSION", @@ -24,7 +25,7 @@ defmodule BeaconApi.V1.ConfigController do "ELECTRA_FORK_VERSION", "DEPOSIT_CONTRACT_ADDRESS", "MESSAGE_DOMAIN_INVALID_SNAPPY", - "MESSAGE_DOMAIN_VALID_SNAPPY", + "MESSAGE_DOMAIN_VALID_SNAPPY" ] # NOTE: this function is required by OpenApiSpex, and should return the information @@ -49,7 +50,8 @@ defmodule BeaconApi.V1.ConfigController do end defp rename_keys(config, renamed_keys) do - renamed_keys |> Enum.reduce(config, fn {old_key, new_key}, config -> + renamed_keys + |> Enum.reduce(config, fn {old_key, new_key}, config -> case Map.get(config, old_key) do nil -> config value -> Map.put_new(config, new_key, value) |> Map.delete(old_key) diff --git a/lib/beacon_api/controllers/v1/node_controller.ex b/lib/beacon_api/controllers/v1/node_controller.ex index 19fb1eab7..0c0447cfe 100644 --- a/lib/beacon_api/controllers/v1/node_controller.ex +++ b/lib/beacon_api/controllers/v1/node_controller.ex @@ -82,12 +82,14 @@ defmodule BeaconApi.V1.NodeController do sync_distance: sync_distance } = SyncBlocks.status() - json(conn, %{"data" => %{ - "is_syncing" => is_syncing, - "is_optimistic" => is_optimistic, - "el_offline" => el_offline, - "head_slot" => head_slot |> Integer.to_string(), - "sync_distance" => sync_distance |> Integer.to_string() - }}) + json(conn, %{ + "data" => %{ + "is_syncing" => is_syncing, + "is_optimistic" => is_optimistic, + "el_offline" => el_offline, + "head_slot" => head_slot |> Integer.to_string(), + "sync_distance" => sync_distance |> Integer.to_string() + } + }) end end diff --git a/lib/lambda_ethereum_consensus/beacon/sync_blocks.ex b/lib/lambda_ethereum_consensus/beacon/sync_blocks.ex index 76778bcc2..b5273749f 100644 --- a/lib/lambda_ethereum_consensus/beacon/sync_blocks.ex +++ b/lib/lambda_ethereum_consensus/beacon/sync_blocks.ex @@ -83,10 +83,12 @@ defmodule LambdaEthereumConsensus.Beacon.SyncBlocks do distance = last_slot - initial_slot + 1 syncing? = distance > 0 - %{is_syncing: syncing?, + %{ + is_syncing: syncing?, is_optimistic: syncing?, el_offline: false, head_slot: head_slot, - sync_distance: distance} + sync_distance: distance + } end end From 85aa3f6bce30a43baa36d5cd90f21276bfaf7460 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Wed, 16 Oct 2024 17:11:51 -0300 Subject: [PATCH 19/24] Merge branch 'sentry-alert-on-head-not-updated' into initial-assertoor-implementation --- Makefile | 17 ++++++------ README.md | 2 +- lib/lambda_ethereum_consensus/application.ex | 11 ++++++-- lib/libp2p_port.ex | 28 +++++++++++++++++++- 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index c9fd95d65..eb9776069 100644 --- a/Makefile +++ b/Makefile @@ -166,38 +166,39 @@ test-iex: # NODE RUNNERS DISCOVERY_PORT ?= 9009 METRICS_PORT ?= 9568 +MODE ?= full #▶️ mainnet: @ Run an interactive terminal using checkpoint sync for mainnet. mainnet: compile-all - iex -S mix run -- --checkpoint-sync-url https://mainnet-checkpoint-sync.stakely.io/ --metrics --metrics-port $(METRICS_PORT) --discovery-port $(DISCOVERY_PORT) + iex -S mix run -- --checkpoint-sync-url https://mainnet-checkpoint-sync.stakely.io/ --metrics --metrics-port $(METRICS_PORT) --discovery-port $(DISCOVERY_PORT) --mode $(MODE) #▶️ mainnet.logfile: @ Run an interactive terminal using checkpoint sync for mainnet with a log file. mainnet.logfile: compile-all - iex -S mix run -- --checkpoint-sync-url https://mainnet-checkpoint-sync.stakely.io/ --metrics --metrics-port $(METRICS_PORT) --log-file ./logs/mainnet.log --discovery-port $(DISCOVERY_PORT) + iex -S mix run -- --checkpoint-sync-url https://mainnet-checkpoint-sync.stakely.io/ --metrics --metrics-port $(METRICS_PORT) --log-file ./logs/mainnet.log --discovery-port $(DISCOVERY_PORT) --mode $(MODE) #▶️ sepolia: @ Run an interactive terminal using sepolia network sepolia: compile-all - iex -S mix run -- --checkpoint-sync-url https://sepolia.beaconstate.info --network sepolia --metrics --metrics-port $(METRICS_PORT) --discovery-port $(DISCOVERY_PORT) + iex -S mix run -- --checkpoint-sync-url https://sepolia.beaconstate.info --network sepolia --metrics --metrics-port $(METRICS_PORT) --discovery-port $(DISCOVERY_PORT) --mode $(MODE) #▶️ sepolia.logfile: @ Run an interactive terminal using sepolia network with a log file sepolia.logfile: compile-all - iex -S mix run -- --checkpoint-sync-url https://sepolia.beaconstate.info --network sepolia --metrics --metrics-port $(METRICS_PORT) --log-file ./logs/sepolia.log --discovery-port $(DISCOVERY_PORT) + iex -S mix run -- --checkpoint-sync-url https://sepolia.beaconstate.info --network sepolia --metrics --metrics-port $(METRICS_PORT) --log-file ./logs/sepolia.log --discovery-port $(DISCOVERY_PORT) --mode $(MODE) #▶️ holesky: @ Run an interactive terminal using holesky network holesky: compile-all - iex -S mix run -- --checkpoint-sync-url https://checkpoint-sync.holesky.ethpandaops.io --network holesky --metrics --metrics-port $(METRICS_PORT) --discovery-port $(DISCOVERY_PORT) + iex -S mix run -- --checkpoint-sync-url https://checkpoint-sync.holesky.ethpandaops.io --network holesky --metrics --metrics-port $(METRICS_PORT) --discovery-port $(DISCOVERY_PORT) --mode $(MODE) #▶️ holesky.logfile: @ Run an interactive terminal using holesky network with a log file holesky.logfile: compile-all - iex -S mix run -- --checkpoint-sync-url https://checkpoint-sync.holesky.ethpandaops.io --network holesky --log-file ./logs/holesky.log --metrics --metrics-port $(METRICS_PORT) --discovery-port $(DISCOVERY_PORT) + iex -S mix run -- --checkpoint-sync-url https://checkpoint-sync.holesky.ethpandaops.io --network holesky --log-file ./logs/holesky.log --metrics --metrics-port $(METRICS_PORT) --discovery-port $(DISCOVERY_PORT) --mode $(MODE) #▶️ gnosis: @ Run an interactive terminal using gnosis network gnosis: compile-all - iex -S mix run -- --checkpoint-sync-url https://checkpoint.gnosischain.com --network gnosis --metrics --metrics-port $(METRICS_PORT) --discovery-port $(DISCOVERY_PORT) + iex -S mix run -- --checkpoint-sync-url https://checkpoint.gnosischain.com --network gnosis --metrics --metrics-port $(METRICS_PORT) --discovery-port $(DISCOVERY_PORT) --mode $(MODE) #▶️ gnosis.logfile: @ Run an interactive terminal using gnosis network with a log file gnosis.logfile: compile-all - iex -S mix run -- --checkpoint-sync-url https://checkpoint.gnosischain.com --network gnosis --metrics --metrics-port $(METRICS_PORT) --log-file ./logs/gnosis.log --discovery-port $(DISCOVERY_PORT) + iex -S mix run -- --checkpoint-sync-url https://checkpoint.gnosischain.com --network gnosis --metrics --metrics-port $(METRICS_PORT) --log-file ./logs/gnosis.log --discovery-port $(DISCOVERY_PORT) --mode $(MODE) #▶️ checkpoint-sync: @ Run an interactive terminal using checkpoint sync for mainnet. checkpoint-sync: mainnet diff --git a/README.md b/README.md index 8d20cdf25..ce1415037 100644 --- a/README.md +++ b/README.md @@ -449,7 +449,7 @@ In that case, you can use [eFlambè](https://github.com/Stratus3D/eflambe) to ge The following code will capture information from 10 calls to `Handlers.on_block/2`, dumping it in different files named \-eflambe-output.bggg. ```elixir -:eflambe.capture({LambdaEthereumConsensus.ForkChoice.Handlers, :on_block, 2}, 10) +:eflambe.capture({LambdaEthereumConsensus.ForkChoice, :on_block, 2}, 2) ``` The files generated can be processed via common flamegraph tools. diff --git a/lib/lambda_ethereum_consensus/application.ex b/lib/lambda_ethereum_consensus/application.ex index dc89954be..025f87ba8 100644 --- a/lib/lambda_ethereum_consensus/application.ex +++ b/lib/lambda_ethereum_consensus/application.ex @@ -33,7 +33,7 @@ defmodule LambdaEthereumConsensus.Application do :ok end - defp get_children(:db) do + defp get_children(:mixed) do CheckpointStates.new() [ @@ -43,8 +43,15 @@ defmodule LambdaEthereumConsensus.Application do ] end + defp get_children(:db) do + get_children(:mixed) ++ + [ + {Task.Supervisor, name: StoreStatesSupervisor} + ] + end + defp get_children(:full) do - get_children(:db) ++ + get_children(:mixed) ++ [ BeaconApi.Endpoint, KeyStoreApi.Endpoint, diff --git a/lib/libp2p_port.ex b/lib/libp2p_port.ex index 48f5a7758..ef30d1f68 100644 --- a/lib/libp2p_port.ex +++ b/lib/libp2p_port.ex @@ -84,6 +84,7 @@ defmodule LambdaEthereumConsensus.Libp2pPort do @tick_time 1000 @sync_delay_millis 15_000 + @head_drift_alert 12 ###################### ### API @@ -792,9 +793,34 @@ defmodule LambdaEthereumConsensus.Libp2pPort do maybe_log_new_slot(slot_data, new_slot_data) - updated_state |> Map.put(:store, new_store) + updated_state + |> Map.put(:store, new_store) + |> update_syncing_status(new_slot_data, new_store) end + defp update_syncing_status(%{syncing: false} = state, {slot, _third}, %Types.Store{ + head_slot: head_slot + }) + when slot - head_slot >= @head_drift_alert do + Logger.error("[Libp2p] Head slot drifted by #{slot - head_slot} slots.") + + # TODO: (#1194) This is a temporary fix to avoid the drift alert to be triggered and the resync to kick in + # when the node is not fully synced. We should have a better way to handle this. + Process.send_after(self(), :sync_blocks, 500) + + %{state | syncing: true} + end + + defp update_syncing_status( + %{syncing: true, blocks_remaining: 0} = state, + {slot, _third}, + %Types.Store{head_slot: head_slot} + ) + when slot - head_slot == 0, + do: %{state | syncing: false} + + defp update_syncing_status(state, _slot_data, _), do: state + defp schedule_next_tick() do # For millisecond precision time_to_next_tick = @tick_time - rem(:os.system_time(:millisecond), @tick_time) From 192ac92cd68bdee6df530251ec95abc36bd157c5 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Wed, 16 Oct 2024 18:54:49 -0300 Subject: [PATCH 20/24] Moved sync_status to Libp2p and made sync blocks depend on the store --- assertoor-config.yml | 10 ++--- .../controllers/v1/node_controller.ex | 16 ++++---- .../beacon/sync_blocks.ex | 29 ++----------- .../fork_choice/fork_choice.ex | 3 +- lib/libp2p_port.ex | 37 ++++++++++++++++- test/unit/beacon_api/beacon_api_v1_test.exs | 41 +++++++++++++++++-- 6 files changed, 89 insertions(+), 47 deletions(-) diff --git a/assertoor-config.yml b/assertoor-config.yml index cc8a7c127..2ec211d8e 100644 --- a/assertoor-config.yml +++ b/assertoor-config.yml @@ -10,8 +10,8 @@ participants: count: 1 cl_max_mem: 4096 keymanager_enabled: true -additional_services: - - assertoor -assertoor_params: - run_stability_check: true - run_block_proposal_check: false \ No newline at end of file +# additional_services: +# - assertoor +# assertoor_params: +# run_stability_check: true +# run_block_proposal_check: false \ No newline at end of file diff --git a/lib/beacon_api/controllers/v1/node_controller.ex b/lib/beacon_api/controllers/v1/node_controller.ex index 0c0447cfe..5a7ad4768 100644 --- a/lib/beacon_api/controllers/v1/node_controller.ex +++ b/lib/beacon_api/controllers/v1/node_controller.ex @@ -3,7 +3,6 @@ defmodule BeaconApi.V1.NodeController do alias BeaconApi.ApiSpec alias BeaconApi.Utils - alias LambdaEthereumConsensus.Beacon.SyncBlocks alias LambdaEthereumConsensus.Libp2pPort alias LambdaEthereumConsensus.P2P.Metadata @@ -27,9 +26,10 @@ defmodule BeaconApi.V1.NodeController do do: ApiSpec.spec().paths["/eth/v1/node/peers"].get @spec health(Plug.Conn.t(), any) :: Plug.Conn.t() - def health(conn, _params) do - %{is_syncing: syncing?} = SyncBlocks.status() - syncing_status = if syncing?, do: 206, else: 200 + def health(conn, params) do + %{syncing?: syncing?} = Libp2pPort.sync_status() + + syncing_status = if syncing?, do: Map.get(params, :syncing_status, 206), else: 200 send_resp(conn, syncing_status, "") rescue @@ -75,12 +75,12 @@ defmodule BeaconApi.V1.NodeController do @spec syncing(Plug.Conn.t(), any) :: Plug.Conn.t() def syncing(conn, _params) do %{ - is_syncing: is_syncing, - is_optimistic: is_optimistic, - el_offline: el_offline, + syncing?: is_syncing, + optimistic?: is_optimistic, + el_offline?: el_offline, head_slot: head_slot, sync_distance: sync_distance - } = SyncBlocks.status() + } = Libp2pPort.sync_status() json(conn, %{ "data" => %{ diff --git a/lib/lambda_ethereum_consensus/beacon/sync_blocks.ex b/lib/lambda_ethereum_consensus/beacon/sync_blocks.ex index b5273749f..67daec7d6 100644 --- a/lib/lambda_ethereum_consensus/beacon/sync_blocks.ex +++ b/lib/lambda_ethereum_consensus/beacon/sync_blocks.ex @@ -21,11 +21,10 @@ defmodule LambdaEthereumConsensus.Beacon.SyncBlocks do finish, each block of those responses will be sent to libp2p port module individually using Libp2pPort.add_block/1. """ - @spec run() :: non_neg_integer() - def run() do - %{head_slot: head_slot} = ForkChoice.get_current_status_message() + @spec run(Types.Store.t()) :: non_neg_integer() + def run(%{head_slot: head_slot} = store) do initial_slot = head_slot + 1 - last_slot = ForkChoice.get_current_chain_slot() + last_slot = ForkChoice.get_current_slot(store) # If we're around genesis, we consider ourselves synced if last_slot <= 0 do @@ -69,26 +68,4 @@ defmodule LambdaEthereumConsensus.Beacon.SyncBlocks do Libp2pPort.notify_block_download_failed(range, reason) {:ok, store} end - - @doc """ - Returns the current syncing status. - - TODO: (#1325) This is a semi-stub. This is not the final implementation, - just in place for start using assertoor. Probably need to be moved to Libp2pPort. - """ - def status() do - {:ok, %{head_slot: head_slot}} = StoreDb.fetch_store() - initial_slot = head_slot + 1 - last_slot = ForkChoice.get_current_chain_slot() - distance = last_slot - initial_slot + 1 - syncing? = distance > 0 - - %{ - is_syncing: syncing?, - is_optimistic: syncing?, - el_offline: false, - head_slot: head_slot, - sync_distance: distance - } - end end diff --git a/lib/lambda_ethereum_consensus/fork_choice/fork_choice.ex b/lib/lambda_ethereum_consensus/fork_choice/fork_choice.ex index 02384db26..8ba5b7fc6 100644 --- a/lib/lambda_ethereum_consensus/fork_choice/fork_choice.ex +++ b/lib/lambda_ethereum_consensus/fork_choice/fork_choice.ex @@ -123,8 +123,7 @@ defmodule LambdaEthereumConsensus.ForkChoice do @doc """ Get the current chain slot based on the system time. - There are just 2 uses of this function outside this module: - - At the begining of SyncBlocks.run/1 function, to get the head slot + There are just 1 use of this function outside this module: - In the Helpers.block_root_by_block_id/1 function """ @spec get_current_chain_slot() :: Types.slot() diff --git a/lib/libp2p_port.ex b/lib/libp2p_port.ex index ef30d1f68..7ba558edc 100644 --- a/lib/libp2p_port.ex +++ b/lib/libp2p_port.ex @@ -384,6 +384,20 @@ defmodule LambdaEthereumConsensus.Libp2pPort do GenServer.cast(pid, {:error_downloading_chunk, range, reason}) end + @doc """ + Returns the current sync status. + """ + @spec sync_status(pid | atom()) :: %{ + syncing?: boolean(), + optimistic?: boolean(), + el_offline?: boolean(), + head_slot: Types.slot(), + sync_distance: non_neg_integer() + } + def sync_status(pid \\ __MODULE__) do + GenServer.call(pid, :sync_status) + end + ######################## ### GenServer Callbacks ######################## @@ -513,8 +527,8 @@ defmodule LambdaEthereumConsensus.Libp2pPort do end @impl GenServer - def handle_info(:sync_blocks, state) do - blocks_to_download = SyncBlocks.run() + def handle_info(:sync_blocks, %{store: store} = state) do + blocks_to_download = SyncBlocks.run(store) new_state = state |> Map.put(:blocks_remaining, blocks_to_download) |> subscribe_if_no_blocks() @@ -575,6 +589,25 @@ defmodule LambdaEthereumConsensus.Libp2pPort do {:reply, :ok, %{state | validator_set: validator_set}} end + @impl GenServer + def handle_call(:sync_status, _from, %{syncing: syncing?, store: store} = state) do + # TODO: (#1325) This is not the final implementation, we are lacking the el check, + # this is just in place for start using assertoor. + head_slot = store.head_slot + current_slot = ForkChoice.get_current_slot(store) + distance = current_slot - head_slot + + result = %{ + syncing?: syncing?, + optimistic?: syncing?, + el_offline?: false, + head_slot: store.head_slot, + sync_distance: distance + } + + {:reply, result, state} + end + ###################### ### PRIVATE FUNCTIONS ###################### diff --git a/test/unit/beacon_api/beacon_api_v1_test.exs b/test/unit/beacon_api/beacon_api_v1_test.exs index 3a9fbfe50..6453bef78 100644 --- a/test/unit/beacon_api/beacon_api_v1_test.exs +++ b/test/unit/beacon_api/beacon_api_v1_test.exs @@ -6,6 +6,8 @@ defmodule Unit.BeaconApiTest.V1 do alias BeaconApi.Router alias BeaconApi.Utils alias LambdaEthereumConsensus.ForkChoice + alias LambdaEthereumConsensus.Libp2pPort + alias LambdaEthereumConsensus.P2P.Metadata alias LambdaEthereumConsensus.Store.BlockDb alias LambdaEthereumConsensus.Store.Db alias LambdaEthereumConsensus.Store.StoreDb @@ -134,7 +136,7 @@ defmodule Unit.BeaconApiTest.V1 do test "get genesis data" do expected_response = %{ "data" => %{ - "genesis_time" => StoreDb.fetch_genesis_time!(), + "genesis_time" => StoreDb.fetch_genesis_time!() |> Integer.to_string(), "genesis_validators_root" => ChainSpec.get_genesis_validators_root() |> Utils.hex_encode(), "genesis_fork_version" => ChainSpec.get("GENESIS_FORK_VERSION") |> Utils.hex_encode() @@ -149,15 +151,46 @@ defmodule Unit.BeaconApiTest.V1 do end test "node health" do + now = :os.system_time(:second) + patch(Libp2pPort, :on_tick, fn _time, state -> state end) + + start_link_supervised!( + {Libp2pPort, + genesis_time: now - 24, store: %Store{genesis_time: now - 24, time: now, head_slot: 1}} + ) + conn = conn(:get, "/eth/v1/node/health", nil) |> Router.call(@opts) assert conn.state == :sent - assert conn.status == 200 + assert conn.status == 206 assert conn.resp_body == "" end + test "node syncing" do + now = :os.system_time(:second) + patch(Libp2pPort, :on_tick, fn _time, state -> state end) + + start_link_supervised!( + {Libp2pPort, + genesis_time: now - 24, store: %Store{genesis_time: now - 24, time: now, head_slot: 1}} + ) + + expected_response = %{ + "data" => %{ + "is_syncing" => true, + "is_optimistic" => true, + "el_offline" => false, + "head_slot" => "1", + "sync_distance" => "1" + } + } + + conn = conn(:get, "/eth/v1/node/syncing", nil) |> Router.call(@opts) + assert conn.state == :sent + assert conn.status == 200 + assert Jason.decode!(conn.resp_body) == expected_response + end + test "node identity" do - alias LambdaEthereumConsensus.Libp2pPort - alias LambdaEthereumConsensus.P2P.Metadata patch(ForkChoice, :get_fork_version, fn -> ChainSpec.get("DENEB_FORK_VERSION") end) start_link_supervised!({Libp2pPort, genesis_time: :os.system_time(:second), store: %Store{}}) From f45a91bec11f0a83597dce8f7fe2ce5ad5212443 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Fri, 18 Oct 2024 13:25:48 -0300 Subject: [PATCH 21/24] Added some additional info to libp2p status and removed unneded alias --- lib/lambda_ethereum_consensus/beacon/sync_blocks.ex | 1 - lib/libp2p_port.ex | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/lambda_ethereum_consensus/beacon/sync_blocks.ex b/lib/lambda_ethereum_consensus/beacon/sync_blocks.ex index 67daec7d6..cc009cf17 100644 --- a/lib/lambda_ethereum_consensus/beacon/sync_blocks.ex +++ b/lib/lambda_ethereum_consensus/beacon/sync_blocks.ex @@ -8,7 +8,6 @@ defmodule LambdaEthereumConsensus.Beacon.SyncBlocks do alias LambdaEthereumConsensus.ForkChoice alias LambdaEthereumConsensus.Libp2pPort alias LambdaEthereumConsensus.P2P.BlockDownloader - alias LambdaEthereumConsensus.Store.StoreDb @blocks_per_chunk 16 @retries 50 diff --git a/lib/libp2p_port.ex b/lib/libp2p_port.ex index 7ba558edc..71486e348 100644 --- a/lib/libp2p_port.ex +++ b/lib/libp2p_port.ex @@ -392,7 +392,8 @@ defmodule LambdaEthereumConsensus.Libp2pPort do optimistic?: boolean(), el_offline?: boolean(), head_slot: Types.slot(), - sync_distance: non_neg_integer() + sync_distance: non_neg_integer(), + blocks_remaining: non_neg_integer() } def sync_status(pid \\ __MODULE__) do GenServer.call(pid, :sync_status) @@ -602,7 +603,8 @@ defmodule LambdaEthereumConsensus.Libp2pPort do optimistic?: syncing?, el_offline?: false, head_slot: store.head_slot, - sync_distance: distance + sync_distance: distance, + blocks_remaining: state.blocks_remaining } {:reply, result, state} From 292aed8269cdc93b14dd4932fd559d728cb21980 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Fri, 18 Oct 2024 13:34:04 -0300 Subject: [PATCH 22/24] initial headers/head implementation --- .../controllers/v1/beacon_controller.ex | 34 +++++++++++++++++++ lib/beacon_api/router.ex | 19 ++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/lib/beacon_api/controllers/v1/beacon_controller.ex b/lib/beacon_api/controllers/v1/beacon_controller.ex index 950f3ec96..d25b60724 100644 --- a/lib/beacon_api/controllers/v1/beacon_controller.ex +++ b/lib/beacon_api/controllers/v1/beacon_controller.ex @@ -1,6 +1,7 @@ defmodule BeaconApi.V1.BeaconController do use BeaconApi, :controller + require Logger alias BeaconApi.ApiSpec alias BeaconApi.ErrorController alias BeaconApi.Helpers @@ -25,6 +26,9 @@ defmodule BeaconApi.V1.BeaconController do def open_api_operation(:get_finality_checkpoints), do: ApiSpec.spec().paths["/eth/v1/beacon/states/{state_id}/finality_checkpoints"].get + def open_api_operation(:get_headers_by_block), + do: ApiSpec.spec().paths["/eth/v1/beacon/headers/{block_id}"].get + @spec get_genesis(Plug.Conn.t(), any) :: Plug.Conn.t() def get_genesis(conn, _params) do conn @@ -182,4 +186,34 @@ defmodule BeaconApi.V1.BeaconController do } }) end + + @spec get_headers_by_block(Plug.Conn.t(), any) :: Plug.Conn.t() + def get_headers_by_block(conn, %{block_id: "head"}) do + Logger.info("[BEACONCONTROLLER] Fetching head block") + {:ok, store} = StoreDb.fetch_store() + head_root = store.head_root + %{signed_block: %{message: message, signature: signature}} = Blocks.get_block_info(head_root) + + conn + |> json(%{ + execution_optimistic: false, # This is a placeholder + finalized: false, # This is obviously false for the head, but should be derived + data: %{ + root: head_root |> Utils.hex_encode(), + canonical: true, # This needs to be derived + header: %{ + message: %{ + slot: message.slot |> Integer.to_string(), + proposer_index: message.proposer_index |> Integer.to_string(), + parent_root: message.parent_root |> Utils.hex_encode(), + state_root: message.state_root |> Utils.hex_encode(), + body_root: SszEx.hash_tree_root!(message.body) |> Utils.hex_encode() + }, + signature: signature |> Utils.hex_encode() + } + } + }) + end + + def get_headers_by_block(conn, _params), do: conn |> ErrorController.not_found(nil) end diff --git a/lib/beacon_api/router.ex b/lib/beacon_api/router.ex index d65ebdb75..6c37c1684 100644 --- a/lib/beacon_api/router.ex +++ b/lib/beacon_api/router.ex @@ -1,9 +1,11 @@ defmodule BeaconApi.Router do use BeaconApi, :router + require Logger pipeline :api do plug(:accepts, ["json"]) plug(OpenApiSpex.Plug.PutApiSpec, module: BeaconApi.ApiSpec) + plug :log_requests, enabled: true end # Ethereum API Version 1 @@ -15,9 +17,10 @@ defmodule BeaconApi.Router do get("/states/:state_id/root", BeaconController, :get_state_root) get("/blocks/:block_id/root", BeaconController, :get_block_root) get("/states/:state_id/finality_checkpoints", BeaconController, :get_finality_checkpoints) + get("/headers/:block_id", BeaconController, :get_headers_by_block) end - scope "config" do + scope "/config" do get("/spec", ConfigController, :get_spec) end @@ -46,4 +49,18 @@ defmodule BeaconApi.Router do # Catch-all route outside of any scope match(:*, "/*path", BeaconApi.ErrorController, :not_found) + + defp log_requests(conn, [enabled: false]), do: conn + + defp log_requests(conn, _opts) do + base_message = "[BeaconAPI Router] Processing request: #{conn.method} - #{conn.request_path}" + query = if conn.query_params != %{}, do: "Query: #{inspect(conn.query_params)}", else: "" + body = if conn.body_params != %{}, do: "Body: #{inspect(conn.body_params)}", else: "" + + [base_message, query, body] + |> Enum.join("\n\t") + |> Logger.info() + + conn + end end From e7937cc9d0439ae8fd603538570ef04686b1264e Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Fri, 18 Oct 2024 18:47:46 -0300 Subject: [PATCH 23/24] Small change to the log_requests plug and removal of old loggers --- lib/beacon_api/controllers/v1/beacon_controller.ex | 2 -- lib/beacon_api/router.ex | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/beacon_api/controllers/v1/beacon_controller.ex b/lib/beacon_api/controllers/v1/beacon_controller.ex index d25b60724..18ac61369 100644 --- a/lib/beacon_api/controllers/v1/beacon_controller.ex +++ b/lib/beacon_api/controllers/v1/beacon_controller.ex @@ -1,7 +1,6 @@ defmodule BeaconApi.V1.BeaconController do use BeaconApi, :controller - require Logger alias BeaconApi.ApiSpec alias BeaconApi.ErrorController alias BeaconApi.Helpers @@ -189,7 +188,6 @@ defmodule BeaconApi.V1.BeaconController do @spec get_headers_by_block(Plug.Conn.t(), any) :: Plug.Conn.t() def get_headers_by_block(conn, %{block_id: "head"}) do - Logger.info("[BEACONCONTROLLER] Fetching head block") {:ok, store} = StoreDb.fetch_store() head_root = store.head_root %{signed_block: %{message: message, signature: signature}} = Blocks.get_block_info(head_root) diff --git a/lib/beacon_api/router.ex b/lib/beacon_api/router.ex index 6c37c1684..abb749b08 100644 --- a/lib/beacon_api/router.ex +++ b/lib/beacon_api/router.ex @@ -5,7 +5,7 @@ defmodule BeaconApi.Router do pipeline :api do plug(:accepts, ["json"]) plug(OpenApiSpex.Plug.PutApiSpec, module: BeaconApi.ApiSpec) - plug :log_requests, enabled: true + plug :log_requests end # Ethereum API Version 1 @@ -50,8 +50,6 @@ defmodule BeaconApi.Router do # Catch-all route outside of any scope match(:*, "/*path", BeaconApi.ErrorController, :not_found) - defp log_requests(conn, [enabled: false]), do: conn - defp log_requests(conn, _opts) do base_message = "[BeaconAPI Router] Processing request: #{conn.method} - #{conn.request_path}" query = if conn.query_params != %{}, do: "Query: #{inspect(conn.query_params)}", else: "" From 691941014c9f2333bb9fec1d446c25fbbb140c75 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Fri, 18 Oct 2024 20:29:41 -0300 Subject: [PATCH 24/24] fixed /states/{state_id}/finality_checkpoints for genesis executions --- lib/beacon_api/helpers.ex | 10 +++++++--- lib/libp2p_port.ex | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/beacon_api/helpers.ex b/lib/beacon_api/helpers.ex index fc5511bc5..8db8b2822 100644 --- a/lib/beacon_api/helpers.ex +++ b/lib/beacon_api/helpers.ex @@ -154,10 +154,14 @@ defmodule BeaconApi.Helpers do @spec finality_checkpoint_by_id(state_id()) :: {:ok, finality_info()} | {:error, String.t()} | :not_found | :empty_slot | :invalid_id def finality_checkpoint_by_id(id) do + empty_checkpoint = %Types.Checkpoint{epoch: 0, root: <<0::256>>} + with {:ok, {state, optimistic, finalized}} <- state_by_state_id(id) do - {:ok, - {state.previous_justified_checkpoint, state.current_justified_checkpoint, - state.finalized_checkpoint, optimistic, finalized}} + previous_justified_ck = Map.get(state, :previous_justified_checkpoint, empty_checkpoint) + current_justified_ck = Map.get(state, :current_justified_checkpoint, empty_checkpoint) + finalized_ck = Map.get(state, :finalized_checkpoint, empty_checkpoint) + + {:ok, {previous_justified_ck, current_justified_ck, finalized_ck, optimistic, finalized}} end end diff --git a/lib/libp2p_port.ex b/lib/libp2p_port.ex index 71486e348..4efddccee 100644 --- a/lib/libp2p_port.ex +++ b/lib/libp2p_port.ex @@ -591,7 +591,7 @@ defmodule LambdaEthereumConsensus.Libp2pPort do end @impl GenServer - def handle_call(:sync_status, _from, %{syncing: syncing?, store: store} = state) do + def handle_call(:sync_status, _from, %{syncing: syncing?, store: %Types.Store{} = store} = state) do # TODO: (#1325) This is not the final implementation, we are lacking the el check, # this is just in place for start using assertoor. head_slot = store.head_slot @@ -604,7 +604,7 @@ defmodule LambdaEthereumConsensus.Libp2pPort do el_offline?: false, head_slot: store.head_slot, sync_distance: distance, - blocks_remaining: state.blocks_remaining + blocks_remaining: Map.get(state, :blocks_remaining) } {:reply, result, state}