3131import org .hyperledger .besu .plugin .services .storage .SegmentedKeyValueStorageTransaction ;
3232
3333import java .util .Optional ;
34+ import java .util .function .Function ;
3435import java .util .function .Supplier ;
36+ import java .util .stream .Stream ;
3537
38+ import kotlin .Pair ;
3639import org .apache .tuweni .bytes .Bytes ;
40+ import org .apache .tuweni .bytes .Bytes32 ;
3741import org .bouncycastle .util .Arrays ;
3842import org .slf4j .Logger ;
3943import org .slf4j .LoggerFactory ;
@@ -103,6 +107,102 @@ public Optional<Bytes> getFlatAccount(
103107 return accountFound ;
104108 }
105109
110+ @ Override
111+ protected Stream <Pair <Bytes32 , Bytes >> accountsToPairStream (
112+ final SegmentedKeyValueStorage storage , final Bytes startKeyHash , final Bytes32 endKeyHash ) {
113+ final Stream <Pair <Bytes32 , Bytes >> stream =
114+ storage
115+ .streamFromKey (
116+ ACCOUNT_INFO_STATE ,
117+ calculateArchiveKeyNoContextMinSuffix (startKeyHash .toArrayUnsafe ()),
118+ calculateArchiveKeyNoContextMaxSuffix (endKeyHash .toArrayUnsafe ()))
119+ .map (e -> Bytes .of (calculateArchiveKeyNoContextMaxSuffix (trimSuffix (e .getKey ()))))
120+ .distinct ()
121+ .map (
122+ e ->
123+ new Pair <>(
124+ Bytes32 .wrap (trimSuffix (e .toArrayUnsafe ())),
125+ Bytes .of (
126+ storage .getNearestBefore (ACCOUNT_INFO_STATE , e ).get ().value ().get ())));
127+ return stream ;
128+ }
129+
130+ @ Override
131+ protected Stream <Pair <Bytes32 , Bytes >> accountsToPairStream (
132+ final SegmentedKeyValueStorage storage , final Bytes startKeyHash ) {
133+ final Stream <Pair <Bytes32 , Bytes >> stream =
134+ storage
135+ .streamFromKey (
136+ ACCOUNT_INFO_STATE ,
137+ calculateArchiveKeyNoContextMinSuffix (startKeyHash .toArrayUnsafe ()))
138+ .map (e -> Bytes .of (calculateArchiveKeyNoContextMaxSuffix (trimSuffix (e .getKey ()))))
139+ .distinct ()
140+ .map (
141+ e ->
142+ new Pair <Bytes32 , Bytes >(
143+ Bytes32 .wrap (trimSuffix (e .toArrayUnsafe ())),
144+ Bytes .of (
145+ storage .getNearestBefore (ACCOUNT_INFO_STATE , e ).get ().value ().get ())));
146+ return stream ;
147+ }
148+
149+ @ Override
150+ protected Stream <Pair <Bytes32 , Bytes >> storageToPairStream (
151+ final SegmentedKeyValueStorage storage ,
152+ final Hash accountHash ,
153+ final Bytes startKeyHash ,
154+ final Function <Bytes , Bytes > valueMapper ) {
155+ return storage
156+ .streamFromKey (
157+ ACCOUNT_STORAGE_STORAGE ,
158+ calculateArchiveKeyNoContextMinSuffix (
159+ calculateNaturalSlotKey (accountHash , Hash .wrap (Bytes32 .wrap (startKeyHash )))))
160+ .map (e -> Bytes .of (calculateArchiveKeyNoContextMaxSuffix (trimSuffix (e .getKey ()))))
161+ .distinct ()
162+ .map (
163+ key ->
164+ new Pair <>(
165+ Bytes32 .wrap (trimSuffix (key .slice (Hash .SIZE ).toArrayUnsafe ())),
166+ valueMapper .apply (
167+ Bytes .of (
168+ storage
169+ .getNearestBefore (ACCOUNT_STORAGE_STORAGE , key )
170+ .get ()
171+ .value ()
172+ .get ())
173+ .trimLeadingZeros ())));
174+ }
175+
176+ @ Override
177+ protected Stream <Pair <Bytes32 , Bytes >> storageToPairStream (
178+ final SegmentedKeyValueStorage storage ,
179+ final Hash accountHash ,
180+ final Bytes startKeyHash ,
181+ final Bytes32 endKeyHash ,
182+ final Function <Bytes , Bytes > valueMapper ) {
183+ return storage
184+ .streamFromKey (
185+ ACCOUNT_STORAGE_STORAGE ,
186+ calculateArchiveKeyNoContextMinSuffix (
187+ calculateNaturalSlotKey (accountHash , Hash .wrap (Bytes32 .wrap (startKeyHash )))),
188+ calculateArchiveKeyNoContextMaxSuffix (
189+ calculateNaturalSlotKey (accountHash , Hash .wrap (endKeyHash ))))
190+ .map (e -> Bytes .of (calculateArchiveKeyNoContextMaxSuffix (trimSuffix (e .getKey ()))))
191+ .distinct ()
192+ .map (
193+ key ->
194+ new Pair <>(
195+ Bytes32 .wrap (trimSuffix (key .slice (Hash .SIZE ).toArrayUnsafe ())),
196+ valueMapper .apply (
197+ Bytes .of (
198+ storage
199+ .getNearestBefore (ACCOUNT_STORAGE_STORAGE , key )
200+ .get ()
201+ .value ()
202+ .get ())
203+ .trimLeadingZeros ())));
204+ }
205+
106206 /*
107207 * Puts the account data for the given account hash and block context.
108208 */
@@ -128,6 +228,10 @@ public void removeFlatAccount(
128228 transaction .put (ACCOUNT_INFO_STATE , keySuffixed , DELETED_ACCOUNT_VALUE );
129229 }
130230
231+ private byte [] trimSuffix (final byte [] suffixedAddress ) {
232+ return Arrays .copyOfRange (suffixedAddress , 0 , suffixedAddress .length - 8 );
233+ }
234+
131235 /*
132236 * Retrieves the storage value for the given account hash and storage slot key, using the world state root hash supplier, storage root supplier, and node loader.
133237 */
@@ -232,6 +336,14 @@ public static byte[] calculateArchiveKeyWithMinSuffix(
232336 return calculateArchiveKeyWithSuffix (context , naturalKey , MIN_BLOCK_SUFFIX );
233337 }
234338
339+ public static byte [] calculateArchiveKeyNoContextMinSuffix (final byte [] naturalKey ) {
340+ return Arrays .concatenate (naturalKey , MIN_BLOCK_SUFFIX );
341+ }
342+
343+ public static byte [] calculateArchiveKeyNoContextMaxSuffix (final byte [] naturalKey ) {
344+ return Arrays .concatenate (naturalKey , MAX_BLOCK_SUFFIX );
345+ }
346+
235347 public static Bytes calculateArchiveKeyWithMaxSuffix (
236348 final BonsaiContext context , final byte [] naturalKey ) {
237349 return Bytes .of (calculateArchiveKeyWithSuffix (context , naturalKey , MAX_BLOCK_SUFFIX ));
0 commit comments