diff --git a/storage/src/main/java/tech/pegasys/teku/storage/server/Database.java b/storage/src/main/java/tech/pegasys/teku/storage/server/Database.java index 4f8751cc44b..162db230511 100644 --- a/storage/src/main/java/tech/pegasys/teku/storage/server/Database.java +++ b/storage/src/main/java/tech/pegasys/teku/storage/server/Database.java @@ -215,6 +215,8 @@ default Stream streamBlobSidecarKeys(final UInt64 Map getColumnCounts(final Optional maybeColumnFilter); + Map> getVariables(); + long getBlobSidecarColumnCount(); long getNonCanonicalBlobSidecarColumnCount(); diff --git a/storage/src/main/java/tech/pegasys/teku/storage/server/kvstore/KvStoreDatabase.java b/storage/src/main/java/tech/pegasys/teku/storage/server/kvstore/KvStoreDatabase.java index c7d5ead766b..2cd6d3c943d 100644 --- a/storage/src/main/java/tech/pegasys/teku/storage/server/kvstore/KvStoreDatabase.java +++ b/storage/src/main/java/tech/pegasys/teku/storage/server/kvstore/KvStoreDatabase.java @@ -380,6 +380,11 @@ public Map getColumnCounts(final Optional maybeColumnFilte return dao.getColumnCounts(maybeColumnFilter); } + @Override + public Map> getVariables() { + return dao.getVariables(); + } + @Override public long getBlobSidecarColumnCount() { return dao.getBlobSidecarColumnCount(); diff --git a/storage/src/main/java/tech/pegasys/teku/storage/server/kvstore/dataaccess/CombinedKvStoreDao.java b/storage/src/main/java/tech/pegasys/teku/storage/server/kvstore/dataaccess/CombinedKvStoreDao.java index 83bda83c9a8..5af4491d897 100644 --- a/storage/src/main/java/tech/pegasys/teku/storage/server/kvstore/dataaccess/CombinedKvStoreDao.java +++ b/storage/src/main/java/tech/pegasys/teku/storage/server/kvstore/dataaccess/CombinedKvStoreDao.java @@ -67,7 +67,11 @@ public CombinedKvStoreDao( @Override public Optional getGenesisTime() { - return db.get(schema.getVariableGenesisTime()); + try { + return db.get(schema.getVariableGenesisTime()); + } catch (final Exception e) { + return Optional.empty(); + } } @Override @@ -432,6 +436,37 @@ public Map getColumnCounts(final Optional maybeColumnFilte return columnCounts; } + @Override + public Map> getVariables() { + Map> variables = new LinkedHashMap<>(); + variables.put("GENESIS_TIME", getGenesisTime().map(UInt64::toString)); + variables.put("JUSTIFIED_CHECKPOINT", getJustifiedCheckpoint().map(Checkpoint::toString)); + variables.put( + "BEST_JUSTIFIED_CHECKPOINT", getBestJustifiedCheckpoint().map(Checkpoint::toString)); + variables.put("FINALIZED_CHECKPOINT", getFinalizedCheckpoint().map(Checkpoint::toString)); + variables.put( + "WEAK_SUBJECTIVITY_CHECKPOINT", getWeakSubjectivityCheckpoint().map(Checkpoint::toString)); + variables.put("ANCHOR_CHECKPOINT", getAnchor().map(Checkpoint::toString)); + variables.put( + "FINALIZED_DEPOSIT_SNAPSHOT", + getFinalizedDepositSnapshot().map(DepositTreeSnapshot::toString)); + try { + variables.put( + "LATEST_FINALIZED_STATE", + getLatestFinalizedState() + .map( + state -> + "BeaconState{slot=" + + state.getSlot() + + ", root=" + + state.hashTreeRoot().toHexString() + + "}")); + } catch (final Exception e) { + variables.put("FINALIZED_STATE", Optional.of(e.toString())); + } + return variables; + } + @Override public long getBlobSidecarColumnCount() { final KvStoreColumn column = diff --git a/storage/src/main/java/tech/pegasys/teku/storage/server/kvstore/dataaccess/KvStoreCombinedDao.java b/storage/src/main/java/tech/pegasys/teku/storage/server/kvstore/dataaccess/KvStoreCombinedDao.java index 2dba5e05e70..438c0b16e51 100644 --- a/storage/src/main/java/tech/pegasys/teku/storage/server/kvstore/dataaccess/KvStoreCombinedDao.java +++ b/storage/src/main/java/tech/pegasys/teku/storage/server/kvstore/dataaccess/KvStoreCombinedDao.java @@ -154,6 +154,8 @@ List getNonCanonicalBlobSidecarKeys( Map getColumnCounts(final Optional maybeColumnFilter); + Map> getVariables(); + long getBlobSidecarColumnCount(); long getNonCanonicalBlobSidecarColumnCount(); diff --git a/storage/src/main/java/tech/pegasys/teku/storage/server/kvstore/dataaccess/KvStoreCombinedDaoAdapter.java b/storage/src/main/java/tech/pegasys/teku/storage/server/kvstore/dataaccess/KvStoreCombinedDaoAdapter.java index b9d918f98dc..da50d25e596 100644 --- a/storage/src/main/java/tech/pegasys/teku/storage/server/kvstore/dataaccess/KvStoreCombinedDaoAdapter.java +++ b/storage/src/main/java/tech/pegasys/teku/storage/server/kvstore/dataaccess/KvStoreCombinedDaoAdapter.java @@ -228,6 +228,11 @@ public Map getColumnCounts(final Optional maybeColumnFilte return result; } + @Override + public Map> getVariables() { + return Map.of(); + } + @Override public long getBlobSidecarColumnCount() { return finalizedDao.getBlobSidecarColumnCount(); diff --git a/storage/src/main/java/tech/pegasys/teku/storage/server/noop/NoOpDatabase.java b/storage/src/main/java/tech/pegasys/teku/storage/server/noop/NoOpDatabase.java index af522b0c619..dc1b3bd4969 100644 --- a/storage/src/main/java/tech/pegasys/teku/storage/server/noop/NoOpDatabase.java +++ b/storage/src/main/java/tech/pegasys/teku/storage/server/noop/NoOpDatabase.java @@ -256,6 +256,11 @@ public Map getColumnCounts(final Optional maybeColumnFilte return new HashMap<>(); } + @Override + public Map> getVariables() { + return new HashMap<>(); + } + @Override public long getBlobSidecarColumnCount() { return 0L; diff --git a/teku/src/main/java/tech/pegasys/teku/cli/subcommand/debug/DebugDbCommand.java b/teku/src/main/java/tech/pegasys/teku/cli/subcommand/debug/DebugDbCommand.java index aa32be3ba42..04a048a2cdd 100644 --- a/teku/src/main/java/tech/pegasys/teku/cli/subcommand/debug/DebugDbCommand.java +++ b/teku/src/main/java/tech/pegasys/teku/cli/subcommand/debug/DebugDbCommand.java @@ -305,6 +305,40 @@ public int getColumnCounts( return 0; } + @Command( + name = "get-variables", + description = "Check variable values", + mixinStandardHelpOptions = true, + showDefaultValues = true, + abbreviateSynopsis = true, + versionProvider = PicoCliVersionProvider.class, + synopsisHeading = "%n", + descriptionHeading = "%nDescription:%n%n", + optionListHeading = "%nOptions:%n", + footerHeading = "%n", + footer = "Teku is licensed under the Apache License 2.0") + public int getVariables( + @Mixin final BeaconNodeDataOptions beaconNodeDataOptions, + @Mixin final Eth2NetworkOptions eth2NetworkOptions, + @Option( + names = {"--filter"}, + description = "Only get variables that match a given filter.") + final String filter) + throws Exception { + try (final Database database = createDatabase(beaconNodeDataOptions, eth2NetworkOptions)) { + final Map> variables = database.getVariables(); + variables + .keySet() + .forEach( + k -> { + if (filter == null || k.contains(filter)) { + System.out.printf("%-30s: %s\n", k, variables.get(k).orElse("EMPTY")); + } + }); + } + return 0; + } + @Command( name = "validate-block-history", description = "Validate the chain of finalized blocks via parent references",