@@ -20,15 +20,15 @@ defmodule LambdaEthereumConsensus.Beacon.StoreSetup do
20
20
@ doc """
21
21
Args: at least one can be nil.
22
22
- testnet_dir: directory of a testnet configuration, including ssz and yaml config.
23
- - checkpoint_sync_url: a url where checkpoint sync can be performed.
23
+ - checkpoint_sync_url: list of urls where checkpoint sync can be performed.
24
24
25
25
Return value: a store setup strategy, which is one of the following:
26
26
- {:file, anchor_state}: path of an ssz file to get the genesis state from.
27
- - {:checkpoint_sync_url, url}: url to get the genesis state from if performing checkpoint sync.
27
+ - {:checkpoint_sync_url, url}: list of urls to get the genesis state from if performing checkpoint sync.
28
28
- :db : the genesis state and store can only be recovered from the db.
29
29
"""
30
30
def make_strategy! ( nil , nil ) , do: :db
31
- def make_strategy! ( nil , url ) when is_binary ( url ) , do: { :checkpoint_sync_url , url }
31
+ def make_strategy! ( nil , urls ) when is_list ( urls ) , do: { :checkpoint_sync_url , urls }
32
32
33
33
def make_strategy! ( dir , nil ) when is_binary ( dir ) do
34
34
Path . join ( dir , "genesis.ssz" )
@@ -55,14 +55,14 @@ defmodule LambdaEthereumConsensus.Beacon.StoreSetup do
55
55
store
56
56
end
57
57
58
- def setup! ( { :checkpoint_sync_url , checkpoint_url } ) do
58
+ def setup! ( { :checkpoint_sync_url , checkpoint_urls } ) do
59
59
case restore_state_from_db ( ) do
60
60
{ :ok , store } ->
61
61
Logger . warning ( "[Checkpoint sync] Recent state found. Ignoring the checkpoint URL." )
62
62
store
63
63
64
64
_ ->
65
- fetch_state_from_url ( checkpoint_url )
65
+ fetch_and_compare_state_from_urls ( checkpoint_urls )
66
66
end
67
67
end
68
68
@@ -87,8 +87,12 @@ defmodule LambdaEthereumConsensus.Beacon.StoreSetup do
87
87
@ spec get_deposit_snapshot! ( ) :: DepositTreeSnapshot . t ( ) | nil
88
88
def get_deposit_snapshot! ( ) , do: get_deposit_snapshot! ( get_strategy! ( ) )
89
89
90
+ # The endpoint for deposit snapshots is deprecated in electra and will be removed in Fulu
91
+ # https://github.com/ethereum/beacon-APIs/pull/494
92
+ # For this reason we don't compare the deposits from the urls as most checkpoints are returning error 500
90
93
@ spec get_deposit_snapshot! ( store_setup_strategy ( ) ) :: DepositTreeSnapshot . t ( ) | nil
91
- def get_deposit_snapshot! ( { :checkpoint_sync_url , url } ) , do: fetch_deposit_snapshot ( url )
94
+ def get_deposit_snapshot! ( { :checkpoint_sync_url , urls } ) ,
95
+ do: fetch_deposit_snapshot ( List . first ( urls ) )
92
96
93
97
def get_deposit_snapshot! ( :db ) do
94
98
case StoreDb . fetch_deposits_snapshot ( ) do
@@ -129,28 +133,65 @@ defmodule LambdaEthereumConsensus.Beacon.StoreSetup do
129
133
end
130
134
end
131
135
132
- defp fetch_state_from_url ( url ) do
136
+ defp fetch_and_compare_state_from_urls ( urls ) do
133
137
Logger . info ( "[Checkpoint sync] Initiating checkpoint sync" )
134
138
139
+ # Fetch last finalized block for all urls
140
+ blocks = for { :ok , res } <- Enum . map ( urls , & CheckpointSync . get_block / 1 ) , do: res
141
+
142
+ case Enum . uniq ( blocks ) do
143
+ [ _ ] ->
144
+ Logger . info (
145
+ "[Checkpoin sync] Received the same last finalized block from #{ length ( blocks ) } checkpoint nodes"
146
+ )
147
+
148
+ _ ->
149
+ Logger . error (
150
+ "[Checkpoint sync] Received inconsistent last finalized block from #{ length ( blocks ) } checkpoint nodes"
151
+ )
152
+
153
+ Logger . flush ( )
154
+ System . halt ( 1 )
155
+ end
156
+
135
157
genesis_validators_root = ChainSpec . get_genesis_validators_root ( )
136
158
159
+ # All urls returned the same last finalized block, we will trust the first to get the state
160
+ { anchor_state , anchor_block } = fetch_state_from_url ( genesis_validators_root , List . first ( urls ) )
161
+
162
+ first_block = List . first ( blocks )
163
+
164
+ if anchor_state . latest_block_header . parent_root == first_block . message . parent_root do
165
+ { :ok , store } = Store . get_forkchoice_store ( anchor_state , anchor_block )
166
+
167
+ # Save store in DB
168
+ StoreDb . persist_store ( store )
169
+
170
+ store
171
+ else
172
+ Logger . error (
173
+ "[Checkpoint sync] Root mismatch when comparing latest finalized block with downloaded state"
174
+ )
175
+
176
+ Logger . flush ( )
177
+ System . halt ( 1 )
178
+ end
179
+ end
180
+
181
+ defp fetch_state_from_url ( genesis_validators_root , url ) do
137
182
case CheckpointSync . get_finalized_block_and_state ( url , genesis_validators_root ) do
138
183
{ :ok , { anchor_state , anchor_block } } ->
139
184
Logger . info (
140
- "[Checkpoint sync] Received beacon state and block" ,
185
+ "[Checkpoint sync] Received beacon state and block from URL #{ url } " ,
141
186
slot: anchor_state . slot
142
187
)
143
188
144
- # We already checked block and state match
145
- { :ok , store } = Store . get_forkchoice_store ( anchor_state , anchor_block )
146
-
147
- # Save store in DB
148
- StoreDb . persist_store ( store )
149
-
150
- store
189
+ { anchor_state , anchor_block }
151
190
152
191
_ ->
153
- Logger . error ( "[Checkpoint sync] Failed to fetch the latest finalized state and block" )
192
+ Logger . error (
193
+ "[Checkpoint sync] Failed to fetch the latest finalized state and block for URL: #{ url } "
194
+ )
154
195
155
196
Logger . flush ( )
156
197
System . halt ( 1 )
0 commit comments