Skip to content

Commit

Permalink
Merge pull request #5943 from multiversx/loaded-keys
Browse files Browse the repository at this point in the history
New endpoint /node/loaded-keys
  • Loading branch information
gabi-vuls committed Feb 13, 2024
2 parents 9c4a906 + a5c3bca commit 452bf4b
Show file tree
Hide file tree
Showing 24 changed files with 311 additions and 8 deletions.
20 changes: 20 additions & 0 deletions api/groups/nodeGroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const (
bootstrapStatusPath = "/bootstrapstatus"
connectedPeersRatingsPath = "/connected-peers-ratings"
managedKeys = "/managed-keys"
loadedKeys = "/loaded-keys"
managedKeysCount = "/managed-keys/count"
eligibleManagedKeys = "/managed-keys/eligible"
waitingManagedKeys = "/managed-keys/waiting"
Expand All @@ -43,6 +44,7 @@ type nodeFacadeHandler interface {
GetConnectedPeersRatingsOnMainNetwork() (string, error)
GetManagedKeysCount() int
GetManagedKeys() []string
GetLoadedKeys() []string
GetEligibleManagedKeys() ([]string, error)
GetWaitingManagedKeys() ([]string, error)
IsInterfaceNil() bool
Expand Down Expand Up @@ -127,6 +129,11 @@ func NewNodeGroup(facade nodeFacadeHandler) (*nodeGroup, error) {
Method: http.MethodGet,
Handler: ng.managedKeys,
},
{
Path: loadedKeys,
Method: http.MethodGet,
Handler: ng.loadedKeys,
},
{
Path: eligibleManagedKeys,
Method: http.MethodGet,
Expand Down Expand Up @@ -404,6 +411,19 @@ func (ng *nodeGroup) managedKeys(c *gin.Context) {
)
}

// loadedKeys returns all keys loaded by the current node
func (ng *nodeGroup) loadedKeys(c *gin.Context) {
keys := ng.getFacade().GetLoadedKeys()
c.JSON(
http.StatusOK,
shared.GenericAPIResponse{
Data: gin.H{"loadedKeys": keys},
Error: "",
Code: shared.ReturnCodeSuccess,
},
)
}

// managedKeysEligible returns the node's eligible managed keys
func (ng *nodeGroup) managedKeysEligible(c *gin.Context) {
keys, err := ng.getFacade().GetEligibleManagedKeys()
Expand Down
38 changes: 38 additions & 0 deletions api/groups/nodeGroup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ type managedKeysResponse struct {
generalResponse
}

type loadedKeysResponse struct {
Data struct {
LoadedKeys []string `json:"loadedKeys"`
} `json:"data"`
generalResponse
}

type managedEligibleKeysResponse struct {
Data struct {
Keys []string `json:"eligibleKeys"`
Expand Down Expand Up @@ -733,6 +740,36 @@ func TestNodeGroup_ManagedKeys(t *testing.T) {
assert.Equal(t, providedKeys, response.Data.ManagedKeys)
}

func TestNodeGroup_LoadedKeys(t *testing.T) {
t.Parallel()

providedKeys := []string{
"pk1",
"pk2",
}
facade := mock.FacadeStub{
GetLoadedKeysCalled: func() []string {
return providedKeys
},
}

nodeGroup, err := groups.NewNodeGroup(&facade)
require.NoError(t, err)

ws := startWebServer(nodeGroup, "node", getNodeRoutesConfig())

req, _ := http.NewRequest("GET", "/node/loaded-keys", nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

response := &loadedKeysResponse{}
loadResponse(resp.Body, response)

assert.Equal(t, http.StatusOK, resp.Code)
assert.Equal(t, "", response.Error)
assert.Equal(t, providedKeys, response.Data.LoadedKeys)
}

func TestNodeGroup_ManagedKeysEligible(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -960,6 +997,7 @@ func getNodeRoutesConfig() config.ApiRoutesConfig {
{Name: "/connected-peers-ratings", Open: true},
{Name: "/managed-keys/count", Open: true},
{Name: "/managed-keys", Open: true},
{Name: "/loaded-keys", Open: true},
{Name: "/managed-keys/eligible", Open: true},
{Name: "/managed-keys/waiting", Open: true},
},
Expand Down
9 changes: 9 additions & 0 deletions api/mock/facadeStub.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ type FacadeStub struct {
IsDataTrieMigratedCalled func(address string, options api.AccountQueryOptions) (bool, error)
GetManagedKeysCountCalled func() int
GetManagedKeysCalled func() []string
GetLoadedKeysCalled func() []string
GetEligibleManagedKeysCalled func() ([]string, error)
GetWaitingManagedKeysCalled func() ([]string, error)
}
Expand Down Expand Up @@ -594,6 +595,14 @@ func (f *FacadeStub) GetManagedKeys() []string {
return make([]string, 0)
}

// GetLoadedKeys -
func (f *FacadeStub) GetLoadedKeys() []string {
if f.GetLoadedKeysCalled != nil {
return f.GetLoadedKeysCalled()
}
return make([]string, 0)
}

// GetEligibleManagedKeys -
func (f *FacadeStub) GetEligibleManagedKeys() ([]string, error) {
if f.GetEligibleManagedKeysCalled != nil {
Expand Down
1 change: 1 addition & 0 deletions api/shared/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ type FacadeHandler interface {
IsDataTrieMigrated(address string, options api.AccountQueryOptions) (bool, error)
GetManagedKeysCount() int
GetManagedKeys() []string
GetLoadedKeys() []string
GetEligibleManagedKeys() ([]string, error)
GetWaitingManagedKeys() ([]string, error)
IsInterfaceNil() bool
Expand Down
3 changes: 3 additions & 0 deletions cmd/node/config/api.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
# /node/managed-keys will return the keys managed by the node
{ Name = "/managed-keys", Open = true },

# /node/loaded-keys will return the keys loaded by the node
{ Name = "/loaded-keys", Open = true },

# /node/managed-keys/count will return the number of keys managed by the node
{ Name = "/managed-keys/count", Open = true },

Expand Down
2 changes: 2 additions & 0 deletions common/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ type ManagedPeersHolder interface {
IncrementRoundsWithoutReceivedMessages(pkBytes []byte)
ResetRoundsWithoutReceivedMessages(pkBytes []byte, pid core.PeerID)
GetManagedKeysByCurrentNode() map[string]crypto.PrivateKey
GetLoadedKeysByCurrentNode() [][]byte
IsKeyManagedByCurrentNode(pkBytes []byte) bool
IsKeyRegistered(pkBytes []byte) bool
IsPidManagedByCurrentNode(pid core.PeerID) bool
Expand Down Expand Up @@ -443,6 +444,7 @@ type StateSyncNotifierSubscriber interface {
type ManagedPeersMonitor interface {
GetManagedKeysCount() int
GetManagedKeys() [][]byte
GetLoadedKeys() [][]byte
GetEligibleManagedKeys() ([][]byte, error)
GetWaitingManagedKeys() ([][]byte, error)
IsInterfaceNil() bool
Expand Down
7 changes: 6 additions & 1 deletion facade/initial/initialNodeFacade.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func (inf *initialNodeFacade) SetSyncer(_ ntp.SyncTimer) {
}

// RestAPIServerDebugMode returns false
//TODO: remove in the future
// TODO: remove in the future
func (inf *initialNodeFacade) RestAPIServerDebugMode() bool {
return false
}
Expand Down Expand Up @@ -416,6 +416,11 @@ func (inf *initialNodeFacade) GetManagedKeys() []string {
return nil
}

// GetLoadedKeys returns nil
func (inf *initialNodeFacade) GetLoadedKeys() []string {
return nil
}

// GetEligibleManagedKeys returns nil and error
func (inf *initialNodeFacade) GetEligibleManagedKeys() ([]string, error) {
return nil, errNodeStarting
Expand Down
17 changes: 17 additions & 0 deletions facade/initial/initialNodeFacade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,23 @@ func TestInitialNodeFacade_AllMethodsShouldNotPanic(t *testing.T) {
assert.Nil(t, txPoolGaps)
assert.Equal(t, errNodeStarting, err)

count := inf.GetManagedKeysCount()
assert.Zero(t, count)

keys := inf.GetManagedKeys()
assert.Nil(t, keys)

keys = inf.GetLoadedKeys()
assert.Nil(t, keys)

keys, err = inf.GetEligibleManagedKeys()
assert.Nil(t, keys)
assert.Equal(t, errNodeStarting, err)

keys, err = inf.GetWaitingManagedKeys()
assert.Nil(t, keys)
assert.Equal(t, errNodeStarting, err)

assert.NotNil(t, inf)
}

Expand Down
1 change: 1 addition & 0 deletions facade/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ type ApiResolver interface {
GetGasConfigs() map[string]map[string]uint64
GetManagedKeysCount() int
GetManagedKeys() []string
GetLoadedKeys() []string
GetEligibleManagedKeys() ([]string, error)
GetWaitingManagedKeys() ([]string, error)
Close() error
Expand Down
9 changes: 9 additions & 0 deletions facade/mock/apiResolverStub.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type ApiResolverStub struct {
GetGasConfigsCalled func() map[string]map[string]uint64
GetManagedKeysCountCalled func() int
GetManagedKeysCalled func() []string
GetLoadedKeysCalled func() []string
GetEligibleManagedKeysCalled func() ([]string, error)
GetWaitingManagedKeysCalled func() ([]string, error)
}
Expand Down Expand Up @@ -308,6 +309,14 @@ func (ars *ApiResolverStub) GetManagedKeys() []string {
return make([]string, 0)
}

// GetLoadedKeys -
func (ars *ApiResolverStub) GetLoadedKeys() []string {
if ars.GetLoadedKeysCalled != nil {
return ars.GetLoadedKeysCalled()
}
return make([]string, 0)
}

// GetEligibleManagedKeys -
func (ars *ApiResolverStub) GetEligibleManagedKeys() ([]string, error) {
if ars.GetEligibleManagedKeysCalled != nil {
Expand Down
12 changes: 9 additions & 3 deletions facade/nodeFacade.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import (
const DefaultRestInterface = "localhost:8080"

// DefaultRestPortOff is the default value that should be passed if it is desired
// to start the node without a REST endpoint available
// to start the node without a REST endpoint available
const DefaultRestPortOff = "off"

var log = logger.GetOrCreate("facade")
Expand Down Expand Up @@ -163,7 +163,8 @@ func (nf *nodeFacade) RestAPIServerDebugMode() bool {

// RestApiInterface returns the interface on which the rest API should start on, based on the config file provided.
// The API will start on the DefaultRestInterface value unless a correct value is passed or
// the value is explicitly set to off, in which case it will not start at all
//
// the value is explicitly set to off, in which case it will not start at all
func (nf *nodeFacade) RestApiInterface() string {
if nf.config.RestApiInterface == "" {
return DefaultRestInterface
Expand Down Expand Up @@ -590,11 +591,16 @@ func (nf *nodeFacade) GetManagedKeysCount() int {
return nf.apiResolver.GetManagedKeysCount()
}

// GetManagedKeys returns all keys managed by the current node when running in multikey mode
// GetManagedKeys returns all keys that should act as validator(main or backup that took over) and will be managed by this node
func (nf *nodeFacade) GetManagedKeys() []string {
return nf.apiResolver.GetManagedKeys()
}

// GetLoadedKeys returns all keys that were loaded by this node
func (nf *nodeFacade) GetLoadedKeys() []string {
return nf.apiResolver.GetLoadedKeys()
}

// GetEligibleManagedKeys returns the eligible managed keys when node is running in multikey mode
func (nf *nodeFacade) GetEligibleManagedKeys() ([]string, error) {
return nf.apiResolver.GetEligibleManagedKeys()
Expand Down
46 changes: 46 additions & 0 deletions facade/nodeFacade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2225,6 +2225,52 @@ func TestNodeFacade_GetInternalStartOfEpochMetaBlock(t *testing.T) {
require.Equal(t, providedResponse, response)
}

func TestNodeFacade_GetManagedKeys(t *testing.T) {
t.Parallel()

providedCount := 100
providedManagedKeys := []string{"pk1", "pk2"}
providedLoadedKeys := []string{"pk3", "pk4"}
providedEligibleKeys := []string{"pk5", "pk6"}
providedWaitingKeys := []string{"pk7", "pk8"}
arg := createMockArguments()
arg.ApiResolver = &mock.ApiResolverStub{
GetManagedKeysCountCalled: func() int {
return providedCount
},
GetManagedKeysCalled: func() []string {
return providedManagedKeys
},
GetLoadedKeysCalled: func() []string {
return providedLoadedKeys
},
GetEligibleManagedKeysCalled: func() ([]string, error) {
return providedEligibleKeys, nil
},
GetWaitingManagedKeysCalled: func() ([]string, error) {
return providedWaitingKeys, nil
},
}
nf, _ := NewNodeFacade(arg)

count := nf.GetManagedKeysCount()
require.Equal(t, providedCount, count)

keys := nf.GetManagedKeys()
require.Equal(t, providedManagedKeys, keys)

keys = nf.GetLoadedKeys()
require.Equal(t, providedLoadedKeys, keys)

keys, err := nf.GetEligibleManagedKeys()
require.Equal(t, providedEligibleKeys, keys)
require.Nil(t, err)

keys, err = nf.GetWaitingManagedKeys()
require.Equal(t, providedWaitingKeys, keys)
require.Nil(t, err)
}

func TestNodeFacade_Close(t *testing.T) {
t.Parallel()

Expand Down
1 change: 1 addition & 0 deletions factory/api/apiResolverFactory.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ func CreateApiResolver(args *ApiResolverArgs) (facade.ApiResolver, error) {
AccountsParser: args.ProcessComponents.AccountsParser(),
GasScheduleNotifier: args.GasScheduleNotifier,
ManagedPeersMonitor: args.StatusComponents.ManagedPeersMonitor(),
PublicKey: args.CryptoComponents.PublicKeyString(),
}

return external.NewNodeApiResolver(argsApiResolver)
Expand Down
1 change: 1 addition & 0 deletions heartbeat/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ type ManagedPeersHolder interface {
IncrementRoundsWithoutReceivedMessages(pkBytes []byte)
ResetRoundsWithoutReceivedMessages(pkBytes []byte, pid core.PeerID)
GetManagedKeysByCurrentNode() map[string]crypto.PrivateKey
GetLoadedKeysByCurrentNode() [][]byte
IsKeyManagedByCurrentNode(pkBytes []byte) bool
IsKeyRegistered(pkBytes []byte) bool
IsPidManagedByCurrentNode(pid core.PeerID) bool
Expand Down
1 change: 1 addition & 0 deletions integrationTests/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ type Facade interface {
IsDataTrieMigrated(address string, options api.AccountQueryOptions) (bool, error)
GetManagedKeysCount() int
GetManagedKeys() []string
GetLoadedKeys() []string
GetEligibleManagedKeys() ([]string, error)
GetWaitingManagedKeys() ([]string, error)
IsInterfaceNil() bool
Expand Down
2 changes: 1 addition & 1 deletion integrationTests/testProcessorNodeWithTestWebServer.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func createFacadeArg(tpn *TestProcessorNode) nodeFacade.ArgNodeFacade {

func createTestApiConfig() config.ApiRoutesConfig {
routes := map[string][]string{
"node": {"/status", "/metrics", "/heartbeatstatus", "/statistics", "/p2pstatus", "/debug", "/peerinfo", "/bootstrapstatus", "/connected-peers-ratings", "/managed-keys/count", "/managed-keys", "/managed-keys/eligible", "/managed-keys/waiting"},
"node": {"/status", "/metrics", "/heartbeatstatus", "/statistics", "/p2pstatus", "/debug", "/peerinfo", "/bootstrapstatus", "/connected-peers-ratings", "/managed-keys/count", "/managed-keys", "/loaded-keys", "/managed-keys/eligible", "/managed-keys/waiting"},
"address": {"/:address", "/:address/balance", "/:address/username", "/:address/code-hash", "/:address/key/:key", "/:address/esdt", "/:address/esdt/:tokenIdentifier"},
"hardfork": {"/trigger"},
"network": {"/status", "/total-staked", "/economics", "/config"},
Expand Down

0 comments on commit 452bf4b

Please sign in to comment.