Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions cmd/util/cmd/checkpoint-verify-hash/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package checkpoint_verify_hash

import (
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"

"github.com/onflow/flow-go/ledger/complete/wal"
)

var (
flagCheckpointDir string
flagCheckpoint string
flagNWorker uint
)

// Cmd verifies the cryptographic integrity of a checkpoint (V6 or V7) by
// recomputing every node's hash and comparing it against the hash stored with the
// node, without loading the whole checkpoint into memory.
var Cmd = &cobra.Command{
Use: "checkpoint-verify-hash",
Short: "Verify every node hash in a checkpoint (V6 or V7) by streaming nodes in DFS order.",
Long: `Verify the cryptographic integrity of a checkpoint (V6 or V7).

Each node is streamed in depth-first order (without loading the whole checkpoint
into memory) and its stored hash is recomputed and compared:
- leaf nodes are verified from their content (V6 payload value, V7 leaf hash),
- interim nodes are verified as HashInterNode of their children's hashes.

The 16 subtrie files are verified concurrently using --n-worker goroutines (1-16);
the top trie is then verified using the subtrie node hashes. On any hash mismatch
or integrity violation the command exits fatally.`,
Run: run,
}

func init() {
Cmd.Flags().StringVar(&flagCheckpointDir, "checkpoint-dir", "",
"directory containing the checkpoint files (required)")
_ = Cmd.MarkFlagRequired("checkpoint-dir")

Cmd.Flags().StringVar(&flagCheckpoint, "checkpoint", "",
"checkpoint header filename, e.g. \"checkpoint.00000100\" or \"checkpoint.00000100.v7\" (required)")
_ = Cmd.MarkFlagRequired("checkpoint")

Cmd.Flags().UintVar(&flagNWorker, "n-worker", 1,
"number of subtrie files to verify concurrently (1-16)")
}

func run(*cobra.Command, []string) {
log.Info().
Str("checkpoint_dir", flagCheckpointDir).
Str("checkpoint", flagCheckpoint).
Uint("n_worker", flagNWorker).
Msg("verifying checkpoint hashes")

err := wal.VerifyCheckpointHashes(log.Logger, flagCheckpointDir, flagCheckpoint, flagNWorker)
if err != nil {
// A hash mismatch or integrity violation (or any read error) is fatal: the
// checkpoint cannot be trusted.
log.Fatal().Err(err).Msg("checkpoint failed hash verification")
}

log.Info().Msgf("successfully verified all node hashes in checkpoint %v", flagCheckpoint)
}
4 changes: 2 additions & 2 deletions cmd/util/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
checkpoint_convert_v7 "github.com/onflow/flow-go/cmd/util/cmd/checkpoint-convert-v7"
checkpoint_iterate_nodes "github.com/onflow/flow-go/cmd/util/cmd/checkpoint-iterate-nodes"
checkpoint_list_tries "github.com/onflow/flow-go/cmd/util/cmd/checkpoint-list-tries"
checkpoint_trie_stats "github.com/onflow/flow-go/cmd/util/cmd/checkpoint-trie-stats"
checkpoint_verify_hash "github.com/onflow/flow-go/cmd/util/cmd/checkpoint-verify-hash"
compare_debug_tx "github.com/onflow/flow-go/cmd/util/cmd/compare-debug-tx"
db_migration "github.com/onflow/flow-go/cmd/util/cmd/db-migration"
debug_script "github.com/onflow/flow-go/cmd/util/cmd/debug-script"
Expand Down Expand Up @@ -107,10 +107,10 @@ func addCommands() {
rootCmd.AddCommand(extract.Cmd)
rootCmd.AddCommand(export.Cmd)
rootCmd.AddCommand(checkpoint_list_tries.Cmd)
rootCmd.AddCommand(checkpoint_trie_stats.Cmd)
rootCmd.AddCommand(checkpoint_collect_stats.Cmd)
rootCmd.AddCommand(checkpoint_convert_v7.Cmd)
rootCmd.AddCommand(checkpoint_iterate_nodes.Cmd)
rootCmd.AddCommand(checkpoint_verify_hash.Cmd)
rootCmd.AddCommand(read_badger.RootCmd)
rootCmd.AddCommand(read_protocol_state.RootCmd)
rootCmd.AddCommand(ledger_json_exporter.Cmd)
Expand Down
Loading