From d9df7ea81c710e488468ebae6be6a16dce9a3486 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 17:04:48 -0300 Subject: [PATCH 1/3] chore(deps-dev): bump stream_data from 1.1.1 to 1.1.2 (#1319) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- mix.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.lock b/mix.lock index 4bcfc664c..85d2a80eb 100644 --- a/mix.lock +++ b/mix.lock @@ -70,7 +70,7 @@ "sourceror": {:hex, :sourceror, "1.5.0", "3e65d5fbb1a8e2864ad6411262c8018fee73474f5789dda12285c82999253d5d", [:mix], [], "hexpm", "4a32b5d189d8453f73278c15712f8731b89e9211e50726b798214b303b51bfc7"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, "statistex": {:hex, :statistex, "1.0.0", "f3dc93f3c0c6c92e5f291704cf62b99b553253d7969e9a5fa713e5481cd858a5", [:mix], [], "hexpm", "ff9d8bee7035028ab4742ff52fc80a2aa35cece833cf5319009b52f1b5a86c27"}, - "stream_data": {:hex, :stream_data, "1.1.1", "fd515ca95619cca83ba08b20f5e814aaf1e5ebff114659dc9731f966c9226246", [:mix], [], "hexpm", "45d0cd46bd06738463fd53f22b70042dbb58c384bb99ef4e7576e7bb7d3b8c8c"}, + "stream_data": {:hex, :stream_data, "1.1.2", "05499eaec0443349ff877aaabc6e194e82bda6799b9ce6aaa1aadac15a9fdb4d", [:mix], [], "hexpm", "129558d2c77cbc1eb2f4747acbbea79e181a5da51108457000020a906813a1a9"}, "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, "telemetry_metrics": {:hex, :telemetry_metrics, "1.0.0", "29f5f84991ca98b8eb02fc208b2e6de7c95f8bb2294ef244a176675adc7775df", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f23713b3847286a534e005126d4c959ebcca68ae9582118ce436b521d1d47d5d"}, "telemetry_metrics_prometheus_core": {:hex, :telemetry_metrics_prometheus_core, "1.2.1", "c9755987d7b959b557084e6990990cb96a50d6482c683fb9622a63837f3cd3d8", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "5e2c599da4983c4f88a33e9571f1458bf98b0cf6ba930f1dc3a6e8cf45d5afb6"}, From b550fee4abf90e10bc028dddac981b963fdcd3f8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 20:13:38 +0000 Subject: [PATCH 2/3] chore(deps): bump open_api_spex from 3.21.1 to 3.21.2 (#1320) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Rodrigo Oliveri --- mix.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.lock b/mix.lock index 85d2a80eb..ca31db9e5 100644 --- a/mix.lock +++ b/mix.lock @@ -43,7 +43,7 @@ "nimble_ownership": {:hex, :nimble_ownership, "1.0.0", "3f87744d42c21b2042a0aa1d48c83c77e6dd9dd357e425a038dd4b49ba8b79a1", [:mix], [], "hexpm", "7c16cc74f4e952464220a73055b557a273e8b1b7ace8489ec9d86e9ad56cb2cc"}, "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, "octo_fetch": {:hex, :octo_fetch, "0.4.0", "074b5ecbc08be10b05b27e9db08bc20a3060142769436242702931c418695b19", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "cf8be6f40cd519d7000bb4e84adcf661c32e59369ca2827c4e20042eda7a7fc6"}, - "open_api_spex": {:hex, :open_api_spex, "3.21.1", "56957b8b6dbd7ba66824d1f89f63cb269d69dbaf6bc4fe3b39ea17b651146780", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 3.0 or ~> 4.0 or ~> 5.0 or ~> 6.0", [hex: :poison, repo: "hexpm", optional: true]}, {:ymlr, "~> 2.0 or ~> 3.0 or ~> 4.0 or ~> 5.0", [hex: :ymlr, repo: "hexpm", optional: true]}], "hexpm", "eab3e703270fe8fce127274d4d1c67c15fcb440421117b44ceed0a19c3b97386"}, + "open_api_spex": {:hex, :open_api_spex, "3.21.2", "6a704f3777761feeb5657340250d6d7332c545755116ca98f33d4b875777e1e5", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 3.0 or ~> 4.0 or ~> 5.0 or ~> 6.0", [hex: :poison, repo: "hexpm", optional: true]}, {:ymlr, "~> 2.0 or ~> 3.0 or ~> 4.0 or ~> 5.0", [hex: :ymlr, repo: "hexpm", optional: true]}], "hexpm", "f42ae6ed668b895ebba3e02773cfb4b41050df26f803f2ef634c72a7687dc387"}, "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "patch": {:hex, :patch, "0.13.1", "2da5b508e4d6558924a0959d95dc3aa8176b5ccf2539e4567481448d61853ccc", [:mix], [], "hexpm", "75f805827d9db0c335155fbb857e6eeb5c85034c9dc668d146bc0bfe48fac822"}, "peep": {:hex, :peep, "3.2.0", "569d7b1f1a8c8f3e72327b42c0b9d4284db9d4ca53514bcf9c8358ee70f45ff8", [:mix], [{:nimble_options, "~> 1.1", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:plug, "~> 1.16", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry_metrics, "~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "267ffde5b7261b132f4e6a0b602d789be176fe8160fad788af9ca0de2c9a9180"}, From 378b2fd5f7a2a40ab0f5d48e8bd561f9dc57ab60 Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveri Date: Mon, 7 Oct 2024 17:19:10 -0300 Subject: [PATCH 3/3] fix: block sync hangs on initial node start (#1314) --- Makefile | 28 ++++++++-- .../fork_choice/fork_choice.ex | 2 +- .../p2p/blob_downloader.ex | 7 +-- .../p2p/block_downloader.ex | 8 +-- lib/lambda_ethereum_consensus/p2p/peerbook.ex | 56 +++++++++++++++---- lib/libp2p_port.ex | 5 +- 6 files changed, 79 insertions(+), 27 deletions(-) diff --git a/Makefile b/Makefile index 617e55619..5e073d07f 100644 --- a/Makefile +++ b/Makefile @@ -162,9 +162,17 @@ iex: compile-all test-iex: MIX_ENV=test iex -S mix run -- --mode db +################## +# NODE RUNNERS +DYSCOVERY_PORT ?= 30303 + #▶️ checkpoint-sync: @ Run an interactive terminal using checkpoint sync. checkpoint-sync: compile-all - iex -S mix run -- --checkpoint-sync-url https://mainnet-checkpoint-sync.stakely.io/ --metrics + iex -S mix run -- --checkpoint-sync-url https://mainnet-checkpoint-sync.stakely.io/ --metrics --discovery-port $(DYSCOVERY_PORT) + +#▶️ checkpoint-sync.logfile: @ Run an interactive terminal using checkpoint sync with a log file. +checkpoint-sync.logfile: compile-all + iex -S mix run -- --checkpoint-sync-url https://mainnet-checkpoint-sync.stakely.io/ --metrics --log-file ./logs/mainnet.log #▶️ checkpoint-sync.logfile: @ Run an interactive terminal using checkpoint sync with a log file. checkpoint-sync.logfile: compile-all @@ -172,7 +180,11 @@ checkpoint-sync.logfile: compile-all #▶️ 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 + iex -S mix run -- --checkpoint-sync-url https://sepolia.beaconstate.info --network sepolia --metrics --discovery-port $(DYSCOVERY_PORT) + +#▶️ 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 --log-file ./logs/sepolia.log #▶️ sepolia.logfile: @ Run an interactive terminal using sepolia network with a log file sepolia.logfile: compile-all @@ -180,7 +192,11 @@ sepolia.logfile: compile-all #▶️ 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 + iex -S mix run -- --checkpoint-sync-url https://checkpoint-sync.holesky.ethpandaops.io --network holesky --discovery-port $(DYSCOVERY_PORT) + +#▶️ 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 #▶️ holesky.logfile: @ Run an interactive terminal using holesky network with a log file holesky.logfile: compile-all @@ -188,7 +204,11 @@ holesky.logfile: compile-all #▶️ gnosis: @ Run an interactive terminal using gnosis network gnosis: compile-all - iex -S mix run -- --checkpoint-sync-url https://checkpoint.gnosischain.com --network gnosis + iex -S mix run -- --checkpoint-sync-url https://checkpoint.gnosischain.com --network gnosis --discovery-port $(DYSCOVERY_PORT) + +#▶️ 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 --log-file ./logs/gnosis.log --discovery-port $(DYSCOVERY_PORT) #🔴 test: @ Run tests test: compile-all diff --git a/lib/lambda_ethereum_consensus/fork_choice/fork_choice.ex b/lib/lambda_ethereum_consensus/fork_choice/fork_choice.ex index 9caa8ef77..44b046ebd 100644 --- a/lib/lambda_ethereum_consensus/fork_choice/fork_choice.ex +++ b/lib/lambda_ethereum_consensus/fork_choice/fork_choice.ex @@ -118,7 +118,7 @@ defmodule LambdaEthereumConsensus.ForkChoice do @doc """ Get the current chain slot based on the system time. - TODO: There are just 2 uses of this function outside this module: + There are just 2 uses of this function outside this module: - At the begining of SyncBlocks.run/1 function, to get the head slot - In the Helpers.block_root_by_block_id/1 function """ diff --git a/lib/lambda_ethereum_consensus/p2p/blob_downloader.ex b/lib/lambda_ethereum_consensus/p2p/blob_downloader.ex index 4493a4fc0..d5e9de110 100644 --- a/lib/lambda_ethereum_consensus/p2p/blob_downloader.ex +++ b/lib/lambda_ethereum_consensus/p2p/blob_downloader.ex @@ -32,7 +32,6 @@ defmodule LambdaEthereumConsensus.P2P.BlobDownloader do def request_blobs_by_range(slot, count, on_blobs, retries) do Logger.debug("Requesting blobs", slot: slot) - # TODO: handle no-peers asynchronously? peer_id = get_some_peer() # NOTE: BeaconBlocksByRangeRequest == BlobSidecarsByRangeRequest @@ -62,7 +61,7 @@ defmodule LambdaEthereumConsensus.P2P.BlobDownloader do P2P.Peerbook.penalize_peer(peer_id) if retries > 0 do - Logger.debug("Retrying request for #{count} blobs", slot: slot) + Logger.debug("Retrying request for #{count} blobs: #{inspect(reason)}", slot: slot) request_blobs_by_range(slot, count, on_blobs, retries - 1) {:ok, store} else @@ -123,8 +122,8 @@ defmodule LambdaEthereumConsensus.P2P.BlobDownloader do defp get_some_peer() do case P2P.Peerbook.get_some_peer() do nil -> - Process.sleep(100) - get_some_peer() + # TODO: handle no-peers asynchronously + raise "No peers available to request blobs from." peer_id -> peer_id diff --git a/lib/lambda_ethereum_consensus/p2p/block_downloader.ex b/lib/lambda_ethereum_consensus/p2p/block_downloader.ex index 6522fa84a..aa9ae0395 100644 --- a/lib/lambda_ethereum_consensus/p2p/block_downloader.ex +++ b/lib/lambda_ethereum_consensus/p2p/block_downloader.ex @@ -66,7 +66,6 @@ defmodule LambdaEthereumConsensus.P2P.BlockDownloader do def request_blocks_by_range(slot, count, on_blocks, retries) do Logger.debug("Requesting block", slot: slot) - # TODO: handle no-peers asynchronously? peer_id = get_some_peer() request = @@ -173,7 +172,8 @@ defmodule LambdaEthereumConsensus.P2P.BlockDownloader do if retries > 0 do :telemetry.execute([:network, :request], %{blocks: 0}, Map.put(tags, :result, "retry")) pretty_roots = Enum.map_join(roots, ", ", &Base.encode16/1) - Logger.debug("Retrying request for blocks with roots #{pretty_roots}") + + Logger.debug("Retrying request for block roots #{pretty_roots}: #{inspect(reason)}") request_blocks_by_root(roots, on_blocks, retries - 1) {:ok, store} else @@ -186,8 +186,8 @@ defmodule LambdaEthereumConsensus.P2P.BlockDownloader do defp get_some_peer() do case P2P.Peerbook.get_some_peer() do nil -> - Process.sleep(100) - get_some_peer() + # TODO: handle no-peers asynchronously + raise "No peers available to request blocks from." peer_id -> peer_id diff --git a/lib/lambda_ethereum_consensus/p2p/peerbook.ex b/lib/lambda_ethereum_consensus/p2p/peerbook.ex index 96b9c34a9..f417304a0 100644 --- a/lib/lambda_ethereum_consensus/p2p/peerbook.ex +++ b/lib/lambda_ethereum_consensus/p2p/peerbook.ex @@ -2,10 +2,13 @@ defmodule LambdaEthereumConsensus.P2P.Peerbook do @moduledoc """ General peer bookkeeping. """ + require Logger alias LambdaEthereumConsensus.Libp2pPort alias LambdaEthereumConsensus.Store.KvSchema + alias LambdaEthereumConsensus.Utils @initial_score 100 + @penalizing_score 15 @target_peers 128 @max_prune_size 8 @prune_percentage 0.05 @@ -41,24 +44,51 @@ defmodule LambdaEthereumConsensus.P2P.Peerbook do Get some peer from the peerbook. """ def get_some_peer() do - # TODO: use some algorithm to pick a good peer, for now it's random + # TODO: This is a very naive implementation of a peer selection algorithm, + # this sorts the peers every time. The same is true for the pruning. peerbook = fetch_peerbook!() if peerbook == %{} do nil else - {peer_id, _score} = Enum.random(peerbook) - peer_id + peerbook + |> Enum.sort_by(fn {_peer_id, score} -> -score end) + |> Enum.take(5) + |> Enum.random() + |> elem(0) end end def penalize_peer(peer_id) do - fetch_peerbook!() |> Map.delete(peer_id) |> store_peerbook() + Logger.debug("[Peerbook] Penalizing peer: #{inspect(Utils.format_shorten_binary(peer_id))}") + + peer_score = fetch_peerbook!() |> Map.get(peer_id) + + case peer_score do + nil -> + :ok + + score when score - @penalizing_score <= 0 -> + Logger.debug("[Peerbook] Removing peer: #{inspect(Utils.format_shorten_binary(peer_id))}") + + fetch_peerbook!() + |> Map.delete(peer_id) + |> store_peerbook() + + score -> + fetch_peerbook!() + |> Map.put(peer_id, score - @penalizing_score) + |> store_peerbook() + end end def handle_new_peer(peer_id) do peerbook = fetch_peerbook!() + Logger.debug( + "[Peerbook] New peer connected: #{inspect(Utils.format_shorten_binary(peer_id))}" + ) + if not Map.has_key?(peerbook, peer_id) do :telemetry.execute([:peers, :connection], %{id: peer_id}, %{result: "success"}) Map.put(peerbook, peer_id, @initial_score) |> store_peerbook() @@ -81,14 +111,10 @@ defmodule LambdaEthereumConsensus.P2P.Peerbook do defp prune() do peerbook = fetch_peerbook!() len = map_size(peerbook) + prune_size = if len > 0, do: calculate_prune_size(len), else: 0 - if len != 0 do - prune_size = - (len * @prune_percentage) - |> round() - |> min(@max_prune_size) - |> min(len - @target_peers) - |> max(0) + if prune_size > 0 do + Logger.debug("[Peerbook] Pruning #{prune_size} peers by challenge") n = :rand.uniform(len) @@ -100,6 +126,14 @@ defmodule LambdaEthereumConsensus.P2P.Peerbook do end end + defp calculate_prune_size(len) do + (len * @prune_percentage) + |> round() + |> min(@max_prune_size) + |> min(len - @target_peers) + |> max(0) + end + defp store_peerbook(peerbook), do: put("", peerbook) defp fetch_peerbook(), do: get("") diff --git a/lib/libp2p_port.ex b/lib/libp2p_port.ex index 52f51f8ed..48f5a7758 100644 --- a/lib/libp2p_port.ex +++ b/lib/libp2p_port.ex @@ -9,8 +9,6 @@ defmodule LambdaEthereumConsensus.Libp2pPort do use GenServer - @tick_time 1000 - alias LambdaEthereumConsensus.Beacon.PendingBlocks alias LambdaEthereumConsensus.Beacon.SyncBlocks alias LambdaEthereumConsensus.ForkChoice @@ -84,7 +82,8 @@ defmodule LambdaEthereumConsensus.Libp2pPort do discovery_addresses: [String.t()] } - @sync_delay_millis 10_000 + @tick_time 1000 + @sync_delay_millis 15_000 ###################### ### API