2020-10-15 22:31:52 +00:00
package accounts
2020-08-11 23:15:06 +00:00
import (
"archive/zip"
2020-09-21 08:50:05 +00:00
"encoding/hex"
2020-08-11 23:15:06 +00:00
"encoding/json"
"io/ioutil"
"os"
"path/filepath"
"sort"
"strings"
"testing"
"time"
"github.com/prysmaticlabs/prysm/shared/fileutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
2021-02-24 18:05:46 +00:00
"github.com/prysmaticlabs/prysm/validator/accounts/iface"
2020-10-15 22:31:52 +00:00
"github.com/prysmaticlabs/prysm/validator/accounts/wallet"
"github.com/prysmaticlabs/prysm/validator/keymanager"
2020-11-16 22:26:04 +00:00
"github.com/prysmaticlabs/prysm/validator/keymanager/derived"
)
var (
testMnemonic = "tumble turn jewel sudden social great water general cabin jacket bounce dry flip monster advance problem social half flee inform century chicken hard reason"
2020-08-11 23:15:06 +00:00
)
2020-09-21 08:50:05 +00:00
func TestBackupAccounts_Noninteractive_Derived ( t * testing . T ) {
walletDir , _ , passwordFilePath := setupWalletAndPasswordsDir ( t )
2021-01-05 13:09:41 +00:00
// Specify the password locally to this file for convenience.
2020-09-21 08:50:05 +00:00
password := "Pa$sW0rD0__Fo0xPr"
require . NoError ( t , ioutil . WriteFile ( passwordFilePath , [ ] byte ( password ) , os . ModePerm ) )
// Write a directory where we will backup accounts to.
2020-11-10 22:45:17 +00:00
backupDir := filepath . Join ( t . TempDir ( ) , "backupDir" )
2020-11-09 20:27:03 +00:00
require . NoError ( t , os . MkdirAll ( backupDir , params . BeaconIoConfig ( ) . ReadWriteExecutePermissions ) )
2020-09-21 08:50:05 +00:00
// Write a password for the accounts we wish to backup to a file.
backupPasswordFile := filepath . Join ( backupDir , "backuppass.txt" )
2020-11-10 22:45:17 +00:00
err := ioutil . WriteFile (
2020-09-21 08:50:05 +00:00
backupPasswordFile ,
[ ] byte ( "Passw0rdz4938%%" ) ,
params . BeaconIoConfig ( ) . ReadWritePermissions ,
)
require . NoError ( t , err )
// We initialize a wallet with a derived keymanager.
cliCtx := setupWalletCtx ( t , & testWalletConfig {
// Wallet configuration flags.
walletDir : walletDir ,
2020-10-15 22:31:52 +00:00
keymanagerKind : keymanager . Derived ,
2020-09-21 08:50:05 +00:00
walletPasswordFile : passwordFilePath ,
// Flags required for BackupAccounts to work.
backupPasswordFile : backupPasswordFile ,
backupDir : backupDir ,
} )
w , err := CreateWalletWithKeymanager ( cliCtx . Context , & CreateWalletConfig {
WalletCfg : & wallet . Config {
WalletDir : walletDir ,
2020-10-15 22:31:52 +00:00
KeymanagerKind : keymanager . Derived ,
2020-09-21 08:50:05 +00:00
WalletPassword : password ,
} ,
} )
require . NoError ( t , err )
2021-02-24 18:05:46 +00:00
km , err := w . InitializeKeymanager ( cliCtx . Context , iface . InitKeymanagerConfig { ListenForChanges : false } )
2020-09-21 08:50:05 +00:00
require . NoError ( t , err )
2020-11-16 22:26:04 +00:00
// Create 2 accounts
derivedKM , ok := km . ( * derived . Keymanager )
require . Equal ( t , true , ok )
err = derivedKM . RecoverAccountsFromMnemonic ( cliCtx . Context , testMnemonic , "" , 2 )
2020-09-21 08:50:05 +00:00
require . NoError ( t , err )
// Obtain the public keys of the accounts we created
2020-10-15 22:31:52 +00:00
pubkeys , err := km . FetchValidatingPublicKeys ( cliCtx . Context )
2020-09-21 08:50:05 +00:00
require . NoError ( t , err )
var generatedPubKeys [ ] string
for _ , pubkey := range pubkeys {
encoded := make ( [ ] byte , hex . EncodedLen ( len ( pubkey ) ) )
hex . Encode ( encoded , pubkey [ : ] )
generatedPubKeys = append ( generatedPubKeys , string ( encoded ) )
}
backupPublicKeys := strings . Join ( generatedPubKeys , "," )
// Recreate a cliCtx with the addition of these backup keys to be later used by the backup process
cliCtx = setupWalletCtx ( t , & testWalletConfig {
// Wallet configuration flags.
walletDir : walletDir ,
2020-10-15 22:31:52 +00:00
keymanagerKind : keymanager . Derived ,
2020-09-21 08:50:05 +00:00
walletPasswordFile : passwordFilePath ,
// Flags required for BackupAccounts to work.
backupPublicKeys : backupPublicKeys ,
backupPasswordFile : backupPasswordFile ,
backupDir : backupDir ,
} )
// Next, we attempt to backup the accounts.
require . NoError ( t , BackupAccountsCli ( cliCtx ) )
// We check a backup.zip file was created at the output path.
zipFilePath := filepath . Join ( backupDir , archiveFilename )
assert . DeepEqual ( t , true , fileutil . FileExists ( zipFilePath ) )
// We attempt to unzip the file and verify the keystores do match our accounts.
f , err := os . Open ( zipFilePath )
require . NoError ( t , err )
defer func ( ) {
require . NoError ( t , f . Close ( ) )
} ( )
fi , err := f . Stat ( )
require . NoError ( t , err )
r , err := zip . NewReader ( f , fi . Size ( ) )
require . NoError ( t , err )
// We check we have 2 keystore files in the unzipped results.
require . DeepEqual ( t , 2 , len ( r . File ) )
unzippedPublicKeys := make ( [ ] string , 2 )
for i , unzipped := range r . File {
ff , err := unzipped . Open ( )
require . NoError ( t , err )
encodedBytes , err := ioutil . ReadAll ( ff )
require . NoError ( t , err )
2020-10-15 22:31:52 +00:00
keystoreFile := & keymanager . Keystore { }
2020-09-21 08:50:05 +00:00
require . NoError ( t , json . Unmarshal ( encodedBytes , keystoreFile ) )
require . NoError ( t , ff . Close ( ) )
unzippedPublicKeys [ i ] = keystoreFile . Pubkey
}
sort . Strings ( unzippedPublicKeys )
sort . Strings ( generatedPubKeys )
assert . DeepEqual ( t , unzippedPublicKeys , generatedPubKeys )
}
2020-10-16 18:45:14 +00:00
func TestBackupAccounts_Noninteractive_Imported ( t * testing . T ) {
2020-08-11 23:15:06 +00:00
walletDir , _ , passwordFilePath := setupWalletAndPasswordsDir ( t )
// Write a directory where we will import keys from.
2020-11-10 22:45:17 +00:00
keysDir := filepath . Join ( t . TempDir ( ) , "keysDir" )
2020-11-09 20:27:03 +00:00
require . NoError ( t , os . MkdirAll ( keysDir , params . BeaconIoConfig ( ) . ReadWriteExecutePermissions ) )
2020-08-11 23:15:06 +00:00
// Write a directory where we will backup accounts to.
2020-11-10 22:45:17 +00:00
backupDir := filepath . Join ( t . TempDir ( ) , "backupDir" )
2020-11-09 20:27:03 +00:00
require . NoError ( t , os . MkdirAll ( backupDir , params . BeaconIoConfig ( ) . ReadWriteExecutePermissions ) )
2020-08-11 23:15:06 +00:00
// Create 2 keystore files in the keys directory we can then
// import from in our wallet.
k1 , _ := createKeystore ( t , keysDir )
time . Sleep ( time . Second )
k2 , _ := createKeystore ( t , keysDir )
generatedPubKeys := [ ] string { k1 . Pubkey , k2 . Pubkey }
backupPublicKeys := strings . Join ( generatedPubKeys , "," )
// Write a password for the accounts we wish to backup to a file.
backupPasswordFile := filepath . Join ( backupDir , "backuppass.txt" )
2020-11-10 22:45:17 +00:00
err := ioutil . WriteFile (
2020-08-11 23:15:06 +00:00
backupPasswordFile ,
[ ] byte ( "Passw0rdz4938%%" ) ,
params . BeaconIoConfig ( ) . ReadWritePermissions ,
)
require . NoError ( t , err )
2020-10-16 18:45:14 +00:00
// We initialize a wallet with a imported keymanager.
2020-08-11 23:15:06 +00:00
cliCtx := setupWalletCtx ( t , & testWalletConfig {
// Wallet configuration flags.
walletDir : walletDir ,
2020-10-16 18:45:14 +00:00
keymanagerKind : keymanager . Imported ,
2020-08-11 23:15:06 +00:00
walletPasswordFile : passwordFilePath ,
accountPasswordFile : passwordFilePath ,
// Flags required for ImportAccounts to work.
keysDir : keysDir ,
// Flags required for BackupAccounts to work.
backupPublicKeys : backupPublicKeys ,
backupPasswordFile : backupPasswordFile ,
backupDir : backupDir ,
} )
2020-10-20 02:26:31 +00:00
_ , err = CreateWalletWithKeymanager ( cliCtx . Context , & CreateWalletConfig {
2020-09-17 01:34:42 +00:00
WalletCfg : & wallet . Config {
2020-08-31 19:46:45 +00:00
WalletDir : walletDir ,
2020-10-16 18:45:14 +00:00
KeymanagerKind : keymanager . Imported ,
2020-10-10 02:07:28 +00:00
WalletPassword : password ,
2020-08-31 19:46:45 +00:00
} ,
} )
2020-08-11 23:15:06 +00:00
require . NoError ( t , err )
// We attempt to import accounts we wrote to the keys directory
// into our newly created wallet.
2020-08-31 19:46:45 +00:00
require . NoError ( t , ImportAccountsCli ( cliCtx ) )
2020-08-11 23:15:06 +00:00
// Next, we attempt to backup the accounts.
2020-08-31 19:46:45 +00:00
require . NoError ( t , BackupAccountsCli ( cliCtx ) )
2020-08-11 23:15:06 +00:00
// We check a backup.zip file was created at the output path.
zipFilePath := filepath . Join ( backupDir , archiveFilename )
assert . DeepEqual ( t , true , fileutil . FileExists ( zipFilePath ) )
// We attempt to unzip the file and verify the keystores do match our accounts.
f , err := os . Open ( zipFilePath )
require . NoError ( t , err )
defer func ( ) {
require . NoError ( t , f . Close ( ) )
} ( )
fi , err := f . Stat ( )
require . NoError ( t , err )
r , err := zip . NewReader ( f , fi . Size ( ) )
require . NoError ( t , err )
// We check we have 2 keystore files in the unzipped results.
require . DeepEqual ( t , 2 , len ( r . File ) )
unzippedPublicKeys := make ( [ ] string , 2 )
for i , unzipped := range r . File {
ff , err := unzipped . Open ( )
require . NoError ( t , err )
encodedBytes , err := ioutil . ReadAll ( ff )
require . NoError ( t , err )
2020-10-15 22:31:52 +00:00
keystoreFile := & keymanager . Keystore { }
2020-08-11 23:15:06 +00:00
require . NoError ( t , json . Unmarshal ( encodedBytes , keystoreFile ) )
require . NoError ( t , ff . Close ( ) )
unzippedPublicKeys [ i ] = keystoreFile . Pubkey
}
sort . Strings ( unzippedPublicKeys )
sort . Strings ( generatedPubKeys )
assert . DeepEqual ( t , unzippedPublicKeys , generatedPubKeys )
}