github.com/prysmaticlabs/prysm@v1.4.4/endtoend/evaluators/api.go (about)

     1  package evaluators
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"net/http"
     8  	"time"
     9  
    10  	"github.com/pkg/errors"
    11  	e2e "github.com/prysmaticlabs/prysm/endtoend/params"
    12  	"github.com/prysmaticlabs/prysm/endtoend/policies"
    13  	e2etypes "github.com/prysmaticlabs/prysm/endtoend/types"
    14  	"google.golang.org/grpc"
    15  )
    16  
    17  type stateValidatorsResponseJson struct {
    18  	Data []*validatorContainerJson `json:"data"`
    19  }
    20  
    21  type validatorContainerJson struct {
    22  	Index     string         `json:"index"`
    23  	Balance   string         `json:"balance"`
    24  	Status    string         `json:"status"`
    25  	Validator *validatorJson `json:"validator"`
    26  }
    27  
    28  type validatorJson struct {
    29  	PublicKey                  string `json:"pubkey"`
    30  	WithdrawalCredentials      string `json:"withdrawal_credentials"`
    31  	EffectiveBalance           string `json:"effective_balance"`
    32  	Slashed                    bool   `json:"slashed"`
    33  	ActivationEligibilityEpoch string `json:"activation_eligibility_epoch"`
    34  	ActivationEpoch            string `json:"activation_epoch"`
    35  	ExitEpoch                  string `json:"exit_epoch"`
    36  	WithdrawableEpoch          string `json:"withdrawable_epoch"`
    37  }
    38  
    39  // ApiVerifyValidators ensures the Ethereum API returns correct validator data.
    40  var ApiVerifyValidators = e2etypes.Evaluator{
    41  	Name:       "api_verify_validators_epoch_%d",
    42  	Policy:     policies.OnEpoch(1),
    43  	Evaluation: apiVerifyValidators,
    44  }
    45  
    46  func apiVerifyValidators(conns ...*grpc.ClientConn) error {
    47  	count := len(conns)
    48  	for i := 0; i < count; i++ {
    49  		resp, err := http.Get(
    50  			fmt.Sprintf("http://localhost:%d/eth/v1/beacon/states/head/validators?status=exited", e2e.TestParams.BeaconNodeRPCPort+i+30),
    51  		)
    52  		if err != nil {
    53  			// Continue if the connection fails, regular flake.
    54  			continue
    55  		}
    56  		if resp.StatusCode != http.StatusOK {
    57  			body, err := ioutil.ReadAll(resp.Body)
    58  			if err != nil {
    59  				return err
    60  			}
    61  			return fmt.Errorf("expected status code OK for beacon node %d, received %v with body %s", i, resp.StatusCode, body)
    62  		}
    63  		validators := &stateValidatorsResponseJson{}
    64  		if err = json.NewDecoder(resp.Body).Decode(&validators); err != nil {
    65  			return err
    66  		}
    67  		if len(validators.Data) != 0 {
    68  			return fmt.Errorf("expected no exited validators to be returned from the API request for beacon node %d", i)
    69  		}
    70  		resp, err = http.Get(
    71  			fmt.Sprintf("http://localhost:%d/eth/v1/beacon/states/head/validators?id=100&id=200", e2e.TestParams.BeaconNodeRPCPort+i+30),
    72  		)
    73  		if err != nil {
    74  			// Continue if the connection fails, regular flake.
    75  			continue
    76  		}
    77  		if resp.StatusCode != http.StatusOK {
    78  			body, err := ioutil.ReadAll(resp.Body)
    79  			if err != nil {
    80  				return err
    81  			}
    82  			return fmt.Errorf("expected status code OK for beacon node %d, received %v with body %s", i, resp.StatusCode, body)
    83  		}
    84  		validators = &stateValidatorsResponseJson{}
    85  		if err = json.NewDecoder(resp.Body).Decode(&validators); err != nil {
    86  			return err
    87  		}
    88  		if len(validators.Data) != 2 {
    89  			return fmt.Errorf("expected 2 validators to be returned from the API request for beacon node %d", i)
    90  		}
    91  		if err = assertValidator(validators.Data[0]); err != nil {
    92  			return errors.Wrapf(err, "incorrect validator data returned from the API request for beacon node %d", i)
    93  		}
    94  		if err = assertValidator(validators.Data[1]); err != nil {
    95  			return errors.Wrapf(err, "incorrect validator data returned from the API request for beacon node %d", i)
    96  		}
    97  
    98  		if err = resp.Body.Close(); err != nil {
    99  			return err
   100  		}
   101  		time.Sleep(connTimeDelay)
   102  	}
   103  	return nil
   104  }
   105  
   106  func assertValidator(v *validatorContainerJson) error {
   107  	if v == nil {
   108  		return errors.New("validator is nil")
   109  	}
   110  	if v.Index != "100" && v.Index != "200" {
   111  		return fmt.Errorf("unexpected validator index '%s'", v.Index)
   112  	}
   113  
   114  	valid := false
   115  	var field, expected, actual string
   116  
   117  	switch v.Index {
   118  	case "100":
   119  		if v.Balance != "32000000000" {
   120  			field = "Balance"
   121  			expected = "32000000000"
   122  			actual = v.Balance
   123  			break
   124  		}
   125  		if v.Status != "active_ongoing" {
   126  			field = "Status"
   127  			expected = "active_ongoing"
   128  			actual = v.Status
   129  			break
   130  		}
   131  		if v.Validator == nil {
   132  			return errors.New("validator is nil")
   133  		}
   134  		if v.Validator.PublicKey != "0x8931cd39ec3133b6ec91f26eec4de555cd7966086b1993dfe69c2b16e80adc62ce82d353b3356d8cc249e4e2d4254122" {
   135  			field = "PublicKey"
   136  			expected = "0x8931cd39ec3133b6ec91f26eec4de555cd7966086b1993dfe69c2b16e80adc62ce82d353b3356d8cc249e4e2d4254122"
   137  			actual = v.Validator.PublicKey
   138  			break
   139  		}
   140  		if v.Validator.WithdrawalCredentials != "0x00b5a389a138ec5069e430a91ec2884660fbb77a4bffdefd03f5e5769c2ba1a9" {
   141  			field = "WithdrawalCredentials"
   142  			expected = "0x00b5a389a138ec5069e430a91ec2884660fbb77a4bffdefd03f5e5769c2ba1a9"
   143  			actual = v.Validator.WithdrawalCredentials
   144  			break
   145  		}
   146  		if v.Validator.EffectiveBalance != "32000000000" {
   147  			field = "EffectiveBalance"
   148  			expected = "32000000000"
   149  			actual = v.Validator.EffectiveBalance
   150  			break
   151  		}
   152  		if v.Validator.Slashed {
   153  			field = "Slashed"
   154  			expected = "32000000000"
   155  			actual = "true"
   156  			break
   157  		}
   158  		if v.Validator.ActivationEligibilityEpoch != "0" {
   159  			field = "ActivationEligibilityEpoch"
   160  			expected = "0"
   161  			actual = v.Validator.ActivationEligibilityEpoch
   162  			break
   163  		}
   164  		if v.Validator.ActivationEpoch != "0" {
   165  			field = "ActivationEpoch"
   166  			expected = "0"
   167  			actual = v.Validator.ActivationEpoch
   168  			break
   169  		}
   170  		if v.Validator.ExitEpoch != "18446744073709551615" {
   171  			field = "ExitEpoch"
   172  			expected = "18446744073709551615"
   173  			actual = v.Validator.ExitEpoch
   174  			break
   175  		}
   176  		if v.Validator.WithdrawableEpoch != "18446744073709551615" {
   177  			field = "WithdrawableEpoch"
   178  			expected = "18446744073709551615"
   179  			actual = v.Validator.WithdrawableEpoch
   180  			break
   181  		}
   182  		valid = true
   183  	case "200":
   184  		if v.Balance != "32000000000" {
   185  			field = "Balance"
   186  			expected = "32000000000"
   187  			actual = v.Balance
   188  			break
   189  		}
   190  		if v.Status != "active_ongoing" {
   191  			field = "Status"
   192  			expected = "active_ongoing"
   193  			actual = v.Status
   194  			break
   195  		}
   196  		if v.Validator == nil {
   197  			return errors.New("validator is nil")
   198  		}
   199  		if v.Validator.PublicKey != "0x8b4ff71ee947785f545c017bbb9ce84c3f6a90097368cf79663b2e11acc53e18e8f7159919784f4d28282cb39a7113f7" {
   200  			field = "PublicKey"
   201  			expected = "0x8b4ff71ee947785f545c017bbb9ce84c3f6a90097368cf79663b2e11acc53e18e8f7159919784f4d28282cb39a7113f7"
   202  			actual = v.Validator.PublicKey
   203  			break
   204  		}
   205  		if v.Validator.WithdrawalCredentials != "0x00b9ea0e53f64def81fe2e783a8bb02e57fb519f56a7224f93f2d37e1572417d" {
   206  			field = "WithdrawalCredentials"
   207  			expected = "0x00b9ea0e53f64def81fe2e783a8bb02e57fb519f56a7224f93f2d37e1572417d"
   208  			actual = v.Validator.WithdrawalCredentials
   209  			break
   210  		}
   211  		if v.Validator.EffectiveBalance != "32000000000" {
   212  			field = "EffectiveBalance"
   213  			expected = "32000000000"
   214  			actual = v.Validator.EffectiveBalance
   215  			break
   216  		}
   217  		if v.Validator.Slashed {
   218  			field = "Slashed"
   219  			expected = "32000000000"
   220  			actual = "true"
   221  			break
   222  		}
   223  		if v.Validator.ActivationEligibilityEpoch != "0" {
   224  			field = "ActivationEligibilityEpoch"
   225  			expected = "0"
   226  			actual = v.Validator.ActivationEligibilityEpoch
   227  			break
   228  		}
   229  		if v.Validator.ActivationEpoch != "0" {
   230  			field = "ActivationEpoch"
   231  			expected = "0"
   232  			actual = v.Validator.ActivationEpoch
   233  			break
   234  		}
   235  		if v.Validator.ExitEpoch != "18446744073709551615" {
   236  			field = "ExitEpoch"
   237  			expected = "18446744073709551615"
   238  			actual = v.Validator.ExitEpoch
   239  			break
   240  		}
   241  		if v.Validator.WithdrawableEpoch != "18446744073709551615" {
   242  			field = "WithdrawableEpoch"
   243  			expected = "18446744073709551615"
   244  			actual = v.Validator.WithdrawableEpoch
   245  			break
   246  		}
   247  		valid = true
   248  	}
   249  
   250  	if !valid {
   251  		return fmt.Errorf("value of '%s' was expected to be '%s' but was '%s'", field, expected, actual)
   252  	}
   253  	return nil
   254  }