Blob API - invalid indicies should error instead of ignored (#13616)

* addressing ux issue when using API

* Update beacon-chain/rpc/eth/blob/handlers.go

Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>

* Update beacon-chain/rpc/eth/blob/handlers.go

Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>

* fixing tests

---------

Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>
This commit is contained in:
james-prysm 2024-02-15 13:54:42 -06:00 committed by GitHub
parent 3a2734f249
commit 2d0fe20917
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 59 additions and 7 deletions

View File

@ -1,6 +1,7 @@
package blob package blob
import ( import (
"fmt"
"net/http" "net/http"
"net/url" "net/url"
"strconv" "strconv"
@ -21,7 +22,11 @@ func (s *Server) Blobs(w http.ResponseWriter, r *http.Request) {
defer span.End() defer span.End()
var sidecars []*eth.BlobSidecar var sidecars []*eth.BlobSidecar
indices := parseIndices(r.URL) indices, err := parseIndices(r.URL)
if err != nil {
httputil.HandleError(w, err.Error(), http.StatusBadRequest)
return
}
segments := strings.Split(r.URL.Path, "/") segments := strings.Split(r.URL.Path, "/")
blockId := segments[len(segments)-1] blockId := segments[len(segments)-1]
@ -63,16 +68,19 @@ func (s *Server) Blobs(w http.ResponseWriter, r *http.Request) {
} }
// parseIndices filters out invalid and duplicate blob indices // parseIndices filters out invalid and duplicate blob indices
func parseIndices(url *url.URL) []uint64 { func parseIndices(url *url.URL) ([]uint64, error) {
rawIndices := url.Query()["indices"] rawIndices := url.Query()["indices"]
indices := make([]uint64, 0, field_params.MaxBlobsPerBlock) indices := make([]uint64, 0, field_params.MaxBlobsPerBlock)
invalidIndices := make([]string, 0)
loop: loop:
for _, raw := range rawIndices { for _, raw := range rawIndices {
ix, err := strconv.ParseUint(raw, 10, 64) ix, err := strconv.ParseUint(raw, 10, 64)
if err != nil { if err != nil {
invalidIndices = append(invalidIndices, raw)
continue continue
} }
if ix >= field_params.MaxBlobsPerBlock { if ix >= field_params.MaxBlobsPerBlock {
invalidIndices = append(invalidIndices, raw)
continue continue
} }
for i := range indices { for i := range indices {
@ -82,7 +90,11 @@ loop:
} }
indices = append(indices, ix) indices = append(indices, ix)
} }
return indices
if len(invalidIndices) > 0 {
return nil, fmt.Errorf("requested blob indices %v are invalid", invalidIndices)
}
return indices, nil
} }
func buildSidecarsResponse(sidecars []*eth.BlobSidecar) *structs.SidecarsResponse { func buildSidecarsResponse(sidecars []*eth.BlobSidecar) *structs.SidecarsResponse {

View File

@ -7,6 +7,7 @@ import (
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"net/url" "net/url"
"reflect"
"strings" "strings"
"testing" "testing"
"time" "time"
@ -27,10 +28,6 @@ import (
"github.com/prysmaticlabs/prysm/v5/testing/util" "github.com/prysmaticlabs/prysm/v5/testing/util"
) )
func TestParseIndices(t *testing.T) {
assert.DeepEqual(t, []uint64{1, 2, 3}, parseIndices(&url.URL{RawQuery: "indices=100&indices=1&indices=2&indices=foo&indices=1&indices=3&bar=bar"}))
}
func TestBlobs(t *testing.T) { func TestBlobs(t *testing.T) {
params.SetupTestConfigCleanup(t) params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig().Copy() cfg := params.BeaconConfig().Copy()
@ -372,3 +369,46 @@ func TestBlobs(t *testing.T) {
require.Equal(t, len(writer.Body.Bytes()), 131932) require.Equal(t, len(writer.Body.Bytes()), 131932)
}) })
} }
func Test_parseIndices(t *testing.T) {
tests := []struct {
name string
query string
want []uint64
wantErr string
}{
{
name: "happy path with duplicate indices within bound and other query parameters ignored",
query: "indices=1&indices=2&indices=1&indices=3&bar=bar",
want: []uint64{1, 2, 3},
},
{
name: "out of bounds indices throws error",
query: "indices=6&indices=7",
wantErr: "requested blob indices [6 7] are invalid",
},
{
name: "negative indices",
query: "indices=-1&indices=-8",
wantErr: "requested blob indices [-1 -8] are invalid",
},
{
name: "invalid indices",
query: "indices=foo&indices=bar",
wantErr: "requested blob indices [foo bar] are invalid",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parseIndices(&url.URL{RawQuery: tt.query})
if err != nil && tt.wantErr != "" {
require.StringContains(t, tt.wantErr, err.Error())
return
}
require.NoError(t, err)
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("parseIndices() got = %v, want %v", got, tt.want)
}
})
}
}