Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New endpoint /node/loaded-keys #5943

Merged
merged 4 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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