mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-10 11:41:21 +00:00
304 lines
11 KiB
Go
304 lines
11 KiB
Go
package blob
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
mockChain "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
|
|
testDB "github.com/prysmaticlabs/prysm/v4/beacon-chain/db/testing"
|
|
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
|
"github.com/prysmaticlabs/prysm/v4/config/params"
|
|
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
|
|
http2 "github.com/prysmaticlabs/prysm/v4/network/http"
|
|
eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/v4/testing/assert"
|
|
"github.com/prysmaticlabs/prysm/v4/testing/require"
|
|
)
|
|
|
|
func TestParseIndices(t *testing.T) {
|
|
assert.DeepEqual(t, []uint64{1, 2, 3}, parseIndices(&url.URL{RawQuery: "indices=1,2,foo,1&indices=3,1&bar=bar"}))
|
|
}
|
|
|
|
func TestBlobs(t *testing.T) {
|
|
params.SetupTestConfigCleanup(t)
|
|
cfg := params.BeaconConfig().Copy()
|
|
cfg.DenebForkEpoch = 1
|
|
params.OverrideBeaconConfig(cfg)
|
|
|
|
db := testDB.SetupDB(t)
|
|
blockroot := bytesutil.PadTo([]byte("blockroot"), 32)
|
|
require.NoError(t, db.SaveBlobSidecar(context.Background(), []*eth.BlobSidecar{
|
|
{
|
|
BlockRoot: blockroot,
|
|
Index: 0,
|
|
Slot: 123,
|
|
BlockParentRoot: []byte("blockparentroot"),
|
|
ProposerIndex: 123,
|
|
Blob: []byte("blob0"),
|
|
KzgCommitment: []byte("kzgcommitment0"),
|
|
KzgProof: []byte("kzgproof0"),
|
|
},
|
|
{
|
|
BlockRoot: blockroot,
|
|
Index: 1,
|
|
Slot: 123,
|
|
BlockParentRoot: []byte("blockparentroot"),
|
|
ProposerIndex: 123,
|
|
Blob: []byte("blob1"),
|
|
KzgCommitment: []byte("kzgcommitment1"),
|
|
KzgProof: []byte("kzgproof1"),
|
|
},
|
|
{
|
|
BlockRoot: blockroot,
|
|
Index: 2,
|
|
Slot: 123,
|
|
BlockParentRoot: []byte("blockparentroot"),
|
|
ProposerIndex: 123,
|
|
Blob: []byte("blob2"),
|
|
KzgCommitment: []byte("kzgcommitment2"),
|
|
KzgProof: []byte("kzgproof2"),
|
|
},
|
|
{
|
|
BlockRoot: blockroot,
|
|
Index: 3,
|
|
Slot: 123,
|
|
BlockParentRoot: []byte("blockparentroot"),
|
|
ProposerIndex: 123,
|
|
Blob: []byte("blob3"),
|
|
KzgCommitment: []byte("kzgcommitment3"),
|
|
KzgProof: []byte("kzgproof3"),
|
|
},
|
|
}))
|
|
|
|
t.Run("genesis", func(t *testing.T) {
|
|
u := "http://foo.example/genesis"
|
|
request := httptest.NewRequest("GET", u, nil)
|
|
writer := httptest.NewRecorder()
|
|
writer.Body = &bytes.Buffer{}
|
|
s := &Server{}
|
|
|
|
s.Blobs(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.Equal(t, "blobs are not supported for Phase 0 fork", e.Message)
|
|
})
|
|
t.Run("head", func(t *testing.T) {
|
|
u := "http://foo.example/head"
|
|
request := httptest.NewRequest("GET", u, nil)
|
|
writer := httptest.NewRecorder()
|
|
writer.Body = &bytes.Buffer{}
|
|
s := &Server{
|
|
ChainInfoFetcher: &mockChain.ChainService{Root: blockroot},
|
|
BeaconDB: db,
|
|
}
|
|
|
|
s.Blobs(writer, request)
|
|
|
|
assert.Equal(t, http.StatusOK, writer.Code)
|
|
resp := &SidecarsResponse{}
|
|
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
|
require.Equal(t, 4, len(resp.Data))
|
|
sidecar := resp.Data[0]
|
|
require.NotNil(t, sidecar)
|
|
assert.Equal(t, "0x626c6f636b726f6f740000000000000000000000000000000000000000000000", sidecar.BlockRoot)
|
|
assert.Equal(t, "0", sidecar.Index)
|
|
assert.Equal(t, "123", sidecar.Slot)
|
|
assert.Equal(t, "0x626c6f636b706172656e74726f6f74", sidecar.BlockParentRoot)
|
|
assert.Equal(t, "123", sidecar.ProposerIndex)
|
|
assert.Equal(t, "0x626c6f6230", sidecar.Blob)
|
|
assert.Equal(t, "0x6b7a67636f6d6d69746d656e7430", sidecar.KZGCommitment)
|
|
assert.Equal(t, "0x6b7a6770726f6f6630", sidecar.KZGProof)
|
|
sidecar = resp.Data[1]
|
|
require.NotNil(t, sidecar)
|
|
assert.Equal(t, "0x626c6f636b726f6f740000000000000000000000000000000000000000000000", sidecar.BlockRoot)
|
|
assert.Equal(t, "1", sidecar.Index)
|
|
assert.Equal(t, "123", sidecar.Slot)
|
|
assert.Equal(t, "0x626c6f636b706172656e74726f6f74", sidecar.BlockParentRoot)
|
|
assert.Equal(t, "123", sidecar.ProposerIndex)
|
|
assert.Equal(t, "0x626c6f6231", sidecar.Blob)
|
|
assert.Equal(t, "0x6b7a67636f6d6d69746d656e7431", sidecar.KZGCommitment)
|
|
assert.Equal(t, "0x6b7a6770726f6f6631", sidecar.KZGProof)
|
|
sidecar = resp.Data[2]
|
|
require.NotNil(t, sidecar)
|
|
assert.Equal(t, "0x626c6f636b726f6f740000000000000000000000000000000000000000000000", sidecar.BlockRoot)
|
|
assert.Equal(t, "2", sidecar.Index)
|
|
assert.Equal(t, "123", sidecar.Slot)
|
|
assert.Equal(t, "0x626c6f636b706172656e74726f6f74", sidecar.BlockParentRoot)
|
|
assert.Equal(t, "123", sidecar.ProposerIndex)
|
|
assert.Equal(t, "0x626c6f6232", sidecar.Blob)
|
|
assert.Equal(t, "0x6b7a67636f6d6d69746d656e7432", sidecar.KZGCommitment)
|
|
assert.Equal(t, "0x6b7a6770726f6f6632", sidecar.KZGProof)
|
|
sidecar = resp.Data[3]
|
|
require.NotNil(t, sidecar)
|
|
assert.Equal(t, "0x626c6f636b726f6f740000000000000000000000000000000000000000000000", sidecar.BlockRoot)
|
|
assert.Equal(t, "3", sidecar.Index)
|
|
assert.Equal(t, "123", sidecar.Slot)
|
|
assert.Equal(t, "0x626c6f636b706172656e74726f6f74", sidecar.BlockParentRoot)
|
|
assert.Equal(t, "123", sidecar.ProposerIndex)
|
|
assert.Equal(t, "0x626c6f6233", sidecar.Blob)
|
|
assert.Equal(t, "0x6b7a67636f6d6d69746d656e7433", sidecar.KZGCommitment)
|
|
assert.Equal(t, "0x6b7a6770726f6f6633", sidecar.KZGProof)
|
|
})
|
|
t.Run("finalized", func(t *testing.T) {
|
|
u := "http://foo.example/finalized"
|
|
request := httptest.NewRequest("GET", u, nil)
|
|
writer := httptest.NewRecorder()
|
|
writer.Body = &bytes.Buffer{}
|
|
s := &Server{
|
|
ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockroot}},
|
|
BeaconDB: db,
|
|
}
|
|
|
|
s.Blobs(writer, request)
|
|
|
|
assert.Equal(t, http.StatusOK, writer.Code)
|
|
resp := &SidecarsResponse{}
|
|
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
|
require.Equal(t, 4, len(resp.Data))
|
|
})
|
|
t.Run("justified", func(t *testing.T) {
|
|
u := "http://foo.example/justified"
|
|
request := httptest.NewRequest("GET", u, nil)
|
|
writer := httptest.NewRecorder()
|
|
writer.Body = &bytes.Buffer{}
|
|
s := &Server{
|
|
ChainInfoFetcher: &mockChain.ChainService{CurrentJustifiedCheckPoint: ð.Checkpoint{Root: blockroot}},
|
|
BeaconDB: db,
|
|
}
|
|
|
|
s.Blobs(writer, request)
|
|
|
|
assert.Equal(t, http.StatusOK, writer.Code)
|
|
resp := &SidecarsResponse{}
|
|
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
|
require.Equal(t, 4, len(resp.Data))
|
|
})
|
|
t.Run("root", func(t *testing.T) {
|
|
u := "http://foo.example/" + hexutil.Encode(blockroot)
|
|
request := httptest.NewRequest("GET", u, nil)
|
|
writer := httptest.NewRecorder()
|
|
writer.Body = &bytes.Buffer{}
|
|
s := &Server{
|
|
BeaconDB: db,
|
|
}
|
|
|
|
s.Blobs(writer, request)
|
|
|
|
assert.Equal(t, http.StatusOK, writer.Code)
|
|
resp := &SidecarsResponse{}
|
|
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
|
require.Equal(t, 4, len(resp.Data))
|
|
})
|
|
t.Run("slot", func(t *testing.T) {
|
|
u := "http://foo.example/123"
|
|
request := httptest.NewRequest("GET", u, nil)
|
|
writer := httptest.NewRecorder()
|
|
writer.Body = &bytes.Buffer{}
|
|
s := &Server{
|
|
BeaconDB: db,
|
|
}
|
|
|
|
s.Blobs(writer, request)
|
|
|
|
assert.Equal(t, http.StatusOK, writer.Code)
|
|
resp := &SidecarsResponse{}
|
|
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
|
require.Equal(t, 4, len(resp.Data))
|
|
})
|
|
t.Run("one blob only", func(t *testing.T) {
|
|
u := "http://foo.example/123?indices=2"
|
|
request := httptest.NewRequest("GET", u, nil)
|
|
writer := httptest.NewRecorder()
|
|
writer.Body = &bytes.Buffer{}
|
|
s := &Server{
|
|
BeaconDB: db,
|
|
}
|
|
|
|
s.Blobs(writer, request)
|
|
|
|
assert.Equal(t, http.StatusOK, writer.Code)
|
|
resp := &SidecarsResponse{}
|
|
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
|
|
require.Equal(t, 1, len(resp.Data))
|
|
sidecar := resp.Data[0]
|
|
require.NotNil(t, sidecar)
|
|
assert.Equal(t, "0x626c6f636b726f6f740000000000000000000000000000000000000000000000", sidecar.BlockRoot)
|
|
assert.Equal(t, "2", sidecar.Index)
|
|
assert.Equal(t, "123", sidecar.Slot)
|
|
assert.Equal(t, "0x626c6f636b706172656e74726f6f74", sidecar.BlockParentRoot)
|
|
assert.Equal(t, "123", sidecar.ProposerIndex)
|
|
assert.Equal(t, "0x626c6f6232", sidecar.Blob)
|
|
assert.Equal(t, "0x6b7a67636f6d6d69746d656e7432", sidecar.KZGCommitment)
|
|
assert.Equal(t, "0x6b7a6770726f6f6632", sidecar.KZGProof)
|
|
})
|
|
t.Run("slot before Deneb fork", func(t *testing.T) {
|
|
u := "http://foo.example/31"
|
|
request := httptest.NewRequest("GET", u, nil)
|
|
writer := httptest.NewRecorder()
|
|
writer.Body = &bytes.Buffer{}
|
|
s := &Server{}
|
|
|
|
s.Blobs(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.Equal(t, "blobs are not supported before Deneb fork", e.Message)
|
|
})
|
|
t.Run("malformed block ID", func(t *testing.T) {
|
|
u := "http://foo.example/foo"
|
|
request := httptest.NewRequest("GET", u, nil)
|
|
writer := httptest.NewRecorder()
|
|
writer.Body = &bytes.Buffer{}
|
|
s := &Server{}
|
|
|
|
s.Blobs(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.Equal(t, true, strings.Contains(e.Message, "could not parse block ID"))
|
|
})
|
|
t.Run("ssz", func(t *testing.T) {
|
|
require.NoError(t, db.SaveBlobSidecar(context.Background(), []*eth.BlobSidecar{
|
|
{
|
|
BlockRoot: blockroot,
|
|
Index: 0,
|
|
Slot: 3,
|
|
BlockParentRoot: make([]byte, fieldparams.RootLength),
|
|
ProposerIndex: 123,
|
|
Blob: make([]byte, fieldparams.BlobLength),
|
|
KzgCommitment: make([]byte, fieldparams.BLSPubkeyLength),
|
|
KzgProof: make([]byte, fieldparams.BLSPubkeyLength),
|
|
},
|
|
}))
|
|
u := "http://foo.example/finalized?indices=0"
|
|
request := httptest.NewRequest("GET", u, nil)
|
|
request.Header.Add("Accept", "application/octet-stream")
|
|
writer := httptest.NewRecorder()
|
|
writer.Body = &bytes.Buffer{}
|
|
s := &Server{
|
|
ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockroot}},
|
|
BeaconDB: db,
|
|
}
|
|
|
|
s.Blobs(writer, request)
|
|
|
|
assert.Equal(t, http.StatusOK, writer.Code)
|
|
assert.Equal(t, len(writer.Body.Bytes()), 131260)
|
|
assert.Equal(t, true, strings.HasPrefix(hexutil.Encode(writer.Body.Bytes()), "0x04000000626c6f636b726f6f7400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000007b"))
|
|
})
|
|
}
|