tests for origin blob fetching (#13667)

* tests for origin blob fetching

* Update beacon-chain/sync/initial-sync/service.go

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

---------

Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>
This commit is contained in:
kasey 2024-03-02 09:11:22 -06:00 committed by GitHub
parent 68b78dd520
commit 4c3dbae3c0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 98 additions and 22 deletions

View File

@ -2115,7 +2115,7 @@ func TestMissingIndices(t *testing.T) {
for _, c := range cases { for _, c := range cases {
bm, bs := filesystem.NewEphemeralBlobStorageWithMocker(t) bm, bs := filesystem.NewEphemeralBlobStorageWithMocker(t)
t.Run(c.name, func(t *testing.T) { t.Run(c.name, func(t *testing.T) {
require.NoError(t, bm.CreateFakeIndices(c.root, c.present)) require.NoError(t, bm.CreateFakeIndices(c.root, c.present...))
missing, err := missingIndices(bs, c.root, c.expected) missing, err := missingIndices(bs, c.root, c.expected)
if c.err != nil { if c.err != nil {
require.ErrorIs(t, err, c.err) require.ErrorIs(t, err, c.err)

View File

@ -37,7 +37,7 @@ type BlobMocker struct {
// CreateFakeIndices creates empty blob sidecar files at the expected path for the given // CreateFakeIndices creates empty blob sidecar files at the expected path for the given
// root and indices to influence the result of Indices(). // root and indices to influence the result of Indices().
func (bm *BlobMocker) CreateFakeIndices(root [32]byte, indices []uint64) error { func (bm *BlobMocker) CreateFakeIndices(root [32]byte, indices ...uint64) error {
for i := range indices { for i := range indices {
n := blobNamer{root: root, index: indices[i]} n := blobNamer{root: root, index: indices[i]}
if err := bm.fs.MkdirAll(n.dir(), directoryPermissions); err != nil { if err := bm.fs.MkdirAll(n.dir(), directoryPermissions); err != nil {

View File

@ -279,34 +279,22 @@ func (s *Service) markSynced() {
close(s.cfg.InitialSyncComplete) close(s.cfg.InitialSyncComplete)
} }
func (s *Service) fetchOriginBlobs(pids []peer.ID) error { func missingBlobRequest(blk blocks.ROBlock, store *filesystem.BlobStorage) (p2ptypes.BlobSidecarsByRootReq, error) {
r, err := s.cfg.DB.OriginCheckpointBlockRoot(s.ctx) r := blk.Root()
if errors.Is(err, db.ErrNotFoundOriginBlockRoot) {
return nil
}
blk, err := s.cfg.DB.Block(s.ctx, r)
if err != nil {
log.WithField("root", r).Error("Block for checkpoint sync origin root not found in db")
return err
}
if blk.Version() < version.Deneb { if blk.Version() < version.Deneb {
return nil return nil, nil
} }
cmts, err := blk.Block().Body().BlobKzgCommitments() cmts, err := blk.Block().Body().BlobKzgCommitments()
if err != nil { if err != nil {
log.WithField("root", r).Error("Error reading commitments from checkpoint sync origin block") log.WithField("root", r).Error("Error reading commitments from checkpoint sync origin block")
return err return nil, err
} }
if len(cmts) == 0 { if len(cmts) == 0 {
return nil return nil, nil
} }
rob, err := blocks.NewROBlockWithRoot(blk, r) onDisk, err := store.Indices(r)
if err != nil { if err != nil {
return err return nil, errors.Wrapf(err, "error checking existing blobs for checkpoint sync block root %#x", r)
}
onDisk, err := s.cfg.BlobStorage.Indices(r)
if err != nil {
return errors.Wrapf(err, "error checking existing blobs for checkpoint sync bloc root %#x", r)
} }
req := make(p2ptypes.BlobSidecarsByRootReq, 0, len(cmts)) req := make(p2ptypes.BlobSidecarsByRootReq, 0, len(cmts))
for i := range cmts { for i := range cmts {
@ -315,8 +303,29 @@ func (s *Service) fetchOriginBlobs(pids []peer.ID) error {
} }
req = append(req, &eth.BlobIdentifier{BlockRoot: r[:], Index: uint64(i)}) req = append(req, &eth.BlobIdentifier{BlockRoot: r[:], Index: uint64(i)})
} }
return req, nil
}
func (s *Service) fetchOriginBlobs(pids []peer.ID) error {
r, err := s.cfg.DB.OriginCheckpointBlockRoot(s.ctx)
if errors.Is(err, db.ErrNotFoundOriginBlockRoot) {
return nil
}
blk, err := s.cfg.DB.Block(s.ctx, r)
if err != nil {
log.WithField("root", fmt.Sprintf("%#x", r)).Error("Block for checkpoint sync origin root not found in db")
return err
}
rob, err := blocks.NewROBlockWithRoot(blk, r)
if err != nil {
return err
}
req, err := missingBlobRequest(rob, s.cfg.BlobStorage)
if err != nil {
return err
}
if len(req) == 0 { if len(req) == 0 {
log.WithField("nBlobs", len(cmts)).WithField("root", fmt.Sprintf("%#x", r)).Debug("All checkpoint block blobs are present") log.WithField("root", fmt.Sprintf("%#x", r)).Debug("All blobs for checkpoint block are present")
return nil return nil
} }
shufflePeers(pids) shufflePeers(pids)

View File

@ -16,6 +16,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/beacon-chain/verification" "github.com/prysmaticlabs/prysm/v5/beacon-chain/verification"
"github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags" "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags"
"github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/assert"
@ -420,3 +421,69 @@ func TestService_Synced(t *testing.T) {
s.synced.Set() s.synced.Set()
assert.Equal(t, true, s.Synced()) assert.Equal(t, true, s.Synced())
} }
func TestMissingBlobRequest(t *testing.T) {
cases := []struct {
name string
setup func(t *testing.T) (blocks.ROBlock, *filesystem.BlobStorage)
nReq int
err error
}{
{
name: "pre-deneb",
setup: func(t *testing.T) (blocks.ROBlock, *filesystem.BlobStorage) {
cb, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockCapella())
require.NoError(t, err)
rob, err := blocks.NewROBlockWithRoot(cb, [32]byte{})
require.NoError(t, err)
return rob, nil
},
nReq: 0,
},
{
name: "deneb zero commitments",
setup: func(t *testing.T) (blocks.ROBlock, *filesystem.BlobStorage) {
bk, _ := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 0, 0)
return bk, nil
},
nReq: 0,
},
{
name: "2 commitments, all missing",
setup: func(t *testing.T) (blocks.ROBlock, *filesystem.BlobStorage) {
bk, _ := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 0, 2)
fs := filesystem.NewEphemeralBlobStorage(t)
return bk, fs
},
nReq: 2,
},
{
name: "2 commitments, 1 missing",
setup: func(t *testing.T) (blocks.ROBlock, *filesystem.BlobStorage) {
bk, _ := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 0, 2)
bm, fs := filesystem.NewEphemeralBlobStorageWithMocker(t)
require.NoError(t, bm.CreateFakeIndices(bk.Root(), 1))
return bk, fs
},
nReq: 1,
},
{
name: "2 commitments, 0 missing",
setup: func(t *testing.T) (blocks.ROBlock, *filesystem.BlobStorage) {
bk, _ := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 0, 2)
bm, fs := filesystem.NewEphemeralBlobStorageWithMocker(t)
require.NoError(t, bm.CreateFakeIndices(bk.Root(), 0, 1))
return bk, fs
},
nReq: 0,
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
blk, store := c.setup(t)
req, err := missingBlobRequest(blk, store)
require.NoError(t, err)
require.Equal(t, c.nReq, len(req))
})
}
}