2929import org .hyperledger .besu .datatypes .Address ;
3030import org .hyperledger .besu .datatypes .Hash ;
3131import org .hyperledger .besu .datatypes .StorageSlotKey ;
32+ import org .hyperledger .besu .datatypes .Wei ;
33+ import org .hyperledger .besu .ethereum .core .BlockHeader ;
34+ import org .hyperledger .besu .ethereum .core .Difficulty ;
3235import org .hyperledger .besu .ethereum .core .InMemoryKeyValueStorageProvider ;
3336import org .hyperledger .besu .ethereum .core .TrieGenerator ;
37+ import org .hyperledger .besu .ethereum .mainnet .MainnetBlockHeaderFunctions ;
3438import org .hyperledger .besu .ethereum .rlp .RLP ;
3539import org .hyperledger .besu .ethereum .storage .StorageProvider ;
3640import org .hyperledger .besu .ethereum .storage .keyvalue .KeyValueSegmentIdentifier ;
3741import org .hyperledger .besu .ethereum .trie .MerkleTrie ;
3842import org .hyperledger .besu .ethereum .trie .StorageEntriesCollector ;
43+ import org .hyperledger .besu .ethereum .trie .diffbased .bonsai .BonsaiAccount ;
3944import org .hyperledger .besu .ethereum .trie .patricia .StoredMerklePatriciaTrie ;
4045import org .hyperledger .besu .ethereum .worldstate .DataStorageConfiguration ;
4146import org .hyperledger .besu .ethereum .worldstate .FlatDbMode ;
4247import org .hyperledger .besu .ethereum .worldstate .ImmutableDataStorageConfiguration ;
4348import org .hyperledger .besu .ethereum .worldstate .StateTrieAccountValue ;
4449import org .hyperledger .besu .ethereum .worldstate .WorldStateStorageCoordinator ;
50+ import org .hyperledger .besu .evm .log .LogsBloomFilter ;
4551import org .hyperledger .besu .metrics .noop .NoOpMetricsSystem ;
4652import org .hyperledger .besu .plugin .services .storage .DataStorageFormat ;
4753import org .hyperledger .besu .plugin .services .storage .KeyValueStorage ;
6369public class BonsaiWorldStateKeyValueStorageTest {
6470
6571 public static Collection <Object []> flatDbMode () {
66- return Arrays .asList (new Object [][] {{FlatDbMode .FULL }, {FlatDbMode .PARTIAL }});
72+ return Arrays .asList (
73+ new Object [][] {{FlatDbMode .FULL }, {FlatDbMode .PARTIAL }, {FlatDbMode .ARCHIVE }});
6774 }
6875
6976 public static Collection <Object []> flatDbModeAndCodeStorageMode () {
7077 return Arrays .asList (
7178 new Object [][] {
7279 {FlatDbMode .FULL , false },
7380 {FlatDbMode .PARTIAL , false },
81+ {FlatDbMode .ARCHIVE , false },
7482 {FlatDbMode .FULL , true },
75- {FlatDbMode .PARTIAL , true }
83+ {FlatDbMode .PARTIAL , true },
84+ {FlatDbMode .ARCHIVE , true }
7685 });
7786 }
7887
@@ -84,10 +93,14 @@ public BonsaiWorldStateKeyValueStorage setUp(final FlatDbMode flatDbMode) {
8493
8594 public BonsaiWorldStateKeyValueStorage setUp (
8695 final FlatDbMode flatDbMode , final boolean useCodeHashStorage ) {
87- storage = emptyStorage (useCodeHashStorage );
88- if (flatDbMode .equals (FlatDbMode .FULL )) {
96+ if (flatDbMode .equals (FlatDbMode .ARCHIVE )) {
97+ storage = emptyArchiveStorage (useCodeHashStorage );
98+ storage .upgradeToFullFlatDbMode ();
99+ } else if (flatDbMode .equals (FlatDbMode .FULL )) {
100+ storage = emptyStorage (useCodeHashStorage );
89101 storage .upgradeToFullFlatDbMode ();
90102 } else if (flatDbMode .equals (FlatDbMode .PARTIAL )) {
103+ storage = emptyStorage (useCodeHashStorage );
91104 storage .downgradeToPartialFlatDbMode ();
92105 }
93106 return storage ;
@@ -392,6 +405,44 @@ void clear_reloadFlatDbStrategy(final FlatDbMode flatDbMode) {
392405 assertThat (storage .getAccount (Hash .ZERO )).isEmpty ();
393406 }
394407
408+ @ ParameterizedTest
409+ @ MethodSource ("flatDbMode" )
410+ void clear_putGetAccountFlatDbStrategy (final FlatDbMode flatDbMode ) {
411+ final BonsaiWorldStateKeyValueStorage storage = spy (setUp (flatDbMode ));
412+
413+ // save world state root hash
414+ final BonsaiWorldStateKeyValueStorage .Updater updater = storage .updater ();
415+
416+ Address account = Address .fromHexString ("0x1cda99fb95e5418ae3bdc3bab5c4efa4a5a58a7c" );
417+
418+ // RLP encoded account: address = 0x1cda99fb95e5418ae3bdc3bab5c4efa4a5a58a7c, balance =
419+ // 0x0000000000000000000000000000000000000000000000007b5e41a364ea8bfc, nonce = 15768
420+ updater
421+ .putAccountInfoState (
422+ account .addressHash (),
423+ Bytes .fromHexString (
424+ "0xF84E823D98887B5E41A364EA8BFCA056E81F171BCC55A6FF8345E692C0F86E5B48E01B996CADC001622FB5E363B421A0C5D2460186F7233C927E7DB2DCC703C0E500B653CA82273B7BFAD8045D85A470" ))
425+ .commit ();
426+
427+ assertThat (storage .getAccount (account .addressHash ())).isNotEmpty ();
428+
429+ BonsaiAccount retrievedAccount =
430+ BonsaiAccount .fromRLP (
431+ null , account , storage .getAccount (account .addressHash ()).get (), false );
432+ assertThat (retrievedAccount .getBalance ())
433+ .isEqualTo (
434+ Wei .fromHexString (
435+ "0x0000000000000000000000000000000000000000000000007b5e41a364ea8bfc" ));
436+ assertThat (retrievedAccount .getNonce ()).isEqualTo (15768 );
437+
438+ // clear
439+ storage .clear ();
440+
441+ assertThat (storage .getFlatDbStrategy ()).isNotNull ();
442+
443+ assertThat (storage .getAccount (account .addressHash ())).isEmpty ();
444+ }
445+
395446 @ ParameterizedTest
396447 @ MethodSource ("flatDbMode" )
397448 void reconcilesNonConflictingUpdaters (final FlatDbMode flatDbMode ) {
@@ -422,7 +473,12 @@ void reconcilesNonConflictingUpdaters(final FlatDbMode flatDbMode) {
422473 @ MethodSource ("flatDbMode" )
423474 void isWorldStateAvailable_defaultIsFalse (final FlatDbMode flatDbMode ) {
424475 setUp (flatDbMode );
425- assertThat (emptyStorage ().isWorldStateAvailable (UInt256 .valueOf (1 ), Hash .EMPTY )).isFalse ();
476+ if (flatDbMode .equals (FlatDbMode .ARCHIVE )) {
477+ assertThat (emptyArchiveStorage ().isWorldStateAvailable (UInt256 .valueOf (1 ), Hash .EMPTY ))
478+ .isFalse ();
479+ } else {
480+ assertThat (emptyStorage ().isWorldStateAvailable (UInt256 .valueOf (1 ), Hash .EMPTY )).isFalse ();
481+ }
426482 }
427483
428484 @ ParameterizedTest
@@ -466,6 +522,19 @@ private BonsaiWorldStateKeyValueStorage emptyStorage() {
466522 DataStorageConfiguration .DEFAULT_BONSAI_CONFIG );
467523 }
468524
525+ private BonsaiWorldStateKeyValueStorage emptyArchiveStorage () {
526+ final BonsaiWorldStateKeyValueStorage archiveStorage =
527+ new BonsaiWorldStateKeyValueStorage (
528+ new InMemoryKeyValueStorageProvider (),
529+ new NoOpMetricsSystem (),
530+ DataStorageConfiguration .DEFAULT_BONSAI_ARCHIVE_CONFIG );
531+ archiveStorage
532+ .getFlatDbStrategy ()
533+ .updateBlockContext (
534+ getArchiveBlockContext (1 )); // Do all archive calls under the context of block 1
535+ return archiveStorage ;
536+ }
537+
469538 private BonsaiWorldStateKeyValueStorage emptyStorage (final boolean useCodeHashStorage ) {
470539 return new BonsaiWorldStateKeyValueStorage (
471540 new InMemoryKeyValueStorageProvider (),
@@ -480,6 +549,26 @@ private BonsaiWorldStateKeyValueStorage emptyStorage(final boolean useCodeHashSt
480549 .build ());
481550 }
482551
552+ private BonsaiWorldStateKeyValueStorage emptyArchiveStorage (final boolean useCodeHashStorage ) {
553+ final BonsaiWorldStateKeyValueStorage archiveStorage =
554+ new BonsaiWorldStateKeyValueStorage (
555+ new InMemoryKeyValueStorageProvider (),
556+ new NoOpMetricsSystem (),
557+ ImmutableDataStorageConfiguration .builder ()
558+ .dataStorageFormat (DataStorageFormat .BONSAI_ARCHIVE )
559+ .bonsaiMaxLayersToLoad (DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD )
560+ .unstable (
561+ ImmutableDataStorageConfiguration .Unstable .builder ()
562+ .bonsaiCodeStoredByCodeHashEnabled (useCodeHashStorage )
563+ .build ())
564+ .build ());
565+ archiveStorage
566+ .getFlatDbStrategy ()
567+ .updateBlockContext (
568+ getArchiveBlockContext (1 )); // Do all archive calls under the context of block 1
569+ return archiveStorage ;
570+ }
571+
483572 @ Test
484573 void successfulPruneReturnsTrue () {
485574 final KeyValueStorage mockTrieLogStorage = mock (KeyValueStorage .class );
@@ -516,4 +605,32 @@ private BonsaiWorldStateKeyValueStorage setupSpyStorage(
516605 new NoOpMetricsSystem (),
517606 DataStorageConfiguration .DEFAULT_BONSAI_CONFIG );
518607 }
608+
609+ private static BlockHeader getArchiveBlockContext (final long blockNumber ) {
610+ final BlockHeader header =
611+ new BlockHeader (
612+ Hash .EMPTY ,
613+ Hash .EMPTY_TRIE_HASH ,
614+ Address .ZERO ,
615+ Hash .EMPTY_TRIE_HASH ,
616+ Hash .EMPTY_TRIE_HASH ,
617+ Hash .EMPTY_TRIE_HASH ,
618+ LogsBloomFilter .builder ().build (),
619+ Difficulty .ONE ,
620+ blockNumber ,
621+ 0 ,
622+ 0 ,
623+ 0 ,
624+ Bytes .of (0x00 ),
625+ Wei .ZERO ,
626+ Hash .EMPTY ,
627+ 0 ,
628+ null ,
629+ null ,
630+ null ,
631+ null ,
632+ null ,
633+ new MainnetBlockHeaderFunctions ());
634+ return header ;
635+ }
519636}
0 commit comments