github.com/Finschia/finschia-sdk@v0.48.1/client/rpc/validators.go (about)

     1  package rpc
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strconv"
     7  	"strings"
     8  
     9  	octypes "github.com/Finschia/ostracon/types"
    10  	"github.com/spf13/cobra"
    11  
    12  	"github.com/Finschia/finschia-sdk/client"
    13  	"github.com/Finschia/finschia-sdk/client/flags"
    14  	cryptocodec "github.com/Finschia/finschia-sdk/crypto/codec"
    15  	cryptotypes "github.com/Finschia/finschia-sdk/crypto/types"
    16  	sdk "github.com/Finschia/finschia-sdk/types"
    17  	"github.com/Finschia/finschia-sdk/types/query"
    18  )
    19  
    20  // TODO these next two functions feel kinda hacky based on their placement
    21  
    22  // ValidatorCommand returns the validator set for a given height
    23  func ValidatorCommand() *cobra.Command {
    24  	cmd := &cobra.Command{
    25  		Use:   "ostracon-validator-set [height]",
    26  		Short: "Get the full ostracon validator set at given height",
    27  		Args:  cobra.MaximumNArgs(1),
    28  		RunE: func(cmd *cobra.Command, args []string) error {
    29  			clientCtx, err := client.GetClientQueryContext(cmd)
    30  			if err != nil {
    31  				return err
    32  			}
    33  			var height *int64
    34  
    35  			// optional height
    36  			if len(args) > 0 {
    37  				h, err := strconv.Atoi(args[0])
    38  				if err != nil {
    39  					return err
    40  				}
    41  				if h > 0 {
    42  					tmp := int64(h)
    43  					height = &tmp
    44  				}
    45  			}
    46  
    47  			page, _ := cmd.Flags().GetInt(flags.FlagPage)
    48  			limit, _ := cmd.Flags().GetInt(flags.FlagLimit)
    49  
    50  			result, err := GetValidators(cmd.Context(), clientCtx, height, &page, &limit)
    51  			if err != nil {
    52  				return err
    53  			}
    54  
    55  			return clientCtx.PrintObjectLegacy(result)
    56  		},
    57  	}
    58  
    59  	cmd.Flags().StringP(flags.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
    60  	cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)")
    61  	cmd.Flags().Int(flags.FlagPage, query.DefaultPage, "Query a specific page of paginated results")
    62  	cmd.Flags().Int(flags.FlagLimit, 100, "Query number of results returned per page")
    63  
    64  	return cmd
    65  }
    66  
    67  // Validator output
    68  type ValidatorOutput struct {
    69  	Address          sdk.ConsAddress    `json:"address"`
    70  	PubKey           cryptotypes.PubKey `json:"pub_key"`
    71  	ProposerPriority int64              `json:"proposer_priority"`
    72  	VotingPower      int64              `json:"voting_power"`
    73  }
    74  
    75  // Validators at a certain height output in bech32 format
    76  type ResultValidatorsOutput struct {
    77  	BlockHeight int64             `json:"block_height"`
    78  	Validators  []ValidatorOutput `json:"validators"`
    79  	Total       uint64            `json:"total"`
    80  }
    81  
    82  func (rvo ResultValidatorsOutput) String() string {
    83  	var b strings.Builder
    84  
    85  	b.WriteString(fmt.Sprintf("block height: %d\n", rvo.BlockHeight))
    86  	b.WriteString(fmt.Sprintf("total count: %d\n", rvo.Total))
    87  
    88  	for _, val := range rvo.Validators {
    89  		b.WriteString(
    90  			fmt.Sprintf(`
    91    Address:          %s
    92    Pubkey:           %s
    93    ProposerPriority: %d
    94    VotingPower:      %d
    95  		`,
    96  				val.Address, val.PubKey, val.ProposerPriority, val.VotingPower,
    97  			),
    98  		)
    99  	}
   100  
   101  	return b.String()
   102  }
   103  
   104  func validatorOutput(validator *octypes.Validator) (ValidatorOutput, error) {
   105  	pk, err := cryptocodec.FromOcPubKeyInterface(validator.PubKey)
   106  	if err != nil {
   107  		return ValidatorOutput{}, err
   108  	}
   109  
   110  	return ValidatorOutput{
   111  		Address:          sdk.ConsAddress(validator.Address),
   112  		PubKey:           pk,
   113  		ProposerPriority: validator.ProposerPriority,
   114  		VotingPower:      validator.VotingPower,
   115  	}, nil
   116  }
   117  
   118  // GetValidators from client
   119  func GetValidators(ctx context.Context, clientCtx client.Context, height *int64, page, limit *int) (ResultValidatorsOutput, error) {
   120  	// get the node
   121  	node, err := clientCtx.GetNode()
   122  	if err != nil {
   123  		return ResultValidatorsOutput{}, err
   124  	}
   125  
   126  	validatorsRes, err := node.Validators(ctx, height, page, limit)
   127  	if err != nil {
   128  		return ResultValidatorsOutput{}, err
   129  	}
   130  
   131  	total := validatorsRes.Total
   132  	if validatorsRes.Total < 0 {
   133  		total = 0
   134  	}
   135  	out := ResultValidatorsOutput{
   136  		BlockHeight: validatorsRes.BlockHeight,
   137  		Validators:  make([]ValidatorOutput, len(validatorsRes.Validators)),
   138  		Total:       uint64(total),
   139  	}
   140  	for i := 0; i < len(validatorsRes.Validators); i++ {
   141  		out.Validators[i], err = validatorOutput(validatorsRes.Validators[i])
   142  		if err != nil {
   143  			return out, err
   144  		}
   145  	}
   146  
   147  	return out, nil
   148  }