mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-22 19:40:37 +00:00
POST version of GetValidators and GetValidatorBalances (#13199)
* POST versions of GetValidators and GetValidatorBalances * post statuses * balances test * group params * test error cases
This commit is contained in:
parent
8902ad3a20
commit
4b3c511a26
@ -1,7 +1,9 @@
|
||||
package beacon
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -49,7 +51,32 @@ func (s *Server) GetValidators(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
isFinalized := s.FinalizationFetcher.IsFinalized(ctx, blockRoot)
|
||||
|
||||
rawIds := r.URL.Query()["id"]
|
||||
var req GetValidatorsRequest
|
||||
if r.Method == http.MethodPost {
|
||||
err = json.NewDecoder(r.Body).Decode(&req)
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
http2.HandleError(w, "No data submitted", http.StatusBadRequest)
|
||||
return
|
||||
case err != nil:
|
||||
http2.HandleError(w, "Could not decode request body: "+err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var statuses []string
|
||||
var rawIds []string
|
||||
if r.Method == http.MethodGet {
|
||||
rawIds = r.URL.Query()["id"]
|
||||
statuses = r.URL.Query()["status"]
|
||||
} else {
|
||||
rawIds = req.Ids
|
||||
statuses = req.Statuses
|
||||
}
|
||||
for i, ss := range statuses {
|
||||
statuses[i] = strings.ToLower(ss)
|
||||
}
|
||||
|
||||
ids, ok := decodeIds(w, st, rawIds, true /* ignore unknown */)
|
||||
if !ok {
|
||||
return
|
||||
@ -72,11 +99,6 @@ func (s *Server) GetValidators(w http.ResponseWriter, r *http.Request) {
|
||||
epoch := slots.ToEpoch(st.Slot())
|
||||
allBalances := st.Balances()
|
||||
|
||||
statuses := r.URL.Query()["status"]
|
||||
for i, ss := range statuses {
|
||||
statuses[i] = strings.ToLower(ss)
|
||||
}
|
||||
|
||||
// Exit early if no matching validators were found or we don't want to further filter validators by status.
|
||||
if len(readOnlyVals) == 0 || len(statuses) == 0 {
|
||||
containers := make([]*ValidatorContainer, len(readOnlyVals))
|
||||
@ -234,7 +256,21 @@ func (bs *Server) GetValidatorBalances(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
isFinalized := bs.FinalizationFetcher.IsFinalized(ctx, blockRoot)
|
||||
|
||||
rawIds := r.URL.Query()["id"]
|
||||
var rawIds []string
|
||||
if r.Method == http.MethodGet {
|
||||
rawIds = r.URL.Query()["id"]
|
||||
} else {
|
||||
err = json.NewDecoder(r.Body).Decode(&rawIds)
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
http2.HandleError(w, "No data submitted", http.StatusBadRequest)
|
||||
return
|
||||
case err != nil:
|
||||
http2.HandleError(w, "Could not decode request body: "+err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ids, ok := decodeIds(w, st, rawIds, true /* ignore unknown */)
|
||||
if !ok {
|
||||
return
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@ -26,8 +27,12 @@ import (
|
||||
)
|
||||
|
||||
func TestGetValidators(t *testing.T) {
|
||||
const exitedValIndex = 3
|
||||
var st state.BeaconState
|
||||
st, _ = util.DeterministicGenesisState(t, 8192)
|
||||
st, _ = util.DeterministicGenesisState(t, 4)
|
||||
vals := st.Validators()
|
||||
vals[exitedValIndex].ExitEpoch = 0
|
||||
require.NoError(t, st.SetValidators(vals))
|
||||
|
||||
t.Run("get all", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{}
|
||||
@ -49,7 +54,7 @@ func TestGetValidators(t *testing.T) {
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
resp := &GetValidatorsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.Equal(t, 8192, len(resp.Data))
|
||||
require.Equal(t, 4, len(resp.Data))
|
||||
val := resp.Data[0]
|
||||
assert.Equal(t, "0", val.Index)
|
||||
assert.Equal(t, "32000000000", val.Balance)
|
||||
@ -77,7 +82,7 @@ func TestGetValidators(t *testing.T) {
|
||||
|
||||
request := httptest.NewRequest(
|
||||
http.MethodGet,
|
||||
"http://example.com/eth/v1/beacon/states/{state_id}/validators?id=15&id=26",
|
||||
"http://example.com/eth/v1/beacon/states/{state_id}/validators?id=0&id=1",
|
||||
nil,
|
||||
)
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head"})
|
||||
@ -89,8 +94,8 @@ func TestGetValidators(t *testing.T) {
|
||||
resp := &GetValidatorsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.Equal(t, 2, len(resp.Data))
|
||||
assert.Equal(t, "15", resp.Data[0].Index)
|
||||
assert.Equal(t, "26", resp.Data[1].Index)
|
||||
assert.Equal(t, "0", resp.Data[0].Index)
|
||||
assert.Equal(t, "1", resp.Data[1].Index)
|
||||
})
|
||||
t.Run("get by pubkey", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{}
|
||||
@ -103,8 +108,8 @@ func TestGetValidators(t *testing.T) {
|
||||
FinalizationFetcher: chainService,
|
||||
}
|
||||
|
||||
pubkey1 := st.PubkeyAtIndex(primitives.ValidatorIndex(20))
|
||||
pubkey2 := st.PubkeyAtIndex(primitives.ValidatorIndex(66))
|
||||
pubkey1 := st.PubkeyAtIndex(primitives.ValidatorIndex(0))
|
||||
pubkey2 := st.PubkeyAtIndex(primitives.ValidatorIndex(1))
|
||||
hexPubkey1 := hexutil.Encode(pubkey1[:])
|
||||
hexPubkey2 := hexutil.Encode(pubkey2[:])
|
||||
request := httptest.NewRequest(
|
||||
@ -121,8 +126,8 @@ func TestGetValidators(t *testing.T) {
|
||||
resp := &GetValidatorsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.Equal(t, 2, len(resp.Data))
|
||||
assert.Equal(t, "20", resp.Data[0].Index)
|
||||
assert.Equal(t, "66", resp.Data[1].Index)
|
||||
assert.Equal(t, "0", resp.Data[0].Index)
|
||||
assert.Equal(t, "1", resp.Data[1].Index)
|
||||
})
|
||||
t.Run("get by both index and pubkey", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{}
|
||||
@ -135,11 +140,11 @@ func TestGetValidators(t *testing.T) {
|
||||
FinalizationFetcher: chainService,
|
||||
}
|
||||
|
||||
pubkey := st.PubkeyAtIndex(primitives.ValidatorIndex(20))
|
||||
pubkey := st.PubkeyAtIndex(primitives.ValidatorIndex(0))
|
||||
hexPubkey := hexutil.Encode(pubkey[:])
|
||||
request := httptest.NewRequest(
|
||||
http.MethodGet,
|
||||
fmt.Sprintf("http://example.com/eth/v1/beacon/states/{state_id}/validators?id=%s&id=60", hexPubkey),
|
||||
fmt.Sprintf("http://example.com/eth/v1/beacon/states/{state_id}/validators?id=%s&id=1", hexPubkey),
|
||||
nil,
|
||||
)
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head"})
|
||||
@ -151,8 +156,8 @@ func TestGetValidators(t *testing.T) {
|
||||
resp := &GetValidatorsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.Equal(t, 2, len(resp.Data))
|
||||
assert.Equal(t, "20", resp.Data[0].Index)
|
||||
assert.Equal(t, "60", resp.Data[1].Index)
|
||||
assert.Equal(t, "0", resp.Data[0].Index)
|
||||
assert.Equal(t, "1", resp.Data[1].Index)
|
||||
})
|
||||
t.Run("state ID required", func(t *testing.T) {
|
||||
s := Server{
|
||||
@ -275,11 +280,139 @@ func TestGetValidators(t *testing.T) {
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
assert.Equal(t, true, resp.Finalized)
|
||||
})
|
||||
t.Run("POST", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{}
|
||||
s := Server{
|
||||
Stater: &testutil.MockStater{
|
||||
BeaconState: st,
|
||||
},
|
||||
HeadFetcher: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
FinalizationFetcher: chainService,
|
||||
}
|
||||
|
||||
var body bytes.Buffer
|
||||
req := &GetValidatorsRequest{
|
||||
Ids: []string{"0", strconv.Itoa(exitedValIndex)},
|
||||
Statuses: []string{"exited"},
|
||||
}
|
||||
b, err := json.Marshal(req)
|
||||
require.NoError(t, err)
|
||||
_, err = body.Write(b)
|
||||
require.NoError(t, err)
|
||||
request := httptest.NewRequest(
|
||||
http.MethodPost,
|
||||
"http://example.com/eth/v1/beacon/states/{state_id}/validators",
|
||||
&body,
|
||||
)
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head"})
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.GetValidators(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
resp := &GetValidatorsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.Equal(t, 1, len(resp.Data))
|
||||
assert.Equal(t, "3", resp.Data[0].Index)
|
||||
})
|
||||
t.Run("POST nil values", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{}
|
||||
s := Server{
|
||||
Stater: &testutil.MockStater{
|
||||
BeaconState: st,
|
||||
},
|
||||
HeadFetcher: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
FinalizationFetcher: chainService,
|
||||
}
|
||||
|
||||
var body bytes.Buffer
|
||||
req := &GetValidatorsRequest{
|
||||
Ids: nil,
|
||||
Statuses: nil,
|
||||
}
|
||||
b, err := json.Marshal(req)
|
||||
require.NoError(t, err)
|
||||
_, err = body.Write(b)
|
||||
require.NoError(t, err)
|
||||
request := httptest.NewRequest(
|
||||
http.MethodPost,
|
||||
"http://example.com/eth/v1/beacon/states/{state_id}/validators",
|
||||
&body,
|
||||
)
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head"})
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.GetValidators(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
resp := &GetValidatorsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.Equal(t, 4, len(resp.Data))
|
||||
})
|
||||
t.Run("POST empty", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{}
|
||||
s := Server{
|
||||
Stater: &testutil.MockStater{
|
||||
BeaconState: st,
|
||||
},
|
||||
HeadFetcher: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
FinalizationFetcher: chainService,
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(
|
||||
http.MethodPost,
|
||||
"http://example.com/eth/v1/beacon/states/{state_id}/validators",
|
||||
nil,
|
||||
)
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head"})
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.GetValidators(writer, request)
|
||||
assert.Equal(t, http.StatusBadRequest, writer.Code)
|
||||
e := &http2.DefaultErrorJson{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e))
|
||||
assert.Equal(t, http.StatusBadRequest, e.Code)
|
||||
assert.StringContains(t, "No data submitted", e.Message)
|
||||
})
|
||||
t.Run("POST invalid", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{}
|
||||
s := Server{
|
||||
Stater: &testutil.MockStater{
|
||||
BeaconState: st,
|
||||
},
|
||||
HeadFetcher: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
FinalizationFetcher: chainService,
|
||||
}
|
||||
|
||||
body := bytes.Buffer{}
|
||||
_, err := body.WriteString("foo")
|
||||
require.NoError(t, err)
|
||||
request := httptest.NewRequest(
|
||||
http.MethodPost,
|
||||
"http://example.com/eth/v1/beacon/states/{state_id}/validators",
|
||||
&body,
|
||||
)
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head"})
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.GetValidators(writer, request)
|
||||
assert.Equal(t, http.StatusBadRequest, writer.Code)
|
||||
e := &http2.DefaultErrorJson{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e))
|
||||
assert.Equal(t, http.StatusBadRequest, e.Code)
|
||||
assert.StringContains(t, "Could not decode request body", e.Message)
|
||||
})
|
||||
}
|
||||
|
||||
func TestListValidators_FilterByStatus(t *testing.T) {
|
||||
func TestGetValidators_FilterByStatus(t *testing.T) {
|
||||
var st state.BeaconState
|
||||
st, _ = util.DeterministicGenesisState(t, 8192)
|
||||
st, _ = util.DeterministicGenesisState(t, 1)
|
||||
|
||||
farFutureEpoch := params.BeaconConfig().FarFutureEpoch
|
||||
validators := []*eth.Validator{
|
||||
@ -366,7 +499,7 @@ func TestListValidators_FilterByStatus(t *testing.T) {
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
resp := &GetValidatorsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
assert.Equal(t, 8192+2, len(resp.Data))
|
||||
assert.Equal(t, 3, len(resp.Data))
|
||||
for _, vc := range resp.Data {
|
||||
assert.Equal(
|
||||
t,
|
||||
@ -397,7 +530,7 @@ func TestListValidators_FilterByStatus(t *testing.T) {
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
resp := &GetValidatorsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
assert.Equal(t, 8192+1, len(resp.Data))
|
||||
assert.Equal(t, 2, len(resp.Data))
|
||||
for _, vc := range resp.Data {
|
||||
require.Equal(
|
||||
t,
|
||||
@ -506,7 +639,7 @@ func TestListValidators_FilterByStatus(t *testing.T) {
|
||||
|
||||
func TestGetValidator(t *testing.T) {
|
||||
var st state.BeaconState
|
||||
st, _ = util.DeterministicGenesisState(t, 8192)
|
||||
st, _ = util.DeterministicGenesisState(t, 2)
|
||||
|
||||
t.Run("get by index", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{}
|
||||
@ -520,7 +653,7 @@ func TestGetValidator(t *testing.T) {
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators/{validator_id}", nil)
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head", "validator_id": "15"})
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head", "validator_id": "0"})
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
@ -528,12 +661,12 @@ func TestGetValidator(t *testing.T) {
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
resp := &GetValidatorResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
assert.Equal(t, "15", resp.Data.Index)
|
||||
assert.Equal(t, "0", resp.Data.Index)
|
||||
assert.Equal(t, "32000000000", resp.Data.Balance)
|
||||
assert.Equal(t, "active_ongoing", resp.Data.Status)
|
||||
require.NotNil(t, resp.Data.Validator)
|
||||
assert.Equal(t, "0x872c61b4a7f8510ec809e5b023f5fdda2105d024c470ddbbeca4bc74e8280af0d178d749853e8f6a841083ac1b4db98f", resp.Data.Validator.Pubkey)
|
||||
assert.Equal(t, "0x00b24fc624e56a5ed42a9639691e27e34b783c7237030367bd17cbef65fa6ccf", resp.Data.Validator.WithdrawalCredentials)
|
||||
assert.Equal(t, "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c", resp.Data.Validator.Pubkey)
|
||||
assert.Equal(t, "0x00ec7ef7780c9d151597924036262dd28dc60e1228f4da6fecf9d402cb3f3594", resp.Data.Validator.WithdrawalCredentials)
|
||||
assert.Equal(t, "32000000000", resp.Data.Validator.EffectiveBalance)
|
||||
assert.Equal(t, false, resp.Data.Validator.Slashed)
|
||||
assert.Equal(t, "0", resp.Data.Validator.ActivationEligibilityEpoch)
|
||||
@ -552,7 +685,7 @@ func TestGetValidator(t *testing.T) {
|
||||
FinalizationFetcher: chainService,
|
||||
}
|
||||
|
||||
pubKey := st.PubkeyAtIndex(primitives.ValidatorIndex(20))
|
||||
pubKey := st.PubkeyAtIndex(primitives.ValidatorIndex(0))
|
||||
hexPubkey := hexutil.Encode(pubKey[:])
|
||||
request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators/{validator_id}", nil)
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head", "validator_id": hexPubkey})
|
||||
@ -563,7 +696,7 @@ func TestGetValidator(t *testing.T) {
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
resp := &GetValidatorResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
assert.Equal(t, "20", resp.Data.Index)
|
||||
assert.Equal(t, "0", resp.Data.Index)
|
||||
})
|
||||
t.Run("state ID required", func(t *testing.T) {
|
||||
s := Server{
|
||||
@ -657,7 +790,7 @@ func TestGetValidator(t *testing.T) {
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators/{validator_id}", nil)
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head", "validator_id": "15"})
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head", "validator_id": "0"})
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
@ -685,7 +818,7 @@ func TestGetValidator(t *testing.T) {
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators/{validator_id}", nil)
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head", "validator_id": "15"})
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head", "validator_id": "0"})
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
@ -699,7 +832,7 @@ func TestGetValidator(t *testing.T) {
|
||||
|
||||
func TestGetValidatorBalances(t *testing.T) {
|
||||
var st state.BeaconState
|
||||
count := uint64(8192)
|
||||
count := uint64(4)
|
||||
st, _ = util.DeterministicGenesisState(t, count)
|
||||
balances := make([]uint64, count)
|
||||
for i := uint64(0); i < count; i++ {
|
||||
@ -727,10 +860,10 @@ func TestGetValidatorBalances(t *testing.T) {
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
resp := &GetValidatorBalancesResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.Equal(t, 8192, len(resp.Data))
|
||||
val := resp.Data[123]
|
||||
assert.Equal(t, "123", val.Index)
|
||||
assert.Equal(t, "123", val.Balance)
|
||||
require.Equal(t, 4, len(resp.Data))
|
||||
val := resp.Data[3]
|
||||
assert.Equal(t, "3", val.Index)
|
||||
assert.Equal(t, "3", val.Balance)
|
||||
})
|
||||
t.Run("get by index", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{}
|
||||
@ -745,7 +878,7 @@ func TestGetValidatorBalances(t *testing.T) {
|
||||
|
||||
request := httptest.NewRequest(
|
||||
http.MethodGet,
|
||||
"http://example.com/eth/v1/beacon/states/{state_id}/validator_balances?id=15&id=26",
|
||||
"http://example.com/eth/v1/beacon/states/{state_id}/validator_balances?id=0&id=1",
|
||||
nil,
|
||||
)
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head"})
|
||||
@ -757,8 +890,8 @@ func TestGetValidatorBalances(t *testing.T) {
|
||||
resp := &GetValidatorBalancesResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.Equal(t, 2, len(resp.Data))
|
||||
assert.Equal(t, "15", resp.Data[0].Index)
|
||||
assert.Equal(t, "26", resp.Data[1].Index)
|
||||
assert.Equal(t, "0", resp.Data[0].Index)
|
||||
assert.Equal(t, "1", resp.Data[1].Index)
|
||||
})
|
||||
t.Run("get by pubkey", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{}
|
||||
@ -770,8 +903,8 @@ func TestGetValidatorBalances(t *testing.T) {
|
||||
OptimisticModeFetcher: chainService,
|
||||
FinalizationFetcher: chainService,
|
||||
}
|
||||
pubkey1 := st.PubkeyAtIndex(primitives.ValidatorIndex(20))
|
||||
pubkey2 := st.PubkeyAtIndex(primitives.ValidatorIndex(66))
|
||||
pubkey1 := st.PubkeyAtIndex(primitives.ValidatorIndex(0))
|
||||
pubkey2 := st.PubkeyAtIndex(primitives.ValidatorIndex(1))
|
||||
hexPubkey1 := hexutil.Encode(pubkey1[:])
|
||||
hexPubkey2 := hexutil.Encode(pubkey2[:])
|
||||
|
||||
@ -789,8 +922,8 @@ func TestGetValidatorBalances(t *testing.T) {
|
||||
resp := &GetValidatorBalancesResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.Equal(t, 2, len(resp.Data))
|
||||
assert.Equal(t, "20", resp.Data[0].Index)
|
||||
assert.Equal(t, "66", resp.Data[1].Index)
|
||||
assert.Equal(t, "0", resp.Data[0].Index)
|
||||
assert.Equal(t, "1", resp.Data[1].Index)
|
||||
})
|
||||
t.Run("get by both index and pubkey", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{}
|
||||
@ -803,11 +936,11 @@ func TestGetValidatorBalances(t *testing.T) {
|
||||
FinalizationFetcher: chainService,
|
||||
}
|
||||
|
||||
pubkey := st.PubkeyAtIndex(primitives.ValidatorIndex(20))
|
||||
pubkey := st.PubkeyAtIndex(primitives.ValidatorIndex(0))
|
||||
hexPubkey := hexutil.Encode(pubkey[:])
|
||||
request := httptest.NewRequest(
|
||||
http.MethodGet,
|
||||
fmt.Sprintf("http://example.com/eth/v1/beacon/states/{state_id}/validators?id=%s&id=60", hexPubkey),
|
||||
fmt.Sprintf("http://example.com/eth/v1/beacon/states/{state_id}/validators?id=%s&id=1", hexPubkey),
|
||||
nil,
|
||||
)
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head"})
|
||||
@ -819,8 +952,8 @@ func TestGetValidatorBalances(t *testing.T) {
|
||||
resp := &GetValidatorsResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.Equal(t, 2, len(resp.Data))
|
||||
assert.Equal(t, "20", resp.Data[0].Index)
|
||||
assert.Equal(t, "60", resp.Data[1].Index)
|
||||
assert.Equal(t, "0", resp.Data[0].Index)
|
||||
assert.Equal(t, "1", resp.Data[1].Index)
|
||||
})
|
||||
t.Run("unknown pubkey is ignored", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{}
|
||||
@ -906,7 +1039,7 @@ func TestGetValidatorBalances(t *testing.T) {
|
||||
|
||||
request := httptest.NewRequest(
|
||||
http.MethodGet,
|
||||
"http://example.com/eth/v1/beacon/states/{state_id}/validator_balances?id=15",
|
||||
"http://example.com/eth/v1/beacon/states/{state_id}/validator_balances?id=0",
|
||||
nil,
|
||||
)
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head"})
|
||||
@ -938,7 +1071,7 @@ func TestGetValidatorBalances(t *testing.T) {
|
||||
|
||||
request := httptest.NewRequest(
|
||||
http.MethodGet,
|
||||
"http://example.com/eth/v1/beacon/states/{state_id}/validator_balances?id=15",
|
||||
"http://example.com/eth/v1/beacon/states/{state_id}/validator_balances?id=0",
|
||||
nil,
|
||||
)
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head"})
|
||||
@ -951,4 +1084,96 @@ func TestGetValidatorBalances(t *testing.T) {
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
assert.Equal(t, true, resp.Finalized)
|
||||
})
|
||||
t.Run("POST", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{}
|
||||
s := Server{
|
||||
Stater: &testutil.MockStater{
|
||||
BeaconState: st,
|
||||
},
|
||||
HeadFetcher: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
FinalizationFetcher: chainService,
|
||||
}
|
||||
|
||||
pubkey1 := st.PubkeyAtIndex(primitives.ValidatorIndex(0))
|
||||
pubkey2 := st.PubkeyAtIndex(primitives.ValidatorIndex(1))
|
||||
hexPubkey1 := hexutil.Encode(pubkey1[:])
|
||||
hexPubkey2 := hexutil.Encode(pubkey2[:])
|
||||
var body bytes.Buffer
|
||||
_, err := body.WriteString(fmt.Sprintf("[\"%s\",\"%s\"]", hexPubkey1, hexPubkey2))
|
||||
require.NoError(t, err)
|
||||
request := httptest.NewRequest(
|
||||
http.MethodPost,
|
||||
"http://example.com/eth/v1/beacon/states/{state_id}/validator_balances",
|
||||
&body,
|
||||
)
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head"})
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.GetValidatorBalances(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
resp := &GetValidatorBalancesResponse{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
||||
require.Equal(t, 2, len(resp.Data))
|
||||
assert.Equal(t, "0", resp.Data[0].Index)
|
||||
assert.Equal(t, "1", resp.Data[1].Index)
|
||||
})
|
||||
t.Run("POST empty", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{}
|
||||
s := Server{
|
||||
Stater: &testutil.MockStater{
|
||||
BeaconState: st,
|
||||
},
|
||||
HeadFetcher: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
FinalizationFetcher: chainService,
|
||||
}
|
||||
|
||||
request := httptest.NewRequest(
|
||||
http.MethodPost,
|
||||
"http://example.com/eth/v1/beacon/states/{state_id}/validator_balances",
|
||||
nil,
|
||||
)
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head"})
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.GetValidatorBalances(writer, request)
|
||||
assert.Equal(t, http.StatusBadRequest, writer.Code)
|
||||
e := &http2.DefaultErrorJson{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e))
|
||||
assert.Equal(t, http.StatusBadRequest, e.Code)
|
||||
assert.StringContains(t, "No data submitted", e.Message)
|
||||
})
|
||||
t.Run("POST invalid", func(t *testing.T) {
|
||||
chainService := &chainMock.ChainService{}
|
||||
s := Server{
|
||||
Stater: &testutil.MockStater{
|
||||
BeaconState: st,
|
||||
},
|
||||
HeadFetcher: chainService,
|
||||
OptimisticModeFetcher: chainService,
|
||||
FinalizationFetcher: chainService,
|
||||
}
|
||||
|
||||
body := bytes.Buffer{}
|
||||
_, err := body.WriteString("foo")
|
||||
require.NoError(t, err)
|
||||
request := httptest.NewRequest(
|
||||
http.MethodPost,
|
||||
"http://example.com/eth/v1/beacon/states/{state_id}/validator_balances",
|
||||
&body,
|
||||
)
|
||||
request = mux.SetURLVars(request, map[string]string{"state_id": "head"})
|
||||
writer := httptest.NewRecorder()
|
||||
writer.Body = &bytes.Buffer{}
|
||||
|
||||
s.GetValidatorBalances(writer, request)
|
||||
assert.Equal(t, http.StatusBadRequest, writer.Code)
|
||||
e := &http2.DefaultErrorJson{}
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e))
|
||||
assert.Equal(t, http.StatusBadRequest, e.Code)
|
||||
assert.StringContains(t, "Could not decode request body", e.Message)
|
||||
})
|
||||
}
|
||||
|
@ -76,6 +76,11 @@ type GetBlockHeaderResponse struct {
|
||||
Data *shared.SignedBeaconBlockHeaderContainer `json:"data"`
|
||||
}
|
||||
|
||||
type GetValidatorsRequest struct {
|
||||
Ids []string `json:"ids"`
|
||||
Statuses []string `json:"statuses"`
|
||||
}
|
||||
|
||||
type GetValidatorsResponse struct {
|
||||
ExecutionOptimistic bool `json:"execution_optimistic"`
|
||||
Finalized bool `json:"finalized"`
|
||||
|
@ -471,9 +471,9 @@ func (s *Service) Start() {
|
||||
s.cfg.Router.HandleFunc("/eth/v1/beacon/headers/{block_id}", beaconChainServerV1.GetBlockHeader).Methods(http.MethodGet)
|
||||
s.cfg.Router.HandleFunc("/eth/v1/beacon/genesis", beaconChainServerV1.GetGenesis).Methods(http.MethodGet)
|
||||
s.cfg.Router.HandleFunc("/eth/v1/beacon/states/{state_id}/finality_checkpoints", beaconChainServerV1.GetFinalityCheckpoints).Methods(http.MethodGet)
|
||||
s.cfg.Router.HandleFunc("/eth/v1/beacon/states/{state_id}/validators", beaconChainServerV1.GetValidators).Methods(http.MethodGet)
|
||||
s.cfg.Router.HandleFunc("/eth/v1/beacon/states/{state_id}/validators", beaconChainServerV1.GetValidators).Methods(http.MethodGet, http.MethodPost)
|
||||
s.cfg.Router.HandleFunc("/eth/v1/beacon/states/{state_id}/validators/{validator_id}", beaconChainServerV1.GetValidator).Methods(http.MethodGet)
|
||||
s.cfg.Router.HandleFunc("/eth/v1/beacon/states/{state_id}/validator_balances", beaconChainServerV1.GetValidatorBalances).Methods(http.MethodGet)
|
||||
s.cfg.Router.HandleFunc("/eth/v1/beacon/states/{state_id}/validator_balances", beaconChainServerV1.GetValidatorBalances).Methods(http.MethodGet, http.MethodPost)
|
||||
|
||||
s.cfg.Router.HandleFunc("/eth/v1/config/deposit_contract", config.GetDepositContract).Methods(http.MethodGet)
|
||||
s.cfg.Router.HandleFunc("/eth/v1/config/fork_schedule", config.GetForkSchedule).Methods(http.MethodGet)
|
||||
|
Loading…
Reference in New Issue
Block a user