github.com/prysmaticlabs/prysm@v1.4.4/validator/accounts/accounts_backup_test.go (about) 1 package accounts 2 3 import ( 4 "archive/zip" 5 "encoding/hex" 6 "encoding/json" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "sort" 11 "strings" 12 "testing" 13 "time" 14 15 "github.com/prysmaticlabs/prysm/shared/fileutil" 16 "github.com/prysmaticlabs/prysm/shared/params" 17 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 18 "github.com/prysmaticlabs/prysm/shared/testutil/require" 19 "github.com/prysmaticlabs/prysm/validator/accounts/iface" 20 "github.com/prysmaticlabs/prysm/validator/accounts/wallet" 21 "github.com/prysmaticlabs/prysm/validator/keymanager" 22 "github.com/prysmaticlabs/prysm/validator/keymanager/derived" 23 constant "github.com/prysmaticlabs/prysm/validator/testing" 24 ) 25 26 func TestBackupAccounts_Noninteractive_Derived(t *testing.T) { 27 walletDir, _, passwordFilePath := setupWalletAndPasswordsDir(t) 28 // Specify the password locally to this file for convenience. 29 password := "Pa$sW0rD0__Fo0xPr" 30 require.NoError(t, ioutil.WriteFile(passwordFilePath, []byte(password), os.ModePerm)) 31 32 // Write a directory where we will backup accounts to. 33 backupDir := filepath.Join(t.TempDir(), "backupDir") 34 require.NoError(t, os.MkdirAll(backupDir, params.BeaconIoConfig().ReadWriteExecutePermissions)) 35 36 // Write a password for the accounts we wish to backup to a file. 37 backupPasswordFile := filepath.Join(backupDir, "backuppass.txt") 38 err := ioutil.WriteFile( 39 backupPasswordFile, 40 []byte("Passw0rdz4938%%"), 41 params.BeaconIoConfig().ReadWritePermissions, 42 ) 43 require.NoError(t, err) 44 45 // We initialize a wallet with a derived keymanager. 46 cliCtx := setupWalletCtx(t, &testWalletConfig{ 47 // Wallet configuration flags. 48 walletDir: walletDir, 49 keymanagerKind: keymanager.Derived, 50 walletPasswordFile: passwordFilePath, 51 // Flags required for BackupAccounts to work. 52 backupPasswordFile: backupPasswordFile, 53 backupDir: backupDir, 54 }) 55 w, err := CreateWalletWithKeymanager(cliCtx.Context, &CreateWalletConfig{ 56 WalletCfg: &wallet.Config{ 57 WalletDir: walletDir, 58 KeymanagerKind: keymanager.Derived, 59 WalletPassword: password, 60 }, 61 }) 62 require.NoError(t, err) 63 64 km, err := w.InitializeKeymanager(cliCtx.Context, iface.InitKeymanagerConfig{ListenForChanges: false}) 65 require.NoError(t, err) 66 // Create 2 accounts 67 derivedKM, ok := km.(*derived.Keymanager) 68 require.Equal(t, true, ok) 69 err = derivedKM.RecoverAccountsFromMnemonic(cliCtx.Context, constant.TestMnemonic, "", 2) 70 require.NoError(t, err) 71 72 // Obtain the public keys of the accounts we created 73 pubkeys, err := km.FetchValidatingPublicKeys(cliCtx.Context) 74 require.NoError(t, err) 75 var generatedPubKeys []string 76 for _, pubkey := range pubkeys { 77 encoded := make([]byte, hex.EncodedLen(len(pubkey))) 78 hex.Encode(encoded, pubkey[:]) 79 generatedPubKeys = append(generatedPubKeys, string(encoded)) 80 } 81 backupPublicKeys := strings.Join(generatedPubKeys, ",") 82 83 // Recreate a cliCtx with the addition of these backup keys to be later used by the backup process 84 cliCtx = setupWalletCtx(t, &testWalletConfig{ 85 // Wallet configuration flags. 86 walletDir: walletDir, 87 keymanagerKind: keymanager.Derived, 88 walletPasswordFile: passwordFilePath, 89 // Flags required for BackupAccounts to work. 90 backupPublicKeys: backupPublicKeys, 91 backupPasswordFile: backupPasswordFile, 92 backupDir: backupDir, 93 }) 94 95 // Next, we attempt to backup the accounts. 96 require.NoError(t, BackupAccountsCli(cliCtx)) 97 98 // We check a backup.zip file was created at the output path. 99 zipFilePath := filepath.Join(backupDir, archiveFilename) 100 assert.DeepEqual(t, true, fileutil.FileExists(zipFilePath)) 101 102 // We attempt to unzip the file and verify the keystores do match our accounts. 103 f, err := os.Open(zipFilePath) 104 require.NoError(t, err) 105 defer func() { 106 require.NoError(t, f.Close()) 107 }() 108 fi, err := f.Stat() 109 require.NoError(t, err) 110 r, err := zip.NewReader(f, fi.Size()) 111 require.NoError(t, err) 112 113 // We check we have 2 keystore files in the unzipped results. 114 require.DeepEqual(t, 2, len(r.File)) 115 unzippedPublicKeys := make([]string, 2) 116 for i, unzipped := range r.File { 117 ff, err := unzipped.Open() 118 require.NoError(t, err) 119 encodedBytes, err := ioutil.ReadAll(ff) 120 require.NoError(t, err) 121 keystoreFile := &keymanager.Keystore{} 122 require.NoError(t, json.Unmarshal(encodedBytes, keystoreFile)) 123 require.NoError(t, ff.Close()) 124 unzippedPublicKeys[i] = keystoreFile.Pubkey 125 } 126 sort.Strings(unzippedPublicKeys) 127 sort.Strings(generatedPubKeys) 128 assert.DeepEqual(t, unzippedPublicKeys, generatedPubKeys) 129 } 130 131 func TestBackupAccounts_Noninteractive_Imported(t *testing.T) { 132 walletDir, _, passwordFilePath := setupWalletAndPasswordsDir(t) 133 // Write a directory where we will import keys from. 134 keysDir := filepath.Join(t.TempDir(), "keysDir") 135 require.NoError(t, os.MkdirAll(keysDir, params.BeaconIoConfig().ReadWriteExecutePermissions)) 136 137 // Write a directory where we will backup accounts to. 138 backupDir := filepath.Join(t.TempDir(), "backupDir") 139 require.NoError(t, os.MkdirAll(backupDir, params.BeaconIoConfig().ReadWriteExecutePermissions)) 140 141 // Create 2 keystore files in the keys directory we can then 142 // import from in our wallet. 143 k1, _ := createKeystore(t, keysDir) 144 time.Sleep(time.Second) 145 k2, _ := createKeystore(t, keysDir) 146 generatedPubKeys := []string{k1.Pubkey, k2.Pubkey} 147 backupPublicKeys := strings.Join(generatedPubKeys, ",") 148 149 // Write a password for the accounts we wish to backup to a file. 150 backupPasswordFile := filepath.Join(backupDir, "backuppass.txt") 151 err := ioutil.WriteFile( 152 backupPasswordFile, 153 []byte("Passw0rdz4938%%"), 154 params.BeaconIoConfig().ReadWritePermissions, 155 ) 156 require.NoError(t, err) 157 158 // We initialize a wallet with a imported keymanager. 159 cliCtx := setupWalletCtx(t, &testWalletConfig{ 160 // Wallet configuration flags. 161 walletDir: walletDir, 162 keymanagerKind: keymanager.Imported, 163 walletPasswordFile: passwordFilePath, 164 accountPasswordFile: passwordFilePath, 165 // Flags required for ImportAccounts to work. 166 keysDir: keysDir, 167 // Flags required for BackupAccounts to work. 168 backupPublicKeys: backupPublicKeys, 169 backupPasswordFile: backupPasswordFile, 170 backupDir: backupDir, 171 }) 172 _, err = CreateWalletWithKeymanager(cliCtx.Context, &CreateWalletConfig{ 173 WalletCfg: &wallet.Config{ 174 WalletDir: walletDir, 175 KeymanagerKind: keymanager.Imported, 176 WalletPassword: password, 177 }, 178 }) 179 require.NoError(t, err) 180 181 // We attempt to import accounts we wrote to the keys directory 182 // into our newly created wallet. 183 require.NoError(t, ImportAccountsCli(cliCtx)) 184 185 // Next, we attempt to backup the accounts. 186 require.NoError(t, BackupAccountsCli(cliCtx)) 187 188 // We check a backup.zip file was created at the output path. 189 zipFilePath := filepath.Join(backupDir, archiveFilename) 190 assert.DeepEqual(t, true, fileutil.FileExists(zipFilePath)) 191 192 // We attempt to unzip the file and verify the keystores do match our accounts. 193 f, err := os.Open(zipFilePath) 194 require.NoError(t, err) 195 defer func() { 196 require.NoError(t, f.Close()) 197 }() 198 fi, err := f.Stat() 199 require.NoError(t, err) 200 r, err := zip.NewReader(f, fi.Size()) 201 require.NoError(t, err) 202 203 // We check we have 2 keystore files in the unzipped results. 204 require.DeepEqual(t, 2, len(r.File)) 205 unzippedPublicKeys := make([]string, 2) 206 for i, unzipped := range r.File { 207 ff, err := unzipped.Open() 208 require.NoError(t, err) 209 encodedBytes, err := ioutil.ReadAll(ff) 210 require.NoError(t, err) 211 keystoreFile := &keymanager.Keystore{} 212 require.NoError(t, json.Unmarshal(encodedBytes, keystoreFile)) 213 require.NoError(t, ff.Close()) 214 unzippedPublicKeys[i] = keystoreFile.Pubkey 215 } 216 sort.Strings(unzippedPublicKeys) 217 sort.Strings(generatedPubKeys) 218 assert.DeepEqual(t, unzippedPublicKeys, generatedPubKeys) 219 }