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,104 @@ 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
167+ .apply (
168+ Bytes .of (
169+ storage
170+ .getNearestBefore (ACCOUNT_STORAGE_STORAGE , key )
171+ .get ()
172+ .value ()
173+ .get ())
174+ .trimLeadingZeros ())));
175+ }
176+
177+ @ Override
178+ protected Stream <Pair <Bytes32 , Bytes >> storageToPairStream (
179+ final SegmentedKeyValueStorage storage ,
180+ final Hash accountHash ,
181+ final Bytes startKeyHash ,
182+ final Bytes32 endKeyHash ,
183+ final Function <Bytes , Bytes > valueMapper ) {
184+ return storage
185+ .streamFromKey (
186+ ACCOUNT_STORAGE_STORAGE ,
187+ calculateArchiveKeyNoContextMinSuffix (
188+ calculateNaturalSlotKey (accountHash , Hash .wrap (Bytes32 .wrap (startKeyHash )))),
189+ calculateArchiveKeyNoContextMaxSuffix (
190+ calculateNaturalSlotKey (accountHash , Hash .wrap (endKeyHash ))))
191+ .map (e -> Bytes .of (calculateArchiveKeyNoContextMaxSuffix (trimSuffix (e .getKey ()))))
192+ .distinct ()
193+ .map (
194+ key ->
195+ new Pair <>(
196+ Bytes32 .wrap (trimSuffix (key .slice (Hash .SIZE ).toArrayUnsafe ())),
197+ valueMapper
198+ .apply (
199+ Bytes .of (
200+ storage
201+ .getNearestBefore (ACCOUNT_STORAGE_STORAGE , key )
202+ .get ()
203+ .value ()
204+ .get ())
205+ .trimLeadingZeros ())));
206+ }
207+
106208 /*
107209 * Puts the account data for the given account hash and block context.
108210 */
@@ -128,6 +230,10 @@ public void removeFlatAccount(
128230 transaction .put (ACCOUNT_INFO_STATE , keySuffixed , DELETED_ACCOUNT_VALUE );
129231 }
130232
233+ private byte [] trimSuffix (final byte [] suffixedAddress ) {
234+ return Arrays .copyOfRange (suffixedAddress , 0 , suffixedAddress .length - 8 );
235+ }
236+
131237 /*
132238 * 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.
133239 */
@@ -232,6 +338,14 @@ public static byte[] calculateArchiveKeyWithMinSuffix(
232338 return calculateArchiveKeyWithSuffix (context , naturalKey , MIN_BLOCK_SUFFIX );
233339 }
234340
341+ public static byte [] calculateArchiveKeyNoContextMinSuffix (final byte [] naturalKey ) {
342+ return Arrays .concatenate (naturalKey , MIN_BLOCK_SUFFIX );
343+ }
344+
345+ public static byte [] calculateArchiveKeyNoContextMaxSuffix (final byte [] naturalKey ) {
346+ return Arrays .concatenate (naturalKey , MAX_BLOCK_SUFFIX );
347+ }
348+
235349 public static Bytes calculateArchiveKeyWithMaxSuffix (
236350 final BonsaiContext context , final byte [] naturalKey ) {
237351 return Bytes .of (calculateArchiveKeyWithSuffix (context , naturalKey , MAX_BLOCK_SUFFIX ));
0 commit comments