Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default bonsai to fully flat db and code storage by codehash #6894

1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
- Allow users to specify which plugins are registered [#6700](https://github.com/hyperledger/besu/pull/6700)
- Layered txpool tuning for blob transactions [#6940](https://github.com/hyperledger/besu/pull/6940)
- Update Gradle to 7.6.4 [#7030](https://github.com/hyperledger/besu/pull/7030)
- Default bonsai to use full-flat db and code-storage-by-code-hash [#6984](https://github.com/hyperledger/besu/pull/6894)

### Bug fixes
- Fix txpool dump/restore race condition [#6665](https://github.com/hyperledger/besu/pull/6665)
Expand Down
4 changes: 2 additions & 2 deletions besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -1706,8 +1706,8 @@ && isOptionSet(commandLine, "--sync-min-peers")) {

CommandLineUtils.failIfOptionDoesntMeetRequirement(
commandLine,
"--Xsnapsync-synchronizer-flat option can only be used when -Xsnapsync-synchronizer-flat-db-healing-enabled is true",
unstableSynchronizerOptions.isSnapsyncFlatDbHealingEnabled(),
"--Xsnapsync-synchronizer-flat option can only be used when --Xbonsai-full-flat-db-enabled is true",
dataStorageOptions.toDomainObject().getUnstable().getBonsaiFullFlatDbEnabled(),
asList(
"--Xsnapsync-synchronizer-flat-account-healed-count-per-request",
"--Xsnapsync-synchronizer-flat-slot-healed-count-per-request"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD;
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_RECEIPT_COMPACTION_ENABLED;
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.DEFAULT_BONSAI_CODE_USING_CODE_HASH_ENABLED;
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.DEFAULT_BONSAI_FULL_FLAT_DB_ENABLED;
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED;
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE;
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT;
Expand Down Expand Up @@ -93,6 +94,18 @@ public static class Unstable {
"The max number of blocks to load and prune trie logs for at startup. (default: ${DEFAULT-VALUE})")
private int bonsaiTrieLogPruningWindowSize = DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE;

// TODO: --Xsnapsync-synchronizer-flat-db-healing-enabled is deprecated, remove it in a future
// release
@CommandLine.Option(
hidden = true,
names = {
"--Xbonsai-full-flat-db-enabled",
"--Xsnapsync-synchronizer-flat-db-healing-enabled"
},
arity = "1",
description = "Enables bonsai full flat database strategy. (default: ${DEFAULT-VALUE})")
private Boolean bonsaiFullFlatDbEnabled = DEFAULT_BONSAI_FULL_FLAT_DB_ENABLED;

@CommandLine.Option(
hidden = true,
names = {"--Xbonsai-code-using-code-hash-enabled"},
Expand Down Expand Up @@ -161,6 +174,8 @@ public static DataStorageOptions fromConfig(final DataStorageConfiguration domai
domainObject.getUnstable().getBonsaiLimitTrieLogsEnabled();
dataStorageOptions.unstableOptions.bonsaiTrieLogPruningWindowSize =
domainObject.getUnstable().getBonsaiTrieLogPruningWindowSize();
dataStorageOptions.unstableOptions.bonsaiFullFlatDbEnabled =
domainObject.getUnstable().getBonsaiFullFlatDbEnabled();
dataStorageOptions.unstableOptions.bonsaiCodeUsingCodeHashEnabled =
domainObject.getUnstable().getBonsaiCodeStoredByCodeHashEnabled();

Expand All @@ -177,6 +192,7 @@ public DataStorageConfiguration toDomainObject() {
ImmutableDataStorageConfiguration.Unstable.builder()
.bonsaiLimitTrieLogsEnabled(unstableOptions.bonsaiLimitTrieLogsEnabled)
.bonsaiTrieLogPruningWindowSize(unstableOptions.bonsaiTrieLogPruningWindowSize)
.bonsaiFullFlatDbEnabled(unstableOptions.bonsaiFullFlatDbEnabled)
.bonsaiCodeStoredByCodeHashEnabled(unstableOptions.bonsaiCodeUsingCodeHashEnabled)
.build())
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,6 @@ public class SynchronizerOptions implements CLIOptions<SynchronizerConfiguration
private static final String SNAP_FLAT_STORAGE_HEALED_COUNT_PER_REQUEST_FLAG =
"--Xsnapsync-synchronizer-flat-slot-healed-count-per-request";

private static final String SNAP_FLAT_DB_HEALING_ENABLED_FLAG =
"--Xsnapsync-synchronizer-flat-db-healing-enabled";

private static final String SNAP_SERVER_ENABLED_FLAG = "--Xsnapsync-server-enabled";

private static final String CHECKPOINT_POST_MERGE_FLAG = "--Xcheckpoint-post-merge-enabled";
Expand Down Expand Up @@ -292,18 +289,11 @@ public void parseBlockPropagationRange(final String arg) {
private int snapsyncFlatStorageHealedCountPerRequest =
SnapSyncConfiguration.DEFAULT_LOCAL_FLAT_STORAGE_COUNT_TO_HEAL_PER_REQUEST;

@CommandLine.Option(
names = SNAP_FLAT_DB_HEALING_ENABLED_FLAG,
hidden = true,
paramLabel = "<Boolean>",
description = "Snap sync flat db healing enabled (default: ${DEFAULT-VALUE})")
private Boolean snapsyncFlatDbHealingEnabled =
SnapSyncConfiguration.DEFAULT_IS_FLAT_DB_HEALING_ENABLED;

@CommandLine.Option(
names = SNAP_SERVER_ENABLED_FLAG,
hidden = true,
paramLabel = "<Boolean>",
arity = "0..1",
description = "Snap sync server enabled (default: ${DEFAULT-VALUE})")
private Boolean snapsyncServerEnabled = SnapSyncConfiguration.DEFAULT_SNAP_SERVER_ENABLED;

Expand All @@ -316,15 +306,6 @@ public void parseBlockPropagationRange(final String arg) {

private SynchronizerOptions() {}

/**
* Flag to know whether the flat db healing feature is enabled or disabled.
*
* @return true is the flat db healing is enabled
*/
public boolean isSnapsyncFlatDbHealingEnabled() {
return snapsyncFlatDbHealingEnabled;
}

/**
* Flag to know whether the Snap sync server feature is enabled or disabled.
*
Expand Down Expand Up @@ -382,9 +363,8 @@ public static SynchronizerOptions fromConfig(final SynchronizerConfiguration con
config.getSnapSyncConfiguration().getLocalFlatAccountCountToHealPerRequest();
options.snapsyncFlatStorageHealedCountPerRequest =
config.getSnapSyncConfiguration().getLocalFlatStorageCountToHealPerRequest();
options.snapsyncFlatDbHealingEnabled =
config.getSnapSyncConfiguration().isFlatDbHealingEnabled();
options.checkpointPostMergeSyncEnabled = config.isCheckpointPostMergeEnabled();
options.snapsyncServerEnabled = config.getSnapSyncConfiguration().isSnapServerEnabled();
return options;
}

Expand Down Expand Up @@ -416,7 +396,6 @@ public SynchronizerConfiguration.Builder toDomainObject() {
.trienodeCountPerRequest(snapsyncTrieNodeCountPerRequest)
.localFlatAccountCountToHealPerRequest(snapsyncFlatAccountHealedCountPerRequest)
.localFlatStorageCountToHealPerRequest(snapsyncFlatStorageHealedCountPerRequest)
.isFlatDbHealingEnabled(snapsyncFlatDbHealingEnabled)
.isSnapServerEnabled(snapsyncServerEnabled)
.build());
builder.checkpointPostMergeEnabled(checkpointPostMergeSyncEnabled);
Expand Down Expand Up @@ -469,17 +448,13 @@ public List<String> getCLIOptions() {
SNAP_BYTECODE_COUNT_PER_REQUEST_FLAG,
OptionParser.format(snapsyncBytecodeCountPerRequest),
SNAP_TRIENODE_COUNT_PER_REQUEST_FLAG,
OptionParser.format(snapsyncTrieNodeCountPerRequest));
if (isSnapsyncFlatDbHealingEnabled()) {
value.addAll(
Arrays.asList(
SNAP_FLAT_ACCOUNT_HEALED_COUNT_PER_REQUEST_FLAG,
OptionParser.format(snapsyncFlatAccountHealedCountPerRequest),
SNAP_FLAT_STORAGE_HEALED_COUNT_PER_REQUEST_FLAG,
OptionParser.format(snapsyncFlatStorageHealedCountPerRequest),
SNAP_SERVER_ENABLED_FLAG,
OptionParser.format(snapsyncServerEnabled)));
}
OptionParser.format(snapsyncTrieNodeCountPerRequest),
SNAP_FLAT_ACCOUNT_HEALED_COUNT_PER_REQUEST_FLAG,
OptionParser.format(snapsyncFlatAccountHealedCountPerRequest),
SNAP_FLAT_STORAGE_HEALED_COUNT_PER_REQUEST_FLAG,
OptionParser.format(snapsyncFlatStorageHealedCountPerRequest),
SNAP_SERVER_ENABLED_FLAG,
OptionParser.format(snapsyncServerEnabled));
return value;
}
}
37 changes: 28 additions & 9 deletions besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2338,29 +2338,48 @@ public void kzgTrustedSetupFileLoadedWithCustomGenesisFile()
}

@Test
public void snapsyncHealingOptionShouldBeDisabledByDefault() {
public void bonsaiFlatDbShouldBeEnabledByDefault() {
final TestBesuCommand besuCommand = parseCommand();
assertThat(besuCommand.unstableSynchronizerOptions.isSnapsyncFlatDbHealingEnabled()).isFalse();
assertThat(
besuCommand
.getDataStorageOptions()
.toDomainObject()
.getUnstable()
.getBonsaiFullFlatDbEnabled())
.isTrue();
}

@Test
public void snapsyncHealingOptionShouldWork() {
final TestBesuCommand besuCommand =
parseCommand("--Xsnapsync-synchronizer-flat-db-healing-enabled", "true");
assertThat(besuCommand.unstableSynchronizerOptions.isSnapsyncFlatDbHealingEnabled()).isTrue();
final TestBesuCommand besuCommand = parseCommand("--Xbonsai-full-flat-db-enabled", "false");
assertThat(
besuCommand
.dataStorageOptions
.toDomainObject()
.getUnstable()
.getBonsaiFullFlatDbEnabled())
.isFalse();
}

@Test
public void snapsyncForHealingFeaturesShouldFailWhenHealingIsNotEnabled() {
parseCommand("--Xsnapsync-synchronizer-flat-account-healed-count-per-request", "100");
parseCommand(
"--Xbonsai-full-flat-db-enabled",
"false",
"--Xsnapsync-synchronizer-flat-account-healed-count-per-request",
"100");
assertThat(commandErrorOutput.toString(UTF_8))
.contains(
"--Xsnapsync-synchronizer-flat option can only be used when -Xsnapsync-synchronizer-flat-db-healing-enabled is true");
"--Xsnapsync-synchronizer-flat option can only be used when --Xbonsai-full-flat-db-enabled is true");

parseCommand("--Xsnapsync-synchronizer-flat-slot-healed-count-per-request", "100");
parseCommand(
"--Xbonsai-full-flat-db-enabled",
"false",
"--Xsnapsync-synchronizer-flat-slot-healed-count-per-request",
"100");
assertThat(commandErrorOutput.toString(UTF_8))
.contains(
"--Xsnapsync-synchronizer-flat option can only be used when -Xsnapsync-synchronizer-flat-db-healing-enabled is true");
"--Xsnapsync-synchronizer-flat option can only be used when --Xbonsai-full-flat-db-enabled is true");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ protected SynchronizerConfiguration.Builder createCustomizedDomainObject() {
.storageCountPerRequest(SnapSyncConfiguration.DEFAULT_STORAGE_COUNT_PER_REQUEST + 2)
.bytecodeCountPerRequest(
SnapSyncConfiguration.DEFAULT_BYTECODE_COUNT_PER_REQUEST + 2)
.isSnapServerEnabled(Boolean.TRUE)
.build());
}

Expand Down
2 changes: 2 additions & 0 deletions besu/src/test/resources/everything_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ receipt-compaction-enabled=true
# feature flags
Xsecp256k1-native-enabled=false
Xaltbn128-native-enabled=false
Xsnapsync-server-enabled=true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should not add the new full flat db flag ?

Xbonsai-full-flat-db-enabled=true

# compatibility flags
compatibility-eth64-forkid-enabled=false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.CODE_STORAGE;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE;
import static org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY;

import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat.FullFlatDbStrategy;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat.PartialFlatDbStrategy;
Expand Down Expand Up @@ -70,12 +71,36 @@ public void loadFlatDbStrategy(final SegmentedKeyValueStorage composedWorldState

@VisibleForTesting
FlatDbMode deriveFlatDbStrategy(final SegmentedKeyValueStorage composedWorldStateStorage) {
final FlatDbMode requestedFlatDbMode =
dataStorageConfiguration.getUnstable().getBonsaiFullFlatDbEnabled()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this flag still in unstable ?

Copy link
Contributor Author

@garyschulte garyschulte Apr 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is, but the generated classes have to be rebuilt to see it. Pretty much all of the bonsai configs are in unstable, we should move them all out of unstable when we change the default to bonsai 👍

? FlatDbMode.FULL
: FlatDbMode.PARTIAL;

final var existingTrieData =
composedWorldStateStorage.get(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY).isPresent();

var flatDbMode =
FlatDbMode.fromVersion(
composedWorldStateStorage
.get(TRIE_BRANCH_STORAGE, FLAT_DB_MODE)
.map(Bytes::wrap)
.orElse(FlatDbMode.PARTIAL.getVersion()));
.orElseGet(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

() -> {
// if we do not have a db-supplied config for flatdb, derive it:
// default to partial if trie data exists, but the flat config does not,
// and default to the storage config otherwise
var flatDbModeVal =
existingTrieData
? FlatDbMode.PARTIAL.getVersion()
: requestedFlatDbMode.getVersion();
// persist this config in the db
var setDbModeTx = composedWorldStateStorage.startTransaction();
setDbModeTx.put(
TRIE_BRANCH_STORAGE, FLAT_DB_MODE, flatDbModeVal.toArrayUnsafe());
setDbModeTx.commit();

return flatDbModeVal;
}));
LOG.info("Bonsai flat db mode found {}", flatDbMode);

return flatDbMode;
Expand Down Expand Up @@ -123,7 +148,7 @@ public FlatDbStrategy getFlatDbStrategy(
public void upgradeToFullFlatDbMode(final SegmentedKeyValueStorage composedWorldStateStorage) {
final SegmentedKeyValueStorageTransaction transaction =
composedWorldStateStorage.startTransaction();
// TODO: consider ARCHIVE mode
LOG.info("setting FlatDbStrategy to FULL");
transaction.put(
TRIE_BRANCH_STORAGE, FLAT_DB_MODE, FlatDbMode.FULL.getVersion().toArrayUnsafe());
transaction.commit();
Expand All @@ -134,6 +159,7 @@ public void downgradeToPartialFlatDbMode(
final SegmentedKeyValueStorage composedWorldStateStorage) {
final SegmentedKeyValueStorageTransaction transaction =
composedWorldStateStorage.startTransaction();
LOG.info("setting FlatDbStrategy to PARTIAL");
transaction.put(
TRIE_BRANCH_STORAGE, FLAT_DB_MODE, FlatDbMode.PARTIAL.getVersion().toArrayUnsafe());
transaction.commit();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ public interface DataStorageConfiguration {
.bonsaiMaxLayersToLoad(DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD)
.build();

DataStorageConfiguration DEFAULT_BONSAI_PARTIAL_DB_CONFIG =
ImmutableDataStorageConfiguration.builder()
.dataStorageFormat(DataStorageFormat.BONSAI)
.bonsaiMaxLayersToLoad(DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD)
.unstable(Unstable.DEFAULT_PARTIAL)
.build();

DataStorageConfiguration DEFAULT_FOREST_CONFIG =
ImmutableDataStorageConfiguration.builder()
.dataStorageFormat(DataStorageFormat.FOREST)
Expand Down Expand Up @@ -65,11 +72,15 @@ interface Unstable {
boolean DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED = false;
long MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT = DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD;
int DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE = 30_000;
boolean DEFAULT_BONSAI_CODE_USING_CODE_HASH_ENABLED = false;
boolean DEFAULT_BONSAI_FULL_FLAT_DB_ENABLED = true;
boolean DEFAULT_BONSAI_CODE_USING_CODE_HASH_ENABLED = true;

DataStorageConfiguration.Unstable DEFAULT =
ImmutableDataStorageConfiguration.Unstable.builder().build();

DataStorageConfiguration.Unstable DEFAULT_PARTIAL =
ImmutableDataStorageConfiguration.Unstable.builder().bonsaiFullFlatDbEnabled(false).build();

@Value.Default
default boolean getBonsaiLimitTrieLogsEnabled() {
return DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED;
Expand All @@ -80,6 +91,11 @@ default int getBonsaiTrieLogPruningWindowSize() {
return DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE;
}

@Value.Default
default boolean getBonsaiFullFlatDbEnabled() {
return DEFAULT_BONSAI_FULL_FLAT_DB_ENABLED;
}

@Value.Default
default boolean getBonsaiCodeStoredByCodeHashEnabled() {
return DEFAULT_BONSAI_CODE_USING_CODE_HASH_ENABLED;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,11 @@ public abstract class AbstractIsolationTests {
@BeforeEach
public void createStorage() {
worldStateKeyValueStorage =
// FYI: BonsaiSnapshoIsolationTests work with frozen/cached worldstates, using PARTIAL
// flat db strategy allows the tests to make account assertions based on trie
// (whereas a full db strategy will not, since the worldstates are frozen/cached)
createKeyValueStorageProvider()
.createWorldStateStorage(DataStorageConfiguration.DEFAULT_BONSAI_CONFIG);
.createWorldStateStorage(DataStorageConfiguration.DEFAULT_BONSAI_PARTIAL_DB_CONFIG);
archive =
new BonsaiWorldStateProvider(
(BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage,
Expand Down
Loading
Loading