mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-08 23:18:15 -05:00
Implement PeerDAS sync (#15564)
* PeerDAS: Implement sync * Fix Potuz's comment. * Fix Potuz's comment. * Fix Potuz's comment. * Fix Satyajit's comment. * Partially fix Potuz's comment. * Fix Potuz's comment. * Fix Potuz's comment. * Fix Potuz's comment. * Fix Potuz's comment. * Fix Potuz's comment. * Fix Potuz's comment. * Fix Potuz's comment. * Add tests for `sendDataColumnSidecarsRequest`. * Fix Satyajit's comment. * Implement `TestSendDataColumnSidecarsRequest`. * Implement `TestFetchDataColumnSidecarsFromPeers`. * Implement `TestUpdateResults`. * Implement `TestSelectPeers`. * Implement `TestCategorizeIndices`. * Fix James' comment. * Fix James's comment. * Fix James' commit. * Fix James' comment. * Fix James' comment. * Fix flakiness in `TestSelectPeers`. * Update cmd/beacon-chain/flags/config.go Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com> * Fix Preston's comment. * Fix James's comment. * Implement `TestFetchDataColumnSidecars`. * Revert "Fix Potuz's comment." This reverts commitc45230b455. * Fix Potuz's comment. * Revert "Fix James' comment." This reverts commita3f919205a. * Fix James' comment. * Fix Preston's comment. * Fix James' comment. * `selectPeers`: Avoid map with key but empty value. * Fix typo. * Fix Potuz's comment. * Fix Potuz's comment. * Fix James' comment. * Add DataColumnStorage and SubscribeAllDataSubnets flag. * Add extra flags * Fix Potuz's and Preston's comment. * Add rate limiter check. --------- Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com> Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
This commit is contained in:
@@ -7,14 +7,17 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v6/async/abool"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/blockchain/kzg"
|
||||
mock "github.com/OffchainLabs/prysm/v6/beacon-chain/blockchain/testing"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/peerdas"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/db/filesystem"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/db/kv"
|
||||
dbtest "github.com/OffchainLabs/prysm/v6/beacon-chain/db/testing"
|
||||
p2pt "github.com/OffchainLabs/prysm/v6/beacon-chain/p2p/testing"
|
||||
p2ptest "github.com/OffchainLabs/prysm/v6/beacon-chain/p2p/testing"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/startup"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/verification"
|
||||
"github.com/OffchainLabs/prysm/v6/cmd/beacon-chain/flags"
|
||||
fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams"
|
||||
"github.com/OffchainLabs/prysm/v6/config/params"
|
||||
"github.com/OffchainLabs/prysm/v6/consensus-types/blocks"
|
||||
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
|
||||
@@ -138,7 +141,7 @@ func TestService_InitStartStop(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
p := p2pt.NewTestP2P(t)
|
||||
p := p2ptest.NewTestP2P(t)
|
||||
connectPeers(t, p, []*peerData{}, p.Peers())
|
||||
for i, tt := range tests {
|
||||
if i == 0 {
|
||||
@@ -328,7 +331,7 @@ func TestService_markSynced(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestService_Resync(t *testing.T) {
|
||||
p := p2pt.NewTestP2P(t)
|
||||
p := p2ptest.NewTestP2P(t)
|
||||
connectPeers(t, p, []*peerData{
|
||||
{blocks: makeSequence(1, 160), finalizedEpoch: 5, headSlot: 160},
|
||||
}, p.Peers())
|
||||
@@ -511,5 +514,152 @@ func TestOriginOutsideRetention(t *testing.T) {
|
||||
require.NoError(t, concreteDB.SaveOriginCheckpointBlockRoot(ctx, blk.Root()))
|
||||
// This would break due to missing service dependencies, but will return nil fast due to being outside retention.
|
||||
require.Equal(t, false, params.WithinDAPeriod(slots.ToEpoch(blk.Block().Slot()), slots.ToEpoch(clock.CurrentSlot())))
|
||||
require.NoError(t, s.fetchOriginBlobs([]peer.ID{}))
|
||||
require.NoError(t, s.fetchOriginSidecars([]peer.ID{}))
|
||||
}
|
||||
|
||||
func TestFetchOriginSidecars(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
|
||||
beaconConfig := params.BeaconConfig()
|
||||
genesisTime := time.Date(2025, time.August, 10, 0, 0, 0, 0, time.UTC)
|
||||
secondsPerSlot := beaconConfig.SecondsPerSlot
|
||||
slotsPerEpoch := beaconConfig.SlotsPerEpoch
|
||||
secondsPerEpoch := uint64(slotsPerEpoch.Mul(secondsPerSlot))
|
||||
retentionEpochs := beaconConfig.MinEpochsForDataColumnSidecarsRequest
|
||||
|
||||
genesisValidatorRoot := [fieldparams.RootLength]byte{}
|
||||
|
||||
t.Run("out of retention period", func(t *testing.T) {
|
||||
// Create an origin block.
|
||||
block := util.NewBeaconBlockFulu()
|
||||
signedBlock, err := blocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(t, err)
|
||||
roBlock, err := blocks.NewROBlock(signedBlock)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Save the block.
|
||||
db := dbtest.SetupDB(t)
|
||||
err = db.SaveOriginCheckpointBlockRoot(ctx, roBlock.Root())
|
||||
require.NoError(t, err)
|
||||
err = db.SaveBlock(ctx, roBlock)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Define "now" to be one epoch after genesis time + retention period.
|
||||
nowWrtGenesisSecs := retentionEpochs.Add(1).Mul(secondsPerEpoch)
|
||||
now := genesisTime.Add(time.Duration(nowWrtGenesisSecs) * time.Second)
|
||||
nower := func() time.Time { return now }
|
||||
clock := startup.NewClock(genesisTime, genesisValidatorRoot, startup.WithNower(nower))
|
||||
|
||||
service := &Service{
|
||||
cfg: &Config{
|
||||
DB: db,
|
||||
},
|
||||
clock: clock,
|
||||
}
|
||||
|
||||
err = service.fetchOriginSidecars(nil)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("no commitments", func(t *testing.T) {
|
||||
// Create an origin block.
|
||||
block := util.NewBeaconBlockFulu()
|
||||
signedBlock, err := blocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(t, err)
|
||||
roBlock, err := blocks.NewROBlock(signedBlock)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Save the block.
|
||||
db := dbtest.SetupDB(t)
|
||||
err = db.SaveOriginCheckpointBlockRoot(ctx, roBlock.Root())
|
||||
require.NoError(t, err)
|
||||
err = db.SaveBlock(ctx, roBlock)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Define "now" to be after genesis time + retention period.
|
||||
nowWrtGenesisSecs := retentionEpochs.Mul(secondsPerEpoch)
|
||||
now := genesisTime.Add(time.Duration(nowWrtGenesisSecs) * time.Second)
|
||||
nower := func() time.Time { return now }
|
||||
clock := startup.NewClock(genesisTime, genesisValidatorRoot, startup.WithNower(nower))
|
||||
|
||||
service := &Service{
|
||||
cfg: &Config{
|
||||
DB: db,
|
||||
P2P: p2ptest.NewTestP2P(t),
|
||||
},
|
||||
clock: clock,
|
||||
}
|
||||
|
||||
err = service.fetchOriginSidecars(nil)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("nominal", func(t *testing.T) {
|
||||
samplesPerSlot := params.BeaconConfig().SamplesPerSlot
|
||||
|
||||
// Start the trusted setup.
|
||||
err := kzg.Start()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create block and sidecars.
|
||||
const blobCount = 1
|
||||
roBlock, _, verifiedRoSidecars := util.GenerateTestFuluBlockWithSidecars(t, blobCount)
|
||||
|
||||
// Save the block.
|
||||
db := dbtest.SetupDB(t)
|
||||
err = db.SaveOriginCheckpointBlockRoot(ctx, roBlock.Root())
|
||||
require.NoError(t, err)
|
||||
|
||||
err = db.SaveBlock(ctx, roBlock)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a data columns storage.
|
||||
dir := t.TempDir()
|
||||
dataColumnStorage, err := filesystem.NewDataColumnStorage(ctx, filesystem.WithDataColumnBasePath(dir))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Compute the columns to request.
|
||||
p2p := p2ptest.NewTestP2P(t)
|
||||
custodyGroupCount, err := p2p.CustodyGroupCount()
|
||||
require.NoError(t, err)
|
||||
|
||||
samplingSize := max(custodyGroupCount, samplesPerSlot)
|
||||
info, _, err := peerdas.Info(p2p.NodeID(), samplingSize)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Save all sidecars except what we need.
|
||||
toSave := make([]blocks.VerifiedRODataColumn, 0, uint64(len(verifiedRoSidecars))-samplingSize)
|
||||
for _, sidecar := range verifiedRoSidecars {
|
||||
if !info.CustodyColumns[sidecar.Index] {
|
||||
toSave = append(toSave, sidecar)
|
||||
}
|
||||
}
|
||||
|
||||
err = dataColumnStorage.Save(toSave)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Define "now" to be after genesis time + retention period.
|
||||
nowWrtGenesisSecs := retentionEpochs.Mul(secondsPerEpoch)
|
||||
now := genesisTime.Add(time.Duration(nowWrtGenesisSecs) * time.Second)
|
||||
nower := func() time.Time { return now }
|
||||
clock := startup.NewClock(genesisTime, genesisValidatorRoot, startup.WithNower(nower))
|
||||
|
||||
service := &Service{
|
||||
cfg: &Config{
|
||||
DB: db,
|
||||
P2P: p2p,
|
||||
DataColumnStorage: dataColumnStorage,
|
||||
},
|
||||
clock: clock,
|
||||
}
|
||||
|
||||
err = service.fetchOriginSidecars(nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Check that needed sidecars are saved.
|
||||
summary := dataColumnStorage.Summary(roBlock.Root())
|
||||
for index := range info.CustodyColumns {
|
||||
require.Equal(t, true, summary.HasIndex(index))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user