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 }