mirror of
https://github.com/luxfi/cli.git
synced 2026-10-30 17:01:20 +00:00
162 lines
4.3 KiB
Go
162 lines
4.3 KiB
Go
// Copyright (C) 2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
package validator
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
"github.com/luxfi/cli/v2/pkg/contract"
|
|
"github.com/luxfi/cli/v2/sdk/network"
|
|
"github.com/luxfi/cli/v2/sdk/utils"
|
|
"github.com/luxfi/ids"
|
|
luxdjson "github.com/luxfi/node/v2/v2/utils/json"
|
|
"github.com/luxfi/node/v2/v2/utils/rpc"
|
|
"github.com/luxfi/node/v2/v2/vms/platformvm"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
)
|
|
|
|
type ValidatorKind int64
|
|
|
|
const (
|
|
UndefinedValidatorKind ValidatorKind = iota
|
|
NonValidator
|
|
SovereignValidator
|
|
NonSovereignValidator
|
|
)
|
|
|
|
// To enable querying validation IDs from P-Chain
|
|
type CurrentValidatorInfo struct {
|
|
Weight luxdjson.Uint64 `json:"weight"`
|
|
NodeID ids.NodeID `json:"nodeID"`
|
|
ValidationID ids.ID `json:"validationID"`
|
|
Balance luxdjson.Uint64 `json:"balance"`
|
|
}
|
|
|
|
func GetTotalWeight(network network.Network, subnetID ids.ID) (uint64, error) {
|
|
validators, err := GetCurrentValidators(network, subnetID)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
weight := uint64(0)
|
|
for _, vdr := range validators {
|
|
weight += uint64(vdr.Weight)
|
|
}
|
|
return weight, nil
|
|
}
|
|
|
|
func IsValidator(network network.Network, subnetID ids.ID, nodeID ids.NodeID) (bool, error) {
|
|
validators, err := GetCurrentValidators(network, subnetID)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
nodeIDs := utils.Map(validators, func(v CurrentValidatorInfo) ids.NodeID { return v.NodeID })
|
|
return utils.Belongs(nodeIDs, nodeID), nil
|
|
}
|
|
|
|
func GetValidatorBalance(net network.Network, validationID ids.ID) (uint64, error) {
|
|
vdrInfo, err := GetValidatorInfo(net, validationID)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return vdrInfo.Balance, nil
|
|
}
|
|
|
|
func GetValidatorInfo(net network.Network, validationID ids.ID) (platformvm.L1Validator, error) {
|
|
pClient := platformvm.NewClient(net.Endpoint)
|
|
ctx, cancel := utils.GetAPIContext()
|
|
defer cancel()
|
|
vdrInfo, _, err := pClient.GetL1Validator(ctx, validationID)
|
|
if err != nil {
|
|
return platformvm.L1Validator{}, err
|
|
}
|
|
return vdrInfo, nil
|
|
}
|
|
|
|
// Returns the validation ID for the Node ID, as registered at the validator manager
|
|
// Will return ids.Empty in case it is not registered
|
|
func GetValidationID(
|
|
rpcURL string,
|
|
managerAddress common.Address,
|
|
nodeID ids.NodeID,
|
|
) (ids.ID, error) {
|
|
// if specialized, need to retrieve underlying manager
|
|
// needs to directly access the manager, does not work with a proxy
|
|
out, err := contract.CallToMethod(
|
|
rpcURL,
|
|
managerAddress,
|
|
"getStakingManagerSettings()->(address,uint256,uint256,uint64,uint16,uint8,uint256,address,bytes32)",
|
|
)
|
|
if err == nil && len(out) == 9 {
|
|
validatorManager, ok := out[0].(common.Address)
|
|
if ok {
|
|
managerAddress = validatorManager
|
|
}
|
|
}
|
|
out, err = contract.CallToMethod(
|
|
rpcURL,
|
|
managerAddress,
|
|
"registeredValidators(bytes)->(bytes32)",
|
|
nodeID[:],
|
|
)
|
|
if err != nil {
|
|
return ids.Empty, err
|
|
}
|
|
return contract.GetSmartContractCallResult[[32]byte]("registeredValidators", out)
|
|
}
|
|
|
|
func GetValidatorKind(
|
|
network network.Network,
|
|
subnetID ids.ID,
|
|
nodeID ids.NodeID,
|
|
) (ValidatorKind, error) {
|
|
pClient := platformvm.NewClient(network.Endpoint)
|
|
ctx, cancel := utils.GetAPIContext()
|
|
defer cancel()
|
|
vs, err := pClient.GetCurrentValidators(ctx, subnetID, nil)
|
|
if err != nil {
|
|
return UndefinedValidatorKind, err
|
|
}
|
|
for _, v := range vs {
|
|
if v.NodeID == nodeID {
|
|
if v.TxID == ids.Empty {
|
|
return SovereignValidator, nil
|
|
}
|
|
return NonSovereignValidator, nil
|
|
}
|
|
}
|
|
return NonValidator, nil
|
|
}
|
|
|
|
// Enables querying the validation IDs from P-Chain
|
|
func GetCurrentValidators(network network.Network, subnetID ids.ID) ([]CurrentValidatorInfo, error) {
|
|
ctx, cancel := utils.GetAPIContext()
|
|
defer cancel()
|
|
requester := rpc.NewEndpointRequester(network.Endpoint + "/ext/P")
|
|
res := &platformvm.GetCurrentValidatorsReply{}
|
|
if err := requester.SendRequest(
|
|
ctx,
|
|
"platform.getCurrentValidators",
|
|
&platformvm.GetCurrentValidatorsArgs{
|
|
SubnetID: subnetID,
|
|
NodeIDs: nil,
|
|
},
|
|
res,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
validators := make([]CurrentValidatorInfo, 0, len(res.Validators))
|
|
for _, vI := range res.Validators {
|
|
vBytes, err := json.Marshal(vI)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var v CurrentValidatorInfo
|
|
if err := json.Unmarshal(vBytes, &v); err != nil {
|
|
return nil, err
|
|
}
|
|
validators = append(validators, v)
|
|
}
|
|
return validators, nil
|
|
}
|