Skip to content

Commit 3e7ce05

Browse files
authored
fix: base not found in tree (#1318)
1 parent 378b2fd commit 3e7ce05

File tree

7 files changed

+79
-32
lines changed

7 files changed

+79
-32
lines changed

.iex.exs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
alias LambdaEthereumConsensus.ForkChoice
2+
alias LambdaEthereumConsensus.ForkChoice.Head
3+
alias LambdaEthereumConsensus.StateTransition.Misc
4+
alias LambdaEthereumConsensus.Store.Blocks
5+
alias LambdaEthereumConsensus.Store.StoreDb
6+
alias LambdaEthereumConsensus.Utils
7+
8+
# Some convenience functions for debugging
9+
store = fn -> StoreDb.fetch_store() |> elem(1) end
10+
11+
head_root = fn -> store.() |> Head.get_head() |> elem(1) |> Utils.format_binary() end
12+
head_slot = fn -> store.() |> Head.get_head() |> elem(1) |> Blocks.get_block_info() |> then(& &1.signed_block.message.slot) end
13+
14+
store_calculated_slot = fn -> store.() |> ForkChoice.get_current_slot() end
15+
16+
epoch = fn slot -> slot |> Misc.compute_epoch_at_slot() end
17+
18+
block_info = fn "0x"<>root -> root |> Base.decode16(case: :lower) |> elem(1) |> Blocks.get_block_info() end
19+
20+
blocks_by_status = fn status -> Blocks.get_blocks_with_status(status) |> elem(1) end
21+
blocks_by_status_count = fn status -> blocks_by_status.(status) |> Enum.count() end

Makefile

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -172,35 +172,23 @@ checkpoint-sync: compile-all
172172

173173
#▶️ checkpoint-sync.logfile: @ Run an interactive terminal using checkpoint sync with a log file.
174174
checkpoint-sync.logfile: compile-all
175-
iex -S mix run -- --checkpoint-sync-url https://mainnet-checkpoint-sync.stakely.io/ --metrics --log-file ./logs/mainnet.log
176-
177-
#▶️ checkpoint-sync.logfile: @ Run an interactive terminal using checkpoint sync with a log file.
178-
checkpoint-sync.logfile: compile-all
179-
iex -S mix run -- --checkpoint-sync-url https://mainnet-checkpoint-sync.stakely.io/ --metrics --log-file ./logs/mainnet.log
175+
iex -S mix run -- --checkpoint-sync-url https://mainnet-checkpoint-sync.stakely.io/ --metrics --log-file ./logs/mainnet.log --discovery-port $(DYSCOVERY_PORT)
180176

181177
#▶️ sepolia: @ Run an interactive terminal using sepolia network
182178
sepolia: compile-all
183179
iex -S mix run -- --checkpoint-sync-url https://sepolia.beaconstate.info --network sepolia --metrics --discovery-port $(DYSCOVERY_PORT)
184180

185181
#▶️ sepolia.logfile: @ Run an interactive terminal using sepolia network with a log file
186182
sepolia.logfile: compile-all
187-
iex -S mix run -- --checkpoint-sync-url https://sepolia.beaconstate.info --network sepolia --metrics --log-file ./logs/sepolia.log
188-
189-
#▶️ sepolia.logfile: @ Run an interactive terminal using sepolia network with a log file
190-
sepolia.logfile: compile-all
191-
iex -S mix run -- --checkpoint-sync-url https://sepolia.beaconstate.info --network sepolia --metrics --log-file ./logs/sepolia.log
183+
iex -S mix run -- --checkpoint-sync-url https://sepolia.beaconstate.info --network sepolia --metrics --log-file ./logs/sepolia.log --discovery-port $(DYSCOVERY_PORT)
192184

193185
#▶️ holesky: @ Run an interactive terminal using holesky network
194186
holesky: compile-all
195187
iex -S mix run -- --checkpoint-sync-url https://checkpoint-sync.holesky.ethpandaops.io --network holesky --discovery-port $(DYSCOVERY_PORT)
196188

197189
#▶️ holesky.logfile: @ Run an interactive terminal using holesky network with a log file
198190
holesky.logfile: compile-all
199-
iex -S mix run -- --checkpoint-sync-url https://checkpoint-sync.holesky.ethpandaops.io --network holesky --log-file ./logs/holesky.log
200-
201-
#▶️ holesky.logfile: @ Run an interactive terminal using holesky network with a log file
202-
holesky.logfile: compile-all
203-
iex -S mix run -- --checkpoint-sync-url https://checkpoint-sync.holesky.ethpandaops.io --network holesky --log-file ./logs/holesky.log
191+
iex -S mix run -- --checkpoint-sync-url https://checkpoint-sync.holesky.ethpandaops.io --network holesky --log-file ./logs/holesky.log --discovery-port $(DYSCOVERY_PORT)
204192

205193
#▶️ gnosis: @ Run an interactive terminal using gnosis network
206194
gnosis: compile-all

lib/lambda_ethereum_consensus/beacon/pending_blocks.ex

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ defmodule LambdaEthereumConsensus.Beacon.PendingBlocks do
1212
alias LambdaEthereumConsensus.P2P.BlockDownloader
1313
alias LambdaEthereumConsensus.Store.BlobDb
1414
alias LambdaEthereumConsensus.Store.Blocks
15+
alias LambdaEthereumConsensus.Utils
1516
alias Types.BlockInfo
1617
alias Types.SignedBeaconBlock
1718
alias Types.Store
1819

19-
@type block_status :: :pending | :invalid | :download | :download_blobs | :unknown
20+
@type block_status ::
21+
:transitioned | :pending | :invalid | :download | :download_blobs | :unknown
2022
@type block_info ::
2123
{SignedBeaconBlock.t(), :pending | :download_blobs}
2224
| {nil, :invalid | :download}
@@ -40,15 +42,18 @@ defmodule LambdaEthereumConsensus.Beacon.PendingBlocks do
4042
def add_block(store, signed_block) do
4143
block_info = BlockInfo.from_block(signed_block)
4244
loaded_block = Blocks.get_block_info(block_info.root)
45+
log_md = [slot: signed_block.message.slot, root: block_info.root]
4346

4447
# If the block is new or was to be downloaded, we store it.
4548
if is_nil(loaded_block) or loaded_block.status == :download do
4649
missing_blobs = missing_blobs(block_info)
4750

4851
if Enum.empty?(missing_blobs) do
52+
Logger.debug("[PendingBlocks] No missing blobs for block, process it", log_md)
4953
Blocks.new_block_info(block_info)
5054
process_block_and_check_children(store, block_info)
5155
else
56+
Logger.debug("[PendingBlocks] Missing blobs for block, scheduling download", log_md)
5257
BlobDownloader.request_blobs_by_root(missing_blobs, &process_blobs/2, @download_retries)
5358

5459
block_info
@@ -72,6 +77,7 @@ defmodule LambdaEthereumConsensus.Beacon.PendingBlocks do
7277
{:ok, blocks} ->
7378
blocks
7479
|> Enum.sort_by(fn %BlockInfo{} = block_info -> block_info.signed_block.message.slot end)
80+
# Could we process just one/a small amount of blocks at a time? would it make more sense?
7581
|> Enum.reduce(store, fn block_info, store ->
7682
{store, _state} = process_block(store, block_info)
7783
store
@@ -101,16 +107,28 @@ defmodule LambdaEthereumConsensus.Beacon.PendingBlocks do
101107
end
102108
end
103109

104-
defp process_block(store, block_info) do
110+
defp process_block(store, %BlockInfo{signed_block: %{message: message}} = block_info) do
105111
if block_info.status != :pending do
106-
Logger.error("Called process block for a block that's not ready: #{block_info}")
112+
Logger.error(
113+
"[PendingBlocks] Called process block for a block that's not ready: #{block_info}"
114+
)
107115
end
108116

109-
parent_root = block_info.signed_block.message.parent_root
117+
log_md = [slot: message.slot, root: block_info.root]
118+
parent_root = message.parent_root
119+
120+
Logger.debug(
121+
"[PendingBlocks] Processing block, parent: #{Utils.format_binary(parent_root)}",
122+
log_md
123+
)
110124

111125
case Blocks.get_block_info(parent_root) do
112126
nil ->
113-
Logger.debug("[PendingBlocks] Add parent to download #{inspect(parent_root)}")
127+
Logger.debug(
128+
"[PendingBlocks] Add parent with root: #{Utils.format_shorten_binary(parent_root)} to download",
129+
log_md
130+
)
131+
114132
Blocks.add_block_to_download(parent_root)
115133

116134
BlockDownloader.request_blocks_by_root(
@@ -127,19 +145,25 @@ defmodule LambdaEthereumConsensus.Beacon.PendingBlocks do
127145
{store, :download_pending}
128146

129147
%BlockInfo{status: :invalid} ->
148+
Logger.warning(
149+
"[PendingBlocks] Parent block with root:#{Utils.format_shorten_binary(parent_root)} is invalid, making this block also invalid",
150+
log_md
151+
)
152+
130153
Blocks.change_status(block_info, :invalid)
131154
{store, :invalid}
132155

133156
%BlockInfo{status: :transitioned} ->
134157
case ForkChoice.on_block(store, block_info) do
135158
{:ok, store} ->
159+
Logger.debug("[PendingBlocks] Block transitioned after ForkChoice.on_block/2", log_md)
136160
Blocks.change_status(block_info, :transitioned)
137161
{store, :transitioned}
138162

139163
{:error, reason, store} ->
140-
Logger.error("[PendingBlocks] Saving block as invalid #{reason}",
141-
slot: block_info.signed_block.message.slot,
142-
root: block_info.root
164+
Logger.error(
165+
"[PendingBlocks] Saving block as invalid after ForkChoice.on_block/2 error: #{reason}",
166+
log_md
143167
)
144168

145169
Blocks.change_status(block_info, :invalid)
@@ -157,15 +181,15 @@ defmodule LambdaEthereumConsensus.Beacon.PendingBlocks do
157181

158182
defp process_downloaded_block(store, {:error, reason}) do
159183
# We might want to declare a block invalid here.
160-
Logger.error("Error downloading block: #{inspect(reason)}")
184+
Logger.error("[PendingBlocks] Error downloading block: #{inspect(reason)}")
161185
{:ok, store}
162186
end
163187

164-
defp process_blobs(store, {:ok, blobs}), do: {:ok, add_blobs(store, blobs)}
188+
def process_blobs(store, {:ok, blobs}), do: {:ok, add_blobs(store, blobs)}
165189

166-
defp process_blobs(store, {:error, reason}) do
190+
def process_blobs(store, {:error, reason}) do
167191
# We might want to declare a block invalid here.
168-
Logger.error("Error downloading blobs: #{inspect(reason)}")
192+
Logger.error("[PendingBlocks] Error downloading blobs: #{inspect(reason)}")
169193
{:ok, store}
170194
end
171195

@@ -178,19 +202,20 @@ defmodule LambdaEthereumConsensus.Beacon.PendingBlocks do
178202
|> Enum.map(&BlobDb.store_blob/1)
179203
|> Enum.uniq()
180204
|> Enum.reduce(store, fn root, store ->
181-
with %BlockInfo{} = block_info <- Blocks.get_block_info(root),
205+
with %BlockInfo{status: :download_blobs} = block_info <- Blocks.get_block_info(root),
182206
[] <- missing_blobs(block_info) do
183207
block_info
184208
|> Blocks.change_status(:pending)
185209
|> then(&process_block_and_check_children(store, &1))
186210
else
187-
_ -> store
211+
_ ->
212+
store
188213
end
189214
end)
190215
end
191216

192217
@spec missing_blobs(BlockInfo.t()) :: [Types.BlobIdentifier.t()]
193-
defp missing_blobs(%BlockInfo{root: root, signed_block: signed_block}) do
218+
def missing_blobs(%BlockInfo{root: root, signed_block: signed_block}) do
194219
signed_block.message.body.blob_kzg_commitments
195220
|> Stream.with_index()
196221
|> Enum.filter(&blob_needs_download?(&1, root))

lib/lambda_ethereum_consensus/fork_choice/fork_choice.ex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ defmodule LambdaEthereumConsensus.ForkChoice do
6565
|> tap(fn store ->
6666
StoreDb.persist_store(store)
6767
Logger.info("[Fork choice] Added new block", slot: slot, root: block_root)
68+
69+
Logger.info("[Fork choice] Recomputed head",
70+
slot: store.head_slot,
71+
root: store.head_root
72+
)
6873
end)
6974
|> then(&{:ok, &1})
7075

lib/lambda_ethereum_consensus/p2p/blob_downloader.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ defmodule LambdaEthereumConsensus.P2P.BlobDownloader do
122122
defp get_some_peer() do
123123
case P2P.Peerbook.get_some_peer() do
124124
nil ->
125-
# TODO: handle no-peers asynchronously
125+
# TODO: (#1317) handle no-peers asynchronously
126126
raise "No peers available to request blobs from."
127127

128128
peer_id ->

lib/lambda_ethereum_consensus/p2p/block_downloader.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ defmodule LambdaEthereumConsensus.P2P.BlockDownloader do
186186
defp get_some_peer() do
187187
case P2P.Peerbook.get_some_peer() do
188188
nil ->
189-
# TODO: handle no-peers asynchronously
189+
# TODO: (#1317) handle no-peers asynchronously
190190
raise "No peers available to request blocks from."
191191

192192
peer_id ->

lib/lambda_ethereum_consensus/utils.ex

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ defmodule LambdaEthereumConsensus.Utils do
4848
"0x#{String.slice(encoded, 0, 3)}..#{String.slice(encoded, -4, 4)}"
4949
end
5050

51+
@doc """
52+
Format a binary to its hexadecimal representation.
53+
"""
54+
@spec format_binary(binary) :: String.t()
55+
def format_binary(binary) do
56+
"0x#{binary |> Base.encode16(case: :lower)}"
57+
end
58+
5159
@doc """
5260
Format a bitstring to a base 2 representation.
5361
"""

0 commit comments

Comments
 (0)