prysm-pulse/validator/accounts/accounts_backup.go
Raul Jordan d077483577
Add V3 Suffix to All Prysm Packages (#11083)
* v3 import renamings

* tidy

* fmt

* rev

* Update beacon-chain/core/epoch/precompute/reward_penalty_test.go

* Update beacon-chain/core/helpers/validators_test.go

* Update beacon-chain/db/alias.go

* Update beacon-chain/db/alias.go

* Update beacon-chain/db/alias.go

* Update beacon-chain/db/iface/BUILD.bazel

* Update beacon-chain/db/kv/kv.go

* Update beacon-chain/db/kv/state.go

* Update beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go

* Update beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go

* Update beacon-chain/sync/initial-sync/service.go

* fix deps

* fix bad replacements

* fix bad replacements

* change back

* gohashtree version

* fix deps

Co-authored-by: Nishant Das <nishdas93@gmail.com>
Co-authored-by: Potuz <potuz@prysmaticlabs.com>
2022-08-16 12:20:13 +00:00

90 lines
3.0 KiB
Go

package accounts
import (
"archive/zip"
"context"
"encoding/json"
"fmt"
"os"
"path/filepath"
"github.com/logrusorgru/aurora"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v3/io/file"
"github.com/prysmaticlabs/prysm/v3/validator/keymanager"
)
var (
au = aurora.NewAurora(true)
)
const (
allAccountsText = "All accounts"
// ArchiveFilename specifies the name of the backup. Exported for tests.
ArchiveFilename = "backup.zip"
)
// Backup allows users to select validator accounts from their wallet
// and export them as a backup.zip file containing the keys as EIP-2335 compliant
// keystore.json files, which are compatible with importing in other Ethereum consensus clients.
func (acm *AccountsCLIManager) Backup(ctx context.Context) error {
keystoresToBackup, err := acm.keymanager.ExtractKeystores(ctx, acm.filteredPubKeys, acm.backupsPassword)
if err != nil {
return errors.Wrap(err, "could not extract keys from keymanager")
}
return zipKeystoresToOutputDir(keystoresToBackup, acm.backupsDir)
}
// Zips a list of keystore into respective EIP-2335 keystore.json files and
// writes their zipped format into the specified output directory.
func zipKeystoresToOutputDir(keystoresToBackup []*keymanager.Keystore, outputDir string) error {
if len(keystoresToBackup) == 0 {
return errors.New("nothing to backup")
}
if err := file.MkdirAll(outputDir); err != nil {
return errors.Wrapf(err, "could not create directory at path: %s", outputDir)
}
// Marshal and zip all keystore files together and write the zip file
// to the specified output directory.
archivePath := filepath.Join(outputDir, ArchiveFilename)
if file.FileExists(archivePath) {
return errors.Errorf("Zip file already exists in directory: %s", archivePath)
}
// We create a new file to store our backup.zip.
zipfile, err := os.Create(filepath.Clean(archivePath))
if err != nil {
return errors.Wrapf(err, "could not create zip file with path: %s", archivePath)
}
defer func() {
if err := zipfile.Close(); err != nil {
log.WithError(err).Error("Could not close zipfile")
}
}()
// Using this zip file, we create a new zip writer which we write
// files to directly from our marshaled keystores.
writer := zip.NewWriter(zipfile)
defer func() {
// We close the zip writer when done.
if err := writer.Close(); err != nil {
log.WithError(err).Error("Could not close zip file after writing")
}
}()
for i, k := range keystoresToBackup {
encodedFile, err := json.MarshalIndent(k, "", "\t")
if err != nil {
return errors.Wrap(err, "could not marshal keystore to JSON file")
}
f, err := writer.Create(fmt.Sprintf("keystore-%d.json", i))
if err != nil {
return errors.Wrap(err, "could not write keystore file to zip")
}
if _, err = f.Write(encodedFile); err != nil {
return errors.Wrap(err, "could not write keystore file contents")
}
}
log.WithField(
"backup-path", archivePath,
).Infof("Successfully backed up %d accounts", len(keystoresToBackup))
return nil
}