github.com/prysmaticlabs/prysm@v1.4.4/validator/slashing-protection/cli_export.go (about)

     1  package slashingprotection
     2  
     3  import (
     4  	"encoding/json"
     5  	"path/filepath"
     6  
     7  	"github.com/pkg/errors"
     8  	"github.com/prysmaticlabs/prysm/cmd/validator/flags"
     9  	"github.com/prysmaticlabs/prysm/shared/cmd"
    10  	"github.com/prysmaticlabs/prysm/shared/fileutil"
    11  	"github.com/prysmaticlabs/prysm/validator/accounts/prompt"
    12  	"github.com/prysmaticlabs/prysm/validator/db/kv"
    13  	export "github.com/prysmaticlabs/prysm/validator/slashing-protection/local/standard-protection-format"
    14  	"github.com/urfave/cli/v2"
    15  )
    16  
    17  const (
    18  	jsonExportFileName = "slashing_protection.json"
    19  )
    20  
    21  // ExportSlashingProtectionJSONCli extracts a validator's slashing protection
    22  // history from their database and formats it into an EIP-3076 standard JSON
    23  // file via a CLI entrypoint to make it easy to migrate machines or Ethereum consensus clients.
    24  //
    25  // Steps:
    26  // 1. Parse a path to the validator's datadir from the CLI context.
    27  // 2. Open the validator database.
    28  // 3. Call the function which actually exports the data from
    29  // from the validator's db into an EIP standard slashing protection format
    30  // 4. Format and save the JSON file to a user's specified output directory.
    31  func ExportSlashingProtectionJSONCli(cliCtx *cli.Context) error {
    32  	var err error
    33  	dataDir := cliCtx.String(cmd.DataDirFlag.Name)
    34  	if !cliCtx.IsSet(cmd.DataDirFlag.Name) {
    35  		dataDir, err = prompt.InputDirectory(cliCtx, prompt.DataDirDirPromptText, cmd.DataDirFlag)
    36  		if err != nil {
    37  			return err
    38  		}
    39  	}
    40  
    41  	// ensure that the validator.db is found under the specified dir or its subdirectories
    42  	found, _, err := fileutil.RecursiveFileFind(kv.ProtectionDbFileName, dataDir)
    43  	if err != nil {
    44  		return errors.Wrapf(err, "error finding validator database at path %s", dataDir)
    45  	}
    46  	if !found {
    47  		return errors.Wrapf(err, "validator database not found at path %s", dataDir)
    48  	}
    49  
    50  	validatorDB, err := kv.NewKVStore(cliCtx.Context, dataDir, &kv.Config{})
    51  	if err != nil {
    52  		return errors.Wrapf(err, "could not access validator database at path %s", dataDir)
    53  	}
    54  	defer func() {
    55  		if err := validatorDB.Close(); err != nil {
    56  			log.WithError(err).Errorf("Could not close validator DB")
    57  		}
    58  	}()
    59  	eipJSON, err := export.ExportStandardProtectionJSON(cliCtx.Context, validatorDB)
    60  	if err != nil {
    61  		return errors.Wrap(err, "could not export slashing protection history")
    62  	}
    63  	outputDir, err := prompt.InputDirectory(
    64  		cliCtx,
    65  		"Enter your desired output directory for your slashing protection history",
    66  		flags.SlashingProtectionExportDirFlag,
    67  	)
    68  	if err != nil {
    69  		return errors.Wrap(err, "could not get slashing protection json file")
    70  	}
    71  	if outputDir == "" {
    72  		return errors.New("output directory not specified")
    73  	}
    74  	exists, err := fileutil.HasDir(outputDir)
    75  	if err != nil {
    76  		return errors.Wrapf(err, "could not check if output directory %s already exists", outputDir)
    77  	}
    78  	if !exists {
    79  		if err := fileutil.MkdirAll(outputDir); err != nil {
    80  			return errors.Wrapf(err, "could not create output directory %s", outputDir)
    81  		}
    82  	}
    83  	outputFilePath := filepath.Join(outputDir, jsonExportFileName)
    84  	encoded, err := json.MarshalIndent(eipJSON, "", "\t")
    85  	if err != nil {
    86  		return errors.Wrap(err, "could not JSON marshal slashing protection history")
    87  	}
    88  	return fileutil.WriteFile(outputFilePath, encoded)
    89  }