Display URLs for tracking exited validators (#8361)

* Display URLs for tracking exited validators

* extract displaying info to separate function

* fix URL comment

* extract config names

* gzl

* lowercase config names

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
This commit is contained in:
Radosław Kapka
2021-02-01 20:00:06 +01:00
committed by GitHub
parent c6e96204e8
commit b5a82b9075
9 changed files with 86 additions and 23 deletions

View File

@@ -33,6 +33,7 @@ go_library(
"//shared/featureconfig:go_default_library",
"//shared/fileutil:go_default_library",
"//shared/grpcutils:go_default_library",
"//shared/params:go_default_library",
"//shared/petnames:go_default_library",
"//shared/promptutil:go_default_library",
"//shared/tos:go_default_library",
@@ -44,6 +45,7 @@ go_library(
"//validator/keymanager/derived:go_default_library",
"//validator/keymanager/imported:go_default_library",
"//validator/keymanager/remote:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_google_uuid//:go_default_library",
"@com_github_logrusorgru_aurora//:go_default_library",
"@com_github_manifoldco_promptui//:go_default_library",

View File

@@ -6,12 +6,14 @@ import (
"io"
"strings"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/cmd"
"github.com/prysmaticlabs/prysm/shared/grpcutils"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/promptutil"
"github.com/prysmaticlabs/prysm/validator/accounts/prompt"
"github.com/prysmaticlabs/prysm/validator/accounts/wallet"
@@ -39,12 +41,12 @@ func ExitAccountsCli(cliCtx *cli.Context, r io.Reader) error {
return err
}
rawPubKeys, formattedPubKeys, err := interact(cliCtx, r, validatingPublicKeys)
rawPubKeys, trimmedPubKeys, err := interact(cliCtx, r, validatingPublicKeys)
if err != nil {
return err
}
// User decided to cancel the voluntary exit.
if rawPubKeys == nil && formattedPubKeys == nil {
if rawPubKeys == nil && trimmedPubKeys == nil {
return nil
}
@@ -52,25 +54,19 @@ func ExitAccountsCli(cliCtx *cli.Context, r io.Reader) error {
if err != nil {
return err
}
cfg := performExitCfg{
*validatorClient,
*nodeClient,
keymanager,
rawPubKeys,
formattedPubKeys,
trimmedPubKeys,
}
formattedExitedKeys, err := performExit(cliCtx, cfg)
rawExitedKeys, trimmedExitedKeys, err := performExit(cliCtx, cfg)
if err != nil {
return err
}
if len(formattedExitedKeys) > 0 {
log.WithField("publicKeys", strings.Join(formattedExitedKeys, ", ")).
Info("Voluntary exit was successful for the accounts listed")
} else {
log.Info("No successful voluntary exits")
}
displayExitInfo(rawExitedKeys, trimmedExitedKeys)
return nil
}
@@ -197,7 +193,7 @@ func prepareClients(cliCtx *cli.Context) (*ethpb.BeaconNodeValidatorClient, *eth
return &validatorClient, &nodeClient, nil
}
func performExit(cliCtx *cli.Context, cfg performExitCfg) ([]string, error) {
func performExit(cliCtx *cli.Context, cfg performExitCfg) (rawExitedKeys [][]byte, formattedExitedKeys []string, err error) {
var rawNotExitedKeys [][]byte
for i, key := range cfg.rawPubKeys {
if err := client.ProposeExit(cliCtx.Context, cfg.validatorClient, cfg.nodeClient, cfg.keymanager.Sign, key); err != nil {
@@ -212,7 +208,9 @@ func performExit(cliCtx *cli.Context, cfg performExitCfg) ([]string, error) {
}
}
}
var formattedExitedKeys []string
rawExitedKeys = make([][]byte, 0)
formattedExitedKeys = make([]string, 0)
for i, key := range cfg.rawPubKeys {
found := false
for _, notExited := range rawNotExitedKeys {
@@ -222,9 +220,38 @@ func performExit(cliCtx *cli.Context, cfg performExitCfg) ([]string, error) {
}
}
if !found {
rawExitedKeys = append(rawExitedKeys, key)
formattedExitedKeys = append(formattedExitedKeys, cfg.formattedPubKeys[i])
}
}
return formattedExitedKeys, nil
return rawExitedKeys, formattedExitedKeys, nil
}
func displayExitInfo(rawExitedKeys [][]byte, trimmedExitedKeys []string) {
if len(rawExitedKeys) > 0 {
urlFormattedPubKeys := make([]string, len(rawExitedKeys))
for i, key := range rawExitedKeys {
var baseUrl string
if params.BeaconConfig().ConfigName == params.ConfigNames[params.Pyrmont] {
baseUrl = "https://pyrmont.beaconcha.in/validator/"
} else {
baseUrl = "https://beaconcha.in/validator/"
}
// Remove '0x' prefix
urlFormattedPubKeys[i] = baseUrl + hexutil.Encode(key)[2:]
}
ifaceKeys := make([]interface{}, len(urlFormattedPubKeys))
for i, k := range urlFormattedPubKeys {
ifaceKeys[i] = k
}
info := fmt.Sprintf("Voluntary exit was successful for the accounts listed. "+
"URLs where you can track each validator's exit:\n"+strings.Repeat("%s\n", len(ifaceKeys)), ifaceKeys...)
log.WithField("publicKeys", strings.Join(trimmedExitedKeys, ", ")).Info(info)
} else {
log.Info("No successful voluntary exits")
}
}

View File

@@ -16,6 +16,7 @@ import (
"github.com/prysmaticlabs/prysm/validator/accounts/wallet"
"github.com/prysmaticlabs/prysm/validator/keymanager"
"github.com/prysmaticlabs/prysm/validator/keymanager/imported"
"github.com/sirupsen/logrus/hooks/test"
"google.golang.org/grpc/metadata"
)
@@ -97,11 +98,12 @@ func TestExitAccountsCli_Ok(t *testing.T) {
rawPubKeys,
formattedPubKeys,
}
formattedExitedKeys, err := performExit(cliCtx, cfg)
rawExitedKeys, formattedExitedKeys, err := performExit(cliCtx, cfg)
require.NoError(t, err)
assert.Equal(t, 1, len(formattedExitedKeys))
expectedKey := "0x" + keystore.Pubkey[:12]
assert.Equal(t, expectedKey, formattedExitedKeys[0])
require.Equal(t, 1, len(rawExitedKeys))
assert.DeepEqual(t, rawPubKeys[0], rawExitedKeys[0])
require.Equal(t, 1, len(formattedExitedKeys))
assert.Equal(t, "0x"+keystore.Pubkey[:12], formattedExitedKeys[0])
}
func TestPrepareWallet_EmptyWalletReturnsError(t *testing.T) {
@@ -149,3 +151,16 @@ func TestPrepareClients_AddsGRPCHeaders(t *testing.T) {
assert.Equal(t, "Basic some-token", md.Get("Authorization")[0])
assert.Equal(t, "some-value", md.Get("Some-Other-Header")[0])
}
func TestDisplayExitInfo(t *testing.T) {
logHook := test.NewGlobal()
key := []byte("0x123456")
displayExitInfo([][]byte{key}, []string{string(key)})
assert.LogsContain(t, logHook, "https://beaconcha.in/validator/3078313233343536")
}
func TestDisplayExitInfo_NoKeys(t *testing.T) {
logHook := test.NewGlobal()
displayExitInfo([][]byte{}, []string{})
assert.LogsContain(t, logHook, "No successful voluntary exits")
}