@@ -2,12 +2,16 @@ defmodule LambdaEthereumConsensus.Store.BlobDb do
2
2
@ moduledoc """
3
3
Storage and retrieval of blobs.
4
4
"""
5
+ require Logger
6
+
5
7
alias LambdaEthereumConsensus.Store.Db
8
+ alias LambdaEthereumConsensus.Store.Utils
6
9
alias Types.Blobdata
7
10
alias Types.BlobSidecar
8
11
9
12
@ blob_sidecar_prefix "blob_sidecar"
10
13
@ blobdata_prefix "blobdata"
14
+ @ block_root_prefix "block_root"
11
15
12
16
@ spec store_blob ( BlobSidecar . t ( ) ) :: :ok
13
17
def store_blob ( % BlobSidecar { signed_block_header: % { message: block_header } } = blob ) do
@@ -22,6 +26,9 @@ defmodule LambdaEthereumConsensus.Store.BlobDb do
22
26
23
27
key = blobdata_key ( block_root , blob . index )
24
28
Db . put ( key , encoded_blobdata )
29
+
30
+ block_root_key = block_root_key ( block_header . slot , blob . index )
31
+ Db . put ( block_root_key , block_root )
25
32
end
26
33
27
34
# TODO: this is only used for tests
@@ -43,6 +50,16 @@ defmodule LambdaEthereumConsensus.Store.BlobDb do
43
50
end
44
51
end
45
52
53
+ @ spec get_blob_by_slot_index ( non_neg_integer ( ) , non_neg_integer ( ) ) ::
54
+ { :ok , BlobSidecar . t ( ) } | { :error , String . t ( ) } | :not_found
55
+ def get_blob_by_slot_index ( slot , index ) do
56
+ block_root_key = block_root_key ( slot , index )
57
+
58
+ with { :ok , block_root } <- Db . get ( block_root_key ) do
59
+ get_blob_sidecar ( block_root , index )
60
+ end
61
+ end
62
+
46
63
@ spec get_blob_with_proof ( Types . root ( ) , Types . blob_index ( ) ) ::
47
64
{ :ok , { Types . blob ( ) , Types . kzg_proof ( ) } } | { :error , String . t ( ) } | :not_found
48
65
def get_blob_with_proof ( block_root , blob_index ) do
@@ -55,8 +72,71 @@ defmodule LambdaEthereumConsensus.Store.BlobDb do
55
72
end
56
73
end
57
74
75
+ @ spec prune_old_blobs ( non_neg_integer ( ) ) :: :ok | { :error , String . t ( ) } | :not_found
76
+ def prune_old_blobs ( current_finalized_slot ) do
77
+ slot =
78
+ current_finalized_slot -
79
+ ChainSpec . get ( "MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS" ) * ChainSpec . get ( "SLOTS_PER_EPOCH" )
80
+
81
+ Logger . info ( "[BlobDb] Pruning started." , slot: slot )
82
+ last_finalized_key = slot |> block_root_key ( 0 )
83
+
84
+ with { :ok , it } <- Db . iterate ( ) ,
85
+ { :ok , @ block_root_prefix <> _ , _value } <-
86
+ Exleveldb . iterator_move ( it , last_finalized_key ) ,
87
+ { :ok , keys_to_remove } <- get_block_root_keys_to_remove ( it ) ,
88
+ :ok <- Exleveldb . iterator_close ( it ) do
89
+ total_removed =
90
+ keys_to_remove
91
+ |> Enum . reduce_while ( 0 , fn
92
+ key , acc_removed_count ->
93
+ case remove_blob_by_block_root_key ( key ) do
94
+ :ok ->
95
+ { :cont , acc_removed_count + 1 }
96
+
97
+ _ ->
98
+ Logger . error ( "[BlobDb] Error while removing key." , key: key )
99
+ { :halt , acc_removed_count }
100
+ end
101
+ end )
102
+
103
+ Logger . info ( "[BlobDb] Pruning finished. #{ total_removed } blobs removed." )
104
+ end
105
+ end
106
+
107
+ @ spec get_block_root_keys_to_remove ( list ( binary ( ) ) , :eleveldb . itr_ref ( ) ) ::
108
+ { :ok , list ( binary ( ) ) }
109
+ defp get_block_root_keys_to_remove ( keys_to_remove \\ [ ] , iterator ) do
110
+ case Exleveldb . iterator_move ( iterator , :prev ) do
111
+ { :ok , << @ block_root_prefix , _rest :: binary >> = block_root_key , _root } ->
112
+ [ block_root_key | keys_to_remove ] |> get_block_root_keys_to_remove ( iterator )
113
+
114
+ _ ->
115
+ { :ok , keys_to_remove }
116
+ end
117
+ end
118
+
119
+ @ spec remove_blob_by_block_root_key ( binary ( ) ) :: :ok | :not_found
120
+ defp remove_blob_by_block_root_key ( block_root_key ) do
121
+ << @ block_root_prefix , _slot :: unsigned - size ( 64 ) , index >> =
122
+ block_root_key
123
+
124
+ with { :ok , block_root } <- Db . get ( block_root_key ) do
125
+ key_blob = blob_sidecar_key ( block_root , index )
126
+ key_data = blobdata_key ( block_root , index )
127
+
128
+ Db . delete ( block_root_key )
129
+ Db . delete ( key_blob )
130
+ Db . delete ( key_data )
131
+ end
132
+ end
133
+
58
134
defp blob_sidecar_key ( block_root , blob_index ) ,
59
135
do: @ blob_sidecar_prefix <> block_root <> << blob_index >>
60
136
61
137
defp blobdata_key ( block_root , blob_index ) , do: @ blobdata_prefix <> block_root <> << blob_index >>
138
+
139
+ defp block_root_key ( blob_slot , blob_index ) do
140
+ Utils . get_key ( @ block_root_prefix , blob_slot ) <> << blob_index >>
141
+ end
62
142
end
0 commit comments