Skip to content
This repository was archived by the owner on Dec 16, 2025. It is now read-only.
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions plugin/evm/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"golang.org/x/exp/slog"

"github.com/ava-labs/avalanchego/api"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/rpc"
)

Expand All @@ -24,7 +25,7 @@ type Client interface {
LockProfile(ctx context.Context, options ...rpc.Option) error
SetLogLevel(ctx context.Context, level slog.Level, options ...rpc.Option) error
GetVMConfig(ctx context.Context, options ...rpc.Option) (*Config, error)
GetCurrentValidators(ctx context.Context, options ...rpc.Option) ([]CurrentValidator, error)
GetCurrentValidators(ctx context.Context, nodeIDs []ids.NodeID, options ...rpc.Option) ([]CurrentValidator, error)
}

// Client implementation for interacting with EVM [chain]
Expand Down Expand Up @@ -77,8 +78,10 @@ func (c *client) GetVMConfig(ctx context.Context, options ...rpc.Option) (*Confi
}

// GetCurrentValidators returns the current validators
func (c *client) GetCurrentValidators(ctx context.Context, options ...rpc.Option) ([]CurrentValidator, error) {
func (c *client) GetCurrentValidators(ctx context.Context, nodeIDs []ids.NodeID, options ...rpc.Option) ([]CurrentValidator, error) {
res := &GetCurrentValidatorsResponse{}
err := c.validatorsRequester.SendRequest(ctx, "validators.getCurrentValidators", struct{}{}, res, options...)
err := c.validatorsRequester.SendRequest(ctx, "validators.getCurrentValidators", &GetCurrentValidatorsRequest{
NodeIDs: nodeIDs,
}, res, options...)
return res.Validators, err
}
72 changes: 52 additions & 20 deletions plugin/evm/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,61 +4,93 @@
package evm

import (
"fmt"
"net/http"
"time"

"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/set"
)

type ValidatorsAPI struct {
vm *VM
}

type GetCurrentValidatorsRequest struct {
NodeIDs []ids.NodeID `json:"nodeIDs"`
}

type GetCurrentValidatorsResponse struct {
Validators []CurrentValidator `json:"validators"`
}

type CurrentValidator struct {
ValidationID ids.ID `json:"validationID"`
NodeID ids.NodeID `json:"nodeID"`
Weight uint64 `json:"weight"`
StartTimestamp uint64 `json:"startTimestamp"`
IsActive bool `json:"isActive"`
IsL1Validator bool `json:"isL1Validator"`
IsConnected bool `json:"isConnected"`
Uptime time.Duration `json:"uptime"`
ValidationID ids.ID `json:"validationID"`
NodeID ids.NodeID `json:"nodeID"`
Weight uint64 `json:"weight"`
StartTimestamp uint64 `json:"startTimestamp"`
IsActive bool `json:"isActive"`
IsL1Validator bool `json:"isL1Validator"`
IsConnected bool `json:"isConnected"`
UptimePercentage float32 `json:"uptimePercentage"`
UptimeSeconds uint64 `json:"uptimeSeconds"`
}

func (api *ValidatorsAPI) GetCurrentValidators(_ *http.Request, _ *struct{}, reply *GetCurrentValidatorsResponse) error {
func (api *ValidatorsAPI) GetCurrentValidators(_ *http.Request, req *GetCurrentValidatorsRequest, reply *GetCurrentValidatorsResponse) error {
api.vm.ctx.Lock.RLock()
defer api.vm.ctx.Lock.RUnlock()

vIDs := api.vm.validatorsManager.GetValidationIDs()
var vIDs set.Set[ids.ID]
if len(req.NodeIDs) > 0 {
vIDs = set.NewSet[ids.ID](len(req.NodeIDs))
for _, nodeID := range req.NodeIDs {
vID, err := api.vm.validatorsManager.GetValidationID(nodeID)
if err != nil {
return fmt.Errorf("couldn't find validator with node ID %s", nodeID)
}
vIDs.Add(vID)
}
} else {
vIDs = api.vm.validatorsManager.GetValidationIDs()
}

reply.Validators = make([]CurrentValidator, 0, vIDs.Len())

for _, vID := range vIDs.List() {
validator, err := api.vm.validatorsManager.GetValidator(vID)
if err != nil {
return err
return fmt.Errorf("couldn't find validator with validation ID %s", vID)
}

isConnected := api.vm.validatorsManager.IsConnected(validator.NodeID)

uptime, _, err := api.vm.validatorsManager.CalculateUptime(validator.NodeID)
upDuration, lastUpdated, err := api.vm.validatorsManager.CalculateUptime(validator.NodeID)
if err != nil {
return err
}
var uptimeFloat float64
startTime := time.Unix(int64(validator.StartTimestamp), 0)
bestPossibleUpDuration := lastUpdated.Sub(startTime)
if bestPossibleUpDuration == 0 {
uptimeFloat = 1
} else {
uptimeFloat = float64(upDuration) / float64(bestPossibleUpDuration)
}

// Transform this to a percentage (0-100) to make it consistent
// with currentValidators in PlatformVM API
uptimePercentage := float32(uptimeFloat * 100)

reply.Validators = append(reply.Validators, CurrentValidator{
ValidationID: validator.ValidationID,
NodeID: validator.NodeID,
StartTimestamp: validator.StartTimestamp,
Weight: validator.Weight,
IsActive: validator.IsActive,
IsL1Validator: validator.IsL1Validator,
IsConnected: isConnected,
Uptime: time.Duration(uptime.Seconds()),
ValidationID: validator.ValidationID,
NodeID: validator.NodeID,
StartTimestamp: validator.StartTimestamp,
Weight: validator.Weight,
IsActive: validator.IsActive,
IsL1Validator: validator.IsL1Validator,
IsConnected: isConnected,
UptimePercentage: uptimePercentage,
UptimeSeconds: uint64(upDuration.Seconds()),
})
}
return nil
Expand Down
2 changes: 2 additions & 0 deletions plugin/evm/validators/state/interfaces/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ type StateReader interface {
GetValidationIDs() set.Set[ids.ID]
// GetNodeIDs returns the validator node IDs in the state
GetNodeIDs() set.Set[ids.NodeID]
// GetValidationID returns the validation ID for the given node ID
GetValidationID(nodeID ids.NodeID) (ids.ID, error)
}

type State interface {
Expand Down
9 changes: 9 additions & 0 deletions plugin/evm/validators/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,15 @@ func (s *state) GetNodeIDs() set.Set[ids.NodeID] {
return ids
}

// GetValidationID returns the validation ID for the given nodeID
func (s *state) GetValidationID(nodeID ids.NodeID) (ids.ID, error) {
vID, exists := s.index[nodeID]
if !exists {
return ids.ID{}, database.ErrNotFound
}
return vID, nil
}

// GetValidator returns the validator data for the given validationID
func (s *state) GetValidator(vID ids.ID) (interfaces.Validator, error) {
data, ok := s.data[vID]
Expand Down
Loading