Make voluntary exits release-ready ()

* phrase validation utility
* use passphrase from docs portal
* enable voluntary exits
* Merge branch 'master' into enable-exits
* rename 'voluntary-exit' to 'exit'
* change passphrase
* gazelle
* change constant to error variable
* Merge branch 'master' into enable-exits
* rename error variable
* build fix
* Merge refs/heads/master into enable-exits
* do not remove whitespace in the middle
* Merge refs/heads/master into enable-exits
* Merge refs/heads/master into enable-exits
* Merge refs/heads/master into enable-exits
* Merge refs/heads/master into enable-exits
* code review changes
* Merge refs/heads/master into enable-exits
* Merge refs/heads/master into enable-exits
This commit is contained in:
Radosław Kapka 2020-09-24 13:00:44 +02:00 committed by GitHub
parent e1cd9143e0
commit 99164761f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 40 additions and 15 deletions

View File

@ -17,6 +17,8 @@ const (
minPasswordScore = 2
)
var errIncorrectPhrase = errors.New("input does not match wanted phrase")
// NotEmpty is a validation function to make sure the input given isn't empty and is valid unicode.
func NotEmpty(input string) error {
if input == "" {
@ -111,3 +113,11 @@ func ValidatePasswordInput(input string) error {
}
return nil
}
// ValidatePhrase checks whether the user input is equal to the wanted phrase. The verification is case sensitive.
func ValidatePhrase(input string, wantedPhrase string) error {
if strings.TrimSpace(input) != wantedPhrase {
return errIncorrectPhrase
}
return nil
}

View File

@ -153,5 +153,25 @@ func TestDefaultAndValidatePrompt(t *testing.T) {
require.NoError(t, err)
})
}
}
func TestValidatePhrase(t *testing.T) {
wantedPhrase := "wanted phrase"
t.Run("correct input", func(t *testing.T) {
assert.NoError(t, ValidatePhrase(wantedPhrase, wantedPhrase))
})
t.Run("correct input with whitespace", func(t *testing.T) {
assert.NoError(t, ValidatePhrase(" wanted phrase ", wantedPhrase))
})
t.Run("incorrect input", func(t *testing.T) {
err := ValidatePhrase("foo", wantedPhrase)
assert.NotNil(t, err)
assert.ErrorContains(t, errIncorrectPhrase.Error(), err)
})
t.Run("wrong letter case", func(t *testing.T) {
err := ValidatePhrase("Wanted Phrase", wantedPhrase)
assert.NotNil(t, err)
assert.ErrorContains(t, errIncorrectPhrase.Error(), err)
})
}

View File

@ -52,8 +52,6 @@ go_library(
"@com_github_urfave_cli_v2//:go_default_library",
"@com_github_wealdtech_go_eth2_wallet_encryptor_keystorev4//:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
],
)

View File

@ -18,8 +18,6 @@ import (
v2 "github.com/prysmaticlabs/prysm/validator/keymanager/v2"
"github.com/urfave/cli/v2"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type performExitCfg struct {
@ -30,6 +28,8 @@ type performExitCfg struct {
formattedPubKeys []string
}
const exitPassphrase = "Exit my validator"
// ExitAccountsCli performs a voluntary exit on one or more accounts.
func ExitAccountsCli(cliCtx *cli.Context, r io.Reader) error {
validatingPublicKeys, keymanager, err := prepareWallet(cliCtx)
@ -73,11 +73,6 @@ func ExitAccountsCli(cliCtx *cli.Context, r io.Reader) error {
return nil
}
// ExitAccountsUnimplemented is a stub for ExitAccounts until the latter is fully implemented.
func ExitAccountsUnimplemented(cliCtx *cli.Context, r io.Reader) error {
return status.Errorf(codes.Unimplemented, "method ExitAccounts not implemented")
}
func prepareWallet(cliCtx *cli.Context) ([][48]byte, v2.IKeymanager, error) {
w, err := wallet.OpenWalletOrElseCli(cliCtx, func(cliCtx *cli.Context) (*wallet.Wallet, error) {
return nil, errors.New(
@ -158,10 +153,12 @@ func interact(cliCtx *cli.Context, r io.Reader, validatingPublicKeys [][48]byte)
promptDescription := "Withdrawing funds is not possible in Phase 0 of the system. " +
"Please navigate to the following website and make sure you understand the current implications " +
"of a voluntary exit before making the final decision:"
promptURL := au.Blue("https://docs.prylabs.network/docs/faq/#can-i-get-back-my-testnet-eth-how-can-i-withdraw-my-validator-gains")
promptQuestion := "Do you still want to continue with the voluntary exit? Y/N"
promptURL := au.Blue("https://docs.prylabs.network/docs/wallet/nondeterministic/exiting-a-validator/#withdrawal-delay-warning")
promptQuestion := "If you still want to continue with the voluntary exit, please input the passphrase from the above URL"
promptText := fmt.Sprintf("%s\n%s\n%s\n%s", promptHeader, promptDescription, promptURL, promptQuestion)
resp, err := promptutil.ValidatePrompt(r, promptText, promptutil.ValidateYesOrNo)
resp, err := promptutil.ValidatePrompt(r, promptText, func(input string) error {
return promptutil.ValidatePhrase(input, exitPassphrase)
})
if err != nil {
return nil, nil, err
}

View File

@ -88,7 +88,7 @@ func TestExitAccountsCli_Ok(t *testing.T) {
// Prepare user input for final confirmation step
var stdin bytes.Buffer
stdin.Write([]byte("Y\n"))
stdin.Write([]byte(exitPassphrase))
rawPubKeys, formattedPubKeys, err := interact(cliCtx, &stdin, validatingPublicKeys)
require.NoError(t, err)
require.NotNil(t, rawPubKeys)

View File

@ -145,7 +145,7 @@ this command outputs a deposit data string which is required to become a validat
},
Action: func(cliCtx *cli.Context) error {
featureconfig.ConfigureValidator(cliCtx)
if err := ExitAccountsUnimplemented(cliCtx, os.Stdin); err != nil {
if err := ExitAccountsCli(cliCtx, os.Stdin); err != nil {
log.Fatalf("Could not perform voluntary exit: %v", err)
}
return nil