mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 21:38:05 -05:00
180 lines
5.8 KiB
Go
180 lines
5.8 KiB
Go
package filesystem
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/OffchainLabs/prysm/v6/config/params"
|
|
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
|
|
"github.com/OffchainLabs/prysm/v6/testing/require"
|
|
"github.com/OffchainLabs/prysm/v6/testing/util"
|
|
"github.com/spf13/afero"
|
|
)
|
|
|
|
func ezIdent(t *testing.T, rootStr string, epoch primitives.Epoch, index uint64) blobIdent {
|
|
r, err := stringToRoot(rootStr)
|
|
require.NoError(t, err)
|
|
return blobIdent{root: r, epoch: epoch, index: index}
|
|
}
|
|
|
|
func setupTestBlobFile(t *testing.T, ident blobIdent, offset primitives.Slot, fs afero.Fs, l fsLayout) {
|
|
slot := util.SlotAtEpoch(t, ident.epoch) + offset
|
|
_, sc := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, slot, 1)
|
|
scb, err := sc[0].MarshalSSZ()
|
|
require.NoError(t, err)
|
|
dir := l.dir(ident)
|
|
require.NoError(t, fs.MkdirAll(dir, directoryPermissions()))
|
|
p := l.sszPath(ident)
|
|
require.NoError(t, afero.WriteFile(fs, p, scb, 0666))
|
|
_, err = fs.Stat(p)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
type migrationTestTarget struct {
|
|
ident blobIdent
|
|
slotOffset primitives.Slot
|
|
migrated bool
|
|
path string
|
|
}
|
|
|
|
func testAssertFsMigrated(t *testing.T, fs afero.Fs, ident blobIdent, before, after fsLayout) {
|
|
// Assert the pre-migration path is gone.
|
|
_, err := fs.Stat(before.sszPath(ident))
|
|
require.ErrorIs(t, err, os.ErrNotExist)
|
|
dir := before.dir(ident)
|
|
_, err = listDir(fs, dir)
|
|
require.ErrorIs(t, err, os.ErrNotExist)
|
|
|
|
// Assert the post-migration path present.
|
|
_, err = fs.Stat(after.sszPath(ident))
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestMigrations(t *testing.T) {
|
|
de := params.BeaconConfig().DenebForkEpoch
|
|
cases := []struct {
|
|
name string
|
|
forwardLayout string
|
|
backwardLayout string
|
|
targets []migrationTestTarget
|
|
}{
|
|
{
|
|
name: "all need migration",
|
|
backwardLayout: LayoutNameFlat,
|
|
forwardLayout: LayoutNameByEpoch,
|
|
targets: []migrationTestTarget{
|
|
{
|
|
ident: ezIdent(t, "0x0125e54c64c925018c9296965a5b622d9f5ab626c10917860dcfb6aa09a0a00b", de+1234, 0),
|
|
},
|
|
{
|
|
ident: ezIdent(t, "0x0127dba6fd30fdbb47e73e861d5c6e602b38ac3ddc945bb6a2fc4e10761e9a86", de+5330, 0),
|
|
slotOffset: 31,
|
|
},
|
|
{
|
|
ident: ezIdent(t, "0x0127dba6fd30fdbb47e73e861d5c6e602b38ac3ddc945bb6a2fc4e10761e9a86", de+5330, 1),
|
|
slotOffset: 31,
|
|
},
|
|
{
|
|
ident: ezIdent(t, "0x0232521756a0b965eab2c2245d7ad85feaeaf5f427cd14d1a7531f9d555b415c", de+16777216, 0),
|
|
slotOffset: 16,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "mix old and new",
|
|
backwardLayout: LayoutNameFlat,
|
|
forwardLayout: LayoutNameByEpoch,
|
|
targets: []migrationTestTarget{
|
|
{
|
|
ident: ezIdent(t, "0x0125e54c64c925018c9296965a5b622d9f5ab626c10917860dcfb6aa09a0a00b", de+1234, 0),
|
|
},
|
|
{
|
|
ident: ezIdent(t, "0x0127dba6fd30fdbb47e73e861d5c6e602b38ac3ddc945bb6a2fc4e10761e9a86", de+5330, 0),
|
|
slotOffset: 31,
|
|
},
|
|
{
|
|
ident: ezIdent(t, "0x0127dba6fd30fdbb47e73e861d5c6e602b38ac3ddc945bb6a2fc4e10761e9a86", de+5330, 1),
|
|
slotOffset: 31,
|
|
},
|
|
{
|
|
ident: ezIdent(t, "0x0232521756a0b965eab2c2245d7ad85feaeaf5f427cd14d1a7531f9d555b415c", de+16777216, 0),
|
|
slotOffset: 16,
|
|
migrated: true,
|
|
},
|
|
{
|
|
ident: ezIdent(t, "0x0232521756a0b965eab2c2245d7ad85feaeaf5f427cd14d1a7531f9d555b415c", de+16777216, 1),
|
|
slotOffset: 16,
|
|
migrated: true,
|
|
},
|
|
{
|
|
ident: ezIdent(t, "0x42eabe3d2c125410cd226de6f2825fb7575ab896c3f52e43de1fa29e4c809aba", de+16777217, 0),
|
|
slotOffset: 16,
|
|
migrated: true,
|
|
},
|
|
{
|
|
ident: ezIdent(t, "0x666cea5034e22bd3b849cb33914cad59afd88ee08e4d5bc0e997411c945fbc1d", de+11235, 1),
|
|
migrated: true,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
t.Run("forward", func(t *testing.T) {
|
|
testMigration(t, c.forwardLayout, c.backwardLayout, c.targets)
|
|
})
|
|
// run the same test in reverse - to cover both directions while making the test table smaller.
|
|
t.Run("backward", func(t *testing.T) {
|
|
testMigration(t, c.forwardLayout, c.backwardLayout, c.targets)
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
func testMigration(t *testing.T, forwardName, backwardName string, targets []migrationTestTarget) {
|
|
fs := afero.NewMemMapFs()
|
|
cache := newBlobStorageCache()
|
|
forward, err := newLayout(forwardName, fs, cache, nil)
|
|
require.NoError(t, err)
|
|
backward, err := newLayout(backwardName, fs, cache, nil)
|
|
require.NoError(t, err)
|
|
for _, tar := range targets {
|
|
if tar.migrated {
|
|
setupTestBlobFile(t, tar.ident, tar.slotOffset, fs, forward)
|
|
} else {
|
|
setupTestBlobFile(t, tar.ident, tar.slotOffset, fs, backward)
|
|
}
|
|
}
|
|
require.NoError(t, migrateLayout(fs, backward, forward, cache))
|
|
for _, tar := range targets {
|
|
// Make sure the file wound up in the right spot, according to the forward layout
|
|
// and that the old file is gone, according to the backward layout.
|
|
testAssertFsMigrated(t, fs, tar.ident, backward, forward)
|
|
entry, ok := cache.get(tar.ident.root)
|
|
// we only expect cache to be populated here by files that needed to be moved.
|
|
if !tar.migrated {
|
|
require.Equal(t, true, ok)
|
|
require.Equal(t, true, entry.HasIndex(tar.ident.index))
|
|
require.Equal(t, tar.ident.epoch, entry.epoch)
|
|
}
|
|
}
|
|
|
|
// Run migration in reverse - testing "undo"
|
|
cache = newBlobStorageCache()
|
|
forward, err = newLayout(forwardName, fs, cache, nil)
|
|
require.NoError(t, err)
|
|
backward, err = newLayout(backwardName, fs, cache, nil)
|
|
require.NoError(t, err)
|
|
// forward and backward are flipped compared to the above
|
|
require.NoError(t, migrateLayout(fs, forward, backward, cache))
|
|
for _, tar := range targets {
|
|
// just like the above, but forward and backward are flipped
|
|
testAssertFsMigrated(t, fs, tar.ident, forward, backward)
|
|
entry, ok := cache.get(tar.ident.root)
|
|
require.Equal(t, true, ok)
|
|
require.Equal(t, true, entry.HasIndex(tar.ident.index))
|
|
require.Equal(t, tar.ident.epoch, entry.epoch)
|
|
}
|
|
}
|