HTTP VALIDATOR API: remote keymanager api /eth/v1/remotekeys (#13059)

* WIP migrating keymanager api changes

* gaz

* fixing more tests

* fixing unit tests

* fixing deepsource

* fixing visibility of package

* fixing more package visability issues

* gaz

* fixing test

* moving routes to proper location

* removing whitespae for linting

* Update validator/rpc/handlers_keymanager.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* radek's comments

---------

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
This commit is contained in:
james-prysm
2023-10-19 11:17:42 -05:00
committed by GitHub
parent e231d88ca0
commit 7143fe80bc
24 changed files with 682 additions and 1948 deletions

View File

@@ -8,11 +8,7 @@ go_library(
],
importpath = "github.com/prysmaticlabs/prysm/v4/validator/keymanager",
visibility = [
"//cmd:__subpackages__",
"//testing/endtoend/components:__subpackages__",
"//tools:__subpackages__",
"//validator:__pkg__",
"//validator:__subpackages__",
"//visibility:public",
],
deps = [
"//async/event:go_default_library",

View File

@@ -1,4 +1,6 @@
package keymanager
// KeysReloaded is a "key reloaded" message.
const KeysReloaded = "Reloaded validator keys into keymanager"
const (
KeysReloaded = "Reloaded validator keys into keymanager"
)

View File

@@ -37,10 +37,8 @@ go_test(
srcs = ["keymanager_test.go"],
embed = [":go_default_library"],
deps = [
"//config/fieldparams:go_default_library",
"//crypto/bls:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/eth/service:go_default_library",
"//proto/prysm/v1alpha1/validator-client:go_default_library",
"//testing/require:go_default_library",
"//validator/keymanager/remote-web3signer/internal:go_default_library",

View File

@@ -24,6 +24,15 @@ import (
log "github.com/sirupsen/logrus"
)
const (
StatusImported = "IMPORTED"
StatusError = "ERROR"
StatusDuplicate = "DUPLICATE"
StatusUnknown = "UNKNOWN"
StatusNotFound = "NOT_FOUND"
StatusDeleted = "DELETED"
)
// SetupConfig includes configuration values for initializing.
// a keymanager, such as passwords, the wallet, and more.
// Web3Signer contains one public keys option. Either through a URL or a static key list.
@@ -449,71 +458,95 @@ func DisplayRemotePublicKeys(validatingPubKeys [][48]byte) {
}
// AddPublicKeys imports a list of public keys into the keymanager for web3signer use. Returns status with message.
func (km *Keymanager) AddPublicKeys(ctx context.Context, pubKeys [][fieldparams.BLSPubkeyLength]byte) ([]*ethpbservice.ImportedRemoteKeysStatus, error) {
if ctx == nil {
return nil, errors.New("context is nil")
}
importedRemoteKeysStatuses := make([]*ethpbservice.ImportedRemoteKeysStatus, len(pubKeys))
for i, pubKey := range pubKeys {
func (km *Keymanager) AddPublicKeys(pubKeys []string) []*keymanager.KeyStatus {
importedRemoteKeysStatuses := make([]*keymanager.KeyStatus, len(pubKeys))
for i, pubkey := range pubKeys {
found := false
pubkeyBytes, err := hexutil.Decode(pubkey)
if err != nil {
importedRemoteKeysStatuses[i] = &keymanager.KeyStatus{
Status: StatusError,
Message: err.Error(),
}
continue
}
if len(pubkeyBytes) != fieldparams.BLSPubkeyLength {
importedRemoteKeysStatuses[i] = &keymanager.KeyStatus{
Status: StatusError,
Message: fmt.Sprintf("pubkey byte length (%d) did not match bls pubkey byte length (%d)", len(pubkeyBytes), fieldparams.BLSPubkeyLength),
}
continue
}
for _, key := range km.providedPublicKeys {
if bytes.Equal(key[:], pubKey[:]) {
if bytes.Equal(key[:], pubkeyBytes) {
found = true
break
}
}
if found {
importedRemoteKeysStatuses[i] = &ethpbservice.ImportedRemoteKeysStatus{
Status: ethpbservice.ImportedRemoteKeysStatus_DUPLICATE,
Message: fmt.Sprintf("Duplicate pubkey: %v, already in use", hexutil.Encode(pubKey[:])),
importedRemoteKeysStatuses[i] = &keymanager.KeyStatus{
Status: StatusDuplicate,
Message: fmt.Sprintf("Duplicate pubkey: %v, already in use", pubkey),
}
continue
}
km.providedPublicKeys = append(km.providedPublicKeys, pubKey)
importedRemoteKeysStatuses[i] = &ethpbservice.ImportedRemoteKeysStatus{
Status: ethpbservice.ImportedRemoteKeysStatus_IMPORTED,
Message: fmt.Sprintf("Successfully added pubkey: %v", hexutil.Encode(pubKey[:])),
km.providedPublicKeys = append(km.providedPublicKeys, bytesutil.ToBytes48(pubkeyBytes))
importedRemoteKeysStatuses[i] = &keymanager.KeyStatus{
Status: StatusImported,
Message: fmt.Sprintf("Successfully added pubkey: %v", pubkey),
}
log.Debug("Added pubkey to keymanager for web3signer", "pubkey", hexutil.Encode(pubKey[:]))
log.Debug("Added pubkey to keymanager for web3signer", "pubkey", pubkey)
}
km.accountsChangedFeed.Send(km.providedPublicKeys)
return importedRemoteKeysStatuses, nil
return importedRemoteKeysStatuses
}
// DeletePublicKeys removes a list of public keys from the keymanager for web3signer use. Returns status with message.
func (km *Keymanager) DeletePublicKeys(ctx context.Context, pubKeys [][fieldparams.BLSPubkeyLength]byte) ([]*ethpbservice.DeletedRemoteKeysStatus, error) {
if ctx == nil {
return nil, errors.New("context is nil")
}
deletedRemoteKeysStatuses := make([]*ethpbservice.DeletedRemoteKeysStatus, len(pubKeys))
func (km *Keymanager) DeletePublicKeys(pubKeys []string) []*keymanager.KeyStatus {
deletedRemoteKeysStatuses := make([]*keymanager.KeyStatus, len(pubKeys))
if len(km.providedPublicKeys) == 0 {
for i := range deletedRemoteKeysStatuses {
deletedRemoteKeysStatuses[i] = &ethpbservice.DeletedRemoteKeysStatus{
Status: ethpbservice.DeletedRemoteKeysStatus_NOT_FOUND,
deletedRemoteKeysStatuses[i] = &keymanager.KeyStatus{
Status: StatusNotFound,
Message: "No pubkeys are set in validator",
}
}
return deletedRemoteKeysStatuses, nil
return deletedRemoteKeysStatuses
}
for i, pubkey := range pubKeys {
for in, key := range km.providedPublicKeys {
if bytes.Equal(key[:], pubkey[:]) {
km.providedPublicKeys = append(km.providedPublicKeys[:in], km.providedPublicKeys[in+1:]...)
deletedRemoteKeysStatuses[i] = &ethpbservice.DeletedRemoteKeysStatus{
Status: ethpbservice.DeletedRemoteKeysStatus_DELETED,
Message: fmt.Sprintf("Successfully deleted pubkey: %v", hexutil.Encode(pubkey[:])),
pubkeyBytes, err := hexutil.Decode(pubkey)
if err != nil {
deletedRemoteKeysStatuses[i] = &keymanager.KeyStatus{
Status: StatusError,
Message: err.Error(),
}
log.Debug("Deleted pubkey from keymanager for web3signer", "pubkey", hexutil.Encode(pubkey[:]))
continue
}
if len(pubkeyBytes) != fieldparams.BLSPubkeyLength {
deletedRemoteKeysStatuses[i] = &keymanager.KeyStatus{
Status: StatusError,
Message: fmt.Sprintf("pubkey byte length (%d) did not match bls pubkey byte length (%d)", len(pubkeyBytes), fieldparams.BLSPubkeyLength),
}
continue
}
if bytes.Equal(key[:], pubkeyBytes) {
km.providedPublicKeys = append(km.providedPublicKeys[:in], km.providedPublicKeys[in+1:]...)
deletedRemoteKeysStatuses[i] = &keymanager.KeyStatus{
Status: StatusDeleted,
Message: fmt.Sprintf("Successfully deleted pubkey: %v", pubkey),
}
log.Debug("Deleted pubkey from keymanager for web3signer", "pubkey", pubkey)
break
}
}
if deletedRemoteKeysStatuses[i] == nil {
deletedRemoteKeysStatuses[i] = &ethpbservice.DeletedRemoteKeysStatus{
Status: ethpbservice.DeletedRemoteKeysStatus_NOT_FOUND,
Message: fmt.Sprintf("Pubkey: %v not found", hexutil.Encode(pubkey[:])),
deletedRemoteKeysStatuses[i] = &keymanager.KeyStatus{
Status: StatusNotFound,
Message: fmt.Sprintf("Pubkey: %v not found", pubkey),
}
}
}
km.accountsChangedFeed.Send(km.providedPublicKeys)
return deletedRemoteKeysStatuses, nil
return deletedRemoteKeysStatuses
}

View File

@@ -8,10 +8,8 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common/hexutil"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
ethpbservice "github.com/prysmaticlabs/prysm/v4/proto/eth/service"
validatorpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1/validator-client"
"github.com/prysmaticlabs/prysm/v4/testing/require"
"github.com/prysmaticlabs/prysm/v4/validator/keymanager/remote-web3signer/internal"
@@ -299,20 +297,14 @@ func TestKeymanager_AddPublicKeys(t *testing.T) {
if err != nil {
fmt.Printf("error: %v", err)
}
pubkey, err := hexutil.Decode("0xa2b5aaad9c6efefe7bb9b1243a043404f3362937cfb6b31833929833173f476630ea2cfeb0d9ddf15f97ca8685948820")
require.NoError(t, err)
publicKeys := [][fieldparams.BLSPubkeyLength]byte{
bytesutil.ToBytes48(pubkey),
}
statuses, err := km.AddPublicKeys(ctx, publicKeys)
require.NoError(t, err)
publicKeys := []string{"0xa2b5aaad9c6efefe7bb9b1243a043404f3362937cfb6b31833929833173f476630ea2cfeb0d9ddf15f97ca8685948820"}
statuses := km.AddPublicKeys(publicKeys)
for _, status := range statuses {
require.Equal(t, ethpbservice.ImportedRemoteKeysStatus_IMPORTED, status.Status)
require.Equal(t, StatusImported, status.Status)
}
statuses, err = km.AddPublicKeys(ctx, publicKeys)
require.NoError(t, err)
statuses = km.AddPublicKeys(publicKeys)
for _, status := range statuses {
require.Equal(t, ethpbservice.ImportedRemoteKeysStatus_DUPLICATE, status.Status)
require.Equal(t, StatusDuplicate, status.Status)
}
}
@@ -330,26 +322,19 @@ func TestKeymanager_DeletePublicKeys(t *testing.T) {
if err != nil {
fmt.Printf("error: %v", err)
}
pubkey, err := hexutil.Decode("0xa2b5aaad9c6efefe7bb9b1243a043404f3362937cfb6b31833929833173f476630ea2cfeb0d9ddf15f97ca8685948820")
require.NoError(t, err)
publicKeys := [][fieldparams.BLSPubkeyLength]byte{
bytesutil.ToBytes48(pubkey),
}
statuses, err := km.AddPublicKeys(ctx, publicKeys)
require.NoError(t, err)
publicKeys := []string{"0xa2b5aaad9c6efefe7bb9b1243a043404f3362937cfb6b31833929833173f476630ea2cfeb0d9ddf15f97ca8685948820"}
statuses := km.AddPublicKeys(publicKeys)
for _, status := range statuses {
require.Equal(t, ethpbservice.ImportedRemoteKeysStatus_IMPORTED, status.Status)
require.Equal(t, StatusImported, status.Status)
}
s, err := km.DeletePublicKeys(ctx, publicKeys)
require.NoError(t, err)
s := km.DeletePublicKeys(publicKeys)
for _, status := range s {
require.Equal(t, ethpbservice.DeletedRemoteKeysStatus_DELETED, status.Status)
require.Equal(t, StatusDeleted, status.Status)
}
s, err = km.DeletePublicKeys(ctx, publicKeys)
require.NoError(t, err)
s = km.DeletePublicKeys(publicKeys)
for _, status := range s {
require.Equal(t, ethpbservice.DeletedRemoteKeysStatus_NOT_FOUND, status.Status)
require.Equal(t, StatusNotFound, status.Status)
}
}

View File

@@ -62,12 +62,18 @@ type KeyStoreExtractor interface {
// PublicKeyAdder allows adding public keys to the keymanager.
type PublicKeyAdder interface {
AddPublicKeys(ctx context.Context, publicKeys [][fieldparams.BLSPubkeyLength]byte) ([]*ethpbservice.ImportedRemoteKeysStatus, error)
AddPublicKeys(publicKeys []string) []*KeyStatus
}
// KeyStatus is a json representation of the status fields for the keymanager apis
type KeyStatus struct {
Status string `json:"status"`
Message string `json:"message"`
}
// PublicKeyDeleter allows deleting public keys set in keymanager.
type PublicKeyDeleter interface {
DeletePublicKeys(ctx context.Context, publicKeys [][fieldparams.BLSPubkeyLength]byte) ([]*ethpbservice.DeletedRemoteKeysStatus, error)
DeletePublicKeys(publicKeys []string) []*KeyStatus
}
type ListKeymanagerAccountConfig struct {