mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-24 12:27:18 +00:00
495e92ce9f
* add maxprocs * add prereqs * add tos and version pkg * add in all runtime packages Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
778 lines
24 KiB
Go
778 lines
24 KiB
Go
package stategen
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
types "github.com/prysmaticlabs/eth2-types"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
|
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
|
|
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
|
|
"github.com/prysmaticlabs/prysm/runtime/version"
|
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
|
"github.com/prysmaticlabs/prysm/shared/params"
|
|
"github.com/prysmaticlabs/prysm/shared/testutil"
|
|
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
|
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
func TestReplayBlocks_AllSkipSlots(t *testing.T) {
|
|
beaconDB := testDB.SetupDB(t)
|
|
|
|
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
|
|
genesisBlock := blocks.NewGenesisBlock([]byte{})
|
|
bodyRoot, err := genesisBlock.Block.HashTreeRoot()
|
|
require.NoError(t, err)
|
|
err = beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{
|
|
Slot: genesisBlock.Block.Slot,
|
|
ParentRoot: genesisBlock.Block.ParentRoot,
|
|
StateRoot: params.BeaconConfig().ZeroHash[:],
|
|
BodyRoot: bodyRoot[:],
|
|
})
|
|
require.NoError(t, err)
|
|
require.NoError(t, beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)))
|
|
cp := beaconState.CurrentJustifiedCheckpoint()
|
|
mockRoot := [32]byte{}
|
|
copy(mockRoot[:], "hello-world")
|
|
cp.Root = mockRoot[:]
|
|
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cp))
|
|
require.NoError(t, beaconState.AppendCurrentEpochAttestations(ðpb.PendingAttestation{}))
|
|
|
|
service := New(beaconDB)
|
|
targetSlot := params.BeaconConfig().SlotsPerEpoch - 1
|
|
newState, err := service.ReplayBlocks(context.Background(), beaconState, []block.SignedBeaconBlock{}, targetSlot)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, targetSlot, newState.Slot(), "Did not advance slots")
|
|
}
|
|
|
|
func TestReplayBlocks_SameSlot(t *testing.T) {
|
|
beaconDB := testDB.SetupDB(t)
|
|
|
|
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
|
|
genesisBlock := blocks.NewGenesisBlock([]byte{})
|
|
bodyRoot, err := genesisBlock.Block.HashTreeRoot()
|
|
require.NoError(t, err)
|
|
err = beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{
|
|
Slot: genesisBlock.Block.Slot,
|
|
ParentRoot: genesisBlock.Block.ParentRoot,
|
|
StateRoot: params.BeaconConfig().ZeroHash[:],
|
|
BodyRoot: bodyRoot[:],
|
|
})
|
|
require.NoError(t, err)
|
|
require.NoError(t, beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)))
|
|
cp := beaconState.CurrentJustifiedCheckpoint()
|
|
mockRoot := [32]byte{}
|
|
copy(mockRoot[:], "hello-world")
|
|
cp.Root = mockRoot[:]
|
|
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cp))
|
|
require.NoError(t, beaconState.AppendCurrentEpochAttestations(ðpb.PendingAttestation{}))
|
|
|
|
service := New(beaconDB)
|
|
targetSlot := beaconState.Slot()
|
|
newState, err := service.ReplayBlocks(context.Background(), beaconState, []block.SignedBeaconBlock{}, targetSlot)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, targetSlot, newState.Slot(), "Did not advance slots")
|
|
}
|
|
|
|
func TestReplayBlocks_LowerSlotBlock(t *testing.T) {
|
|
beaconDB := testDB.SetupDB(t)
|
|
|
|
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
|
|
require.NoError(t, beaconState.SetSlot(1))
|
|
genesisBlock := blocks.NewGenesisBlock([]byte{})
|
|
bodyRoot, err := genesisBlock.Block.HashTreeRoot()
|
|
require.NoError(t, err)
|
|
err = beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{
|
|
Slot: genesisBlock.Block.Slot,
|
|
ParentRoot: genesisBlock.Block.ParentRoot,
|
|
StateRoot: params.BeaconConfig().ZeroHash[:],
|
|
BodyRoot: bodyRoot[:],
|
|
})
|
|
require.NoError(t, err)
|
|
require.NoError(t, beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)))
|
|
cp := beaconState.CurrentJustifiedCheckpoint()
|
|
mockRoot := [32]byte{}
|
|
copy(mockRoot[:], "hello-world")
|
|
cp.Root = mockRoot[:]
|
|
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cp))
|
|
require.NoError(t, beaconState.AppendCurrentEpochAttestations(ðpb.PendingAttestation{}))
|
|
|
|
service := New(beaconDB)
|
|
targetSlot := beaconState.Slot()
|
|
b := testutil.NewBeaconBlock()
|
|
b.Block.Slot = beaconState.Slot() - 1
|
|
newState, err := service.ReplayBlocks(context.Background(), beaconState, []block.SignedBeaconBlock{wrapper.WrappedPhase0SignedBeaconBlock(b)}, targetSlot)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, targetSlot, newState.Slot(), "Did not advance slots")
|
|
}
|
|
|
|
func TestReplayBlocks_ThroughForkBoundary(t *testing.T) {
|
|
params.SetupTestConfigCleanup(t)
|
|
bCfg := params.BeaconConfig()
|
|
bCfg.AltairForkEpoch = 1
|
|
bCfg.ForkVersionSchedule[bytesutil.ToBytes4(bCfg.AltairForkVersion)] = 1
|
|
params.OverrideBeaconConfig(bCfg)
|
|
|
|
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
|
|
genesisBlock := blocks.NewGenesisBlock([]byte{})
|
|
bodyRoot, err := genesisBlock.Block.HashTreeRoot()
|
|
require.NoError(t, err)
|
|
err = beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{
|
|
Slot: genesisBlock.Block.Slot,
|
|
ParentRoot: genesisBlock.Block.ParentRoot,
|
|
StateRoot: params.BeaconConfig().ZeroHash[:],
|
|
BodyRoot: bodyRoot[:],
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
service := New(testDB.SetupDB(t))
|
|
targetSlot := params.BeaconConfig().SlotsPerEpoch
|
|
newState, err := service.ReplayBlocks(context.Background(), beaconState, []block.SignedBeaconBlock{}, targetSlot)
|
|
require.NoError(t, err)
|
|
|
|
// Verify state is version Altair.
|
|
assert.Equal(t, version.Altair, newState.Version())
|
|
}
|
|
|
|
func TestLoadBlocks_FirstBranch(t *testing.T) {
|
|
beaconDB := testDB.SetupDB(t)
|
|
ctx := context.Background()
|
|
s := &State{
|
|
beaconDB: beaconDB,
|
|
}
|
|
|
|
roots, savedBlocks, err := tree1(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32))
|
|
require.NoError(t, err)
|
|
|
|
filteredBlocks, err := s.LoadBlocks(ctx, 0, 8, roots[len(roots)-1])
|
|
require.NoError(t, err)
|
|
|
|
wanted := []*ethpb.SignedBeaconBlock{
|
|
savedBlocks[8],
|
|
savedBlocks[6],
|
|
savedBlocks[4],
|
|
savedBlocks[2],
|
|
savedBlocks[1],
|
|
savedBlocks[0],
|
|
}
|
|
|
|
for i, block := range wanted {
|
|
if !proto.Equal(block, filteredBlocks[i].Proto()) {
|
|
t.Error("Did not get wanted blocks")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLoadBlocks_SecondBranch(t *testing.T) {
|
|
beaconDB := testDB.SetupDB(t)
|
|
ctx := context.Background()
|
|
s := &State{
|
|
beaconDB: beaconDB,
|
|
}
|
|
|
|
roots, savedBlocks, err := tree1(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32))
|
|
require.NoError(t, err)
|
|
|
|
filteredBlocks, err := s.LoadBlocks(ctx, 0, 5, roots[5])
|
|
require.NoError(t, err)
|
|
|
|
wanted := []*ethpb.SignedBeaconBlock{
|
|
savedBlocks[5],
|
|
savedBlocks[3],
|
|
savedBlocks[1],
|
|
savedBlocks[0],
|
|
}
|
|
|
|
for i, block := range wanted {
|
|
if !proto.Equal(block, filteredBlocks[i].Proto()) {
|
|
t.Error("Did not get wanted blocks")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLoadBlocks_ThirdBranch(t *testing.T) {
|
|
beaconDB := testDB.SetupDB(t)
|
|
ctx := context.Background()
|
|
s := &State{
|
|
beaconDB: beaconDB,
|
|
}
|
|
|
|
roots, savedBlocks, err := tree1(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32))
|
|
require.NoError(t, err)
|
|
|
|
filteredBlocks, err := s.LoadBlocks(ctx, 0, 7, roots[7])
|
|
require.NoError(t, err)
|
|
|
|
wanted := []*ethpb.SignedBeaconBlock{
|
|
savedBlocks[7],
|
|
savedBlocks[6],
|
|
savedBlocks[4],
|
|
savedBlocks[2],
|
|
savedBlocks[1],
|
|
savedBlocks[0],
|
|
}
|
|
|
|
for i, block := range wanted {
|
|
if !proto.Equal(block, filteredBlocks[i].Proto()) {
|
|
t.Error("Did not get wanted blocks")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLoadBlocks_SameSlots(t *testing.T) {
|
|
beaconDB := testDB.SetupDB(t)
|
|
ctx := context.Background()
|
|
s := &State{
|
|
beaconDB: beaconDB,
|
|
}
|
|
|
|
roots, savedBlocks, err := tree2(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32))
|
|
require.NoError(t, err)
|
|
|
|
filteredBlocks, err := s.LoadBlocks(ctx, 0, 3, roots[6])
|
|
require.NoError(t, err)
|
|
|
|
wanted := []*ethpb.SignedBeaconBlock{
|
|
savedBlocks[6],
|
|
savedBlocks[5],
|
|
savedBlocks[1],
|
|
savedBlocks[0],
|
|
}
|
|
|
|
for i, block := range wanted {
|
|
if !proto.Equal(block, filteredBlocks[i].Proto()) {
|
|
t.Error("Did not get wanted blocks")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLoadBlocks_SameEndSlots(t *testing.T) {
|
|
beaconDB := testDB.SetupDB(t)
|
|
ctx := context.Background()
|
|
s := &State{
|
|
beaconDB: beaconDB,
|
|
}
|
|
|
|
roots, savedBlocks, err := tree3(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32))
|
|
require.NoError(t, err)
|
|
|
|
filteredBlocks, err := s.LoadBlocks(ctx, 0, 2, roots[2])
|
|
require.NoError(t, err)
|
|
|
|
wanted := []*ethpb.SignedBeaconBlock{
|
|
savedBlocks[2],
|
|
savedBlocks[1],
|
|
savedBlocks[0],
|
|
}
|
|
|
|
for i, block := range wanted {
|
|
if !proto.Equal(block, filteredBlocks[i].Proto()) {
|
|
t.Error("Did not get wanted blocks")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLoadBlocks_SameEndSlotsWith2blocks(t *testing.T) {
|
|
beaconDB := testDB.SetupDB(t)
|
|
ctx := context.Background()
|
|
s := &State{
|
|
beaconDB: beaconDB,
|
|
}
|
|
|
|
roots, savedBlocks, err := tree4(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32))
|
|
require.NoError(t, err)
|
|
|
|
filteredBlocks, err := s.LoadBlocks(ctx, 0, 2, roots[1])
|
|
require.NoError(t, err)
|
|
|
|
wanted := []*ethpb.SignedBeaconBlock{
|
|
savedBlocks[1],
|
|
savedBlocks[0],
|
|
}
|
|
|
|
for i, block := range wanted {
|
|
if !proto.Equal(block, filteredBlocks[i].Proto()) {
|
|
t.Error("Did not get wanted blocks")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLoadBlocks_BadStart(t *testing.T) {
|
|
beaconDB := testDB.SetupDB(t)
|
|
ctx := context.Background()
|
|
s := &State{
|
|
beaconDB: beaconDB,
|
|
}
|
|
|
|
roots, _, err := tree1(t, beaconDB, bytesutil.PadTo([]byte{'A'}, 32))
|
|
require.NoError(t, err)
|
|
_, err = s.LoadBlocks(ctx, 0, 5, roots[8])
|
|
assert.ErrorContains(t, "end block roots don't match", err)
|
|
}
|
|
|
|
func TestLastSavedBlock_Genesis(t *testing.T) {
|
|
beaconDB := testDB.SetupDB(t)
|
|
ctx := context.Background()
|
|
s := &State{
|
|
beaconDB: beaconDB,
|
|
finalizedInfo: &finalizedInfo{slot: 128},
|
|
}
|
|
|
|
gBlk := testutil.NewBeaconBlock()
|
|
gRoot, err := gBlk.Block.HashTreeRoot()
|
|
require.NoError(t, err)
|
|
require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(gBlk)))
|
|
require.NoError(t, s.beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
|
|
|
|
savedRoot, savedSlot, err := s.lastSavedBlock(ctx, 0)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, types.Slot(0), savedSlot, "Did not save genesis slot")
|
|
assert.Equal(t, savedRoot, savedRoot, "Did not save genesis root")
|
|
}
|
|
|
|
func TestLastSavedBlock_CanGet(t *testing.T) {
|
|
beaconDB := testDB.SetupDB(t)
|
|
ctx := context.Background()
|
|
s := &State{
|
|
beaconDB: beaconDB,
|
|
finalizedInfo: &finalizedInfo{slot: 128},
|
|
}
|
|
|
|
b1 := testutil.NewBeaconBlock()
|
|
b1.Block.Slot = s.finalizedInfo.slot + 5
|
|
require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1)))
|
|
b2 := testutil.NewBeaconBlock()
|
|
b2.Block.Slot = s.finalizedInfo.slot + 10
|
|
require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b2)))
|
|
b3 := testutil.NewBeaconBlock()
|
|
b3.Block.Slot = s.finalizedInfo.slot + 20
|
|
require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b3)))
|
|
|
|
savedRoot, savedSlot, err := s.lastSavedBlock(ctx, s.finalizedInfo.slot+100)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, s.finalizedInfo.slot+20, savedSlot)
|
|
wantedRoot, err := b3.Block.HashTreeRoot()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, wantedRoot, savedRoot, "Did not save correct root")
|
|
}
|
|
|
|
func TestLastSavedBlock_NoSavedBlock(t *testing.T) {
|
|
beaconDB := testDB.SetupDB(t)
|
|
ctx := context.Background()
|
|
s := &State{
|
|
beaconDB: beaconDB,
|
|
finalizedInfo: &finalizedInfo{slot: 128},
|
|
}
|
|
|
|
root, slot, err := s.lastSavedBlock(ctx, s.finalizedInfo.slot+1)
|
|
require.NoError(t, err)
|
|
if slot != 0 && root != [32]byte{} {
|
|
t.Error("Did not get wanted block")
|
|
}
|
|
}
|
|
|
|
func TestLastSavedState_Genesis(t *testing.T) {
|
|
beaconDB := testDB.SetupDB(t)
|
|
ctx := context.Background()
|
|
s := &State{
|
|
beaconDB: beaconDB,
|
|
finalizedInfo: &finalizedInfo{slot: 128},
|
|
}
|
|
|
|
gBlk := testutil.NewBeaconBlock()
|
|
gState, err := testutil.NewBeaconState()
|
|
require.NoError(t, err)
|
|
gRoot, err := gBlk.Block.HashTreeRoot()
|
|
require.NoError(t, err)
|
|
require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(gBlk)))
|
|
require.NoError(t, s.beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
|
|
require.NoError(t, s.beaconDB.SaveState(ctx, gState, gRoot))
|
|
|
|
savedState, err := s.lastSavedState(ctx, 0)
|
|
require.NoError(t, err)
|
|
require.DeepSSZEqual(t, gState.InnerStateUnsafe(), savedState.InnerStateUnsafe())
|
|
}
|
|
|
|
func TestLastSavedState_CanGet(t *testing.T) {
|
|
beaconDB := testDB.SetupDB(t)
|
|
ctx := context.Background()
|
|
s := &State{
|
|
beaconDB: beaconDB,
|
|
finalizedInfo: &finalizedInfo{slot: 128},
|
|
}
|
|
|
|
b1 := testutil.NewBeaconBlock()
|
|
b1.Block.Slot = s.finalizedInfo.slot + 5
|
|
require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1)))
|
|
b2 := testutil.NewBeaconBlock()
|
|
b2.Block.Slot = s.finalizedInfo.slot + 10
|
|
require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b2)))
|
|
b2Root, err := b2.Block.HashTreeRoot()
|
|
require.NoError(t, err)
|
|
st, err := testutil.NewBeaconState()
|
|
require.NoError(t, err)
|
|
require.NoError(t, st.SetSlot(s.finalizedInfo.slot+10))
|
|
|
|
require.NoError(t, s.beaconDB.SaveState(ctx, st, b2Root))
|
|
b3 := testutil.NewBeaconBlock()
|
|
b3.Block.Slot = s.finalizedInfo.slot + 20
|
|
require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b3)))
|
|
|
|
savedState, err := s.lastSavedState(ctx, s.finalizedInfo.slot+100)
|
|
require.NoError(t, err)
|
|
require.DeepSSZEqual(t, st.InnerStateUnsafe(), savedState.InnerStateUnsafe())
|
|
}
|
|
|
|
func TestLastSavedState_NoSavedBlockState(t *testing.T) {
|
|
beaconDB := testDB.SetupDB(t)
|
|
ctx := context.Background()
|
|
s := &State{
|
|
beaconDB: beaconDB,
|
|
finalizedInfo: &finalizedInfo{slot: 128},
|
|
}
|
|
|
|
b1 := testutil.NewBeaconBlock()
|
|
b1.Block.Slot = 127
|
|
require.NoError(t, s.beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1)))
|
|
|
|
_, err := s.lastSavedState(ctx, s.finalizedInfo.slot+1)
|
|
assert.ErrorContains(t, errUnknownState.Error(), err)
|
|
}
|
|
|
|
// tree1 constructs the following tree:
|
|
// B0 - B1 - - B3 -- B5
|
|
// \- B2 -- B4 -- B6 ----- B8
|
|
// \- B7
|
|
func tree1(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) {
|
|
b0 := testutil.NewBeaconBlock()
|
|
b0.Block.Slot = 0
|
|
b0.Block.ParentRoot = genesisRoot
|
|
r0, err := b0.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b1 := testutil.NewBeaconBlock()
|
|
b1.Block.Slot = 1
|
|
b1.Block.ParentRoot = r0[:]
|
|
r1, err := b1.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b2 := testutil.NewBeaconBlock()
|
|
b2.Block.Slot = 2
|
|
b2.Block.ParentRoot = r1[:]
|
|
r2, err := b2.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b3 := testutil.NewBeaconBlock()
|
|
b3.Block.Slot = 3
|
|
b3.Block.ParentRoot = r1[:]
|
|
r3, err := b3.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b4 := testutil.NewBeaconBlock()
|
|
b4.Block.Slot = 4
|
|
b4.Block.ParentRoot = r2[:]
|
|
r4, err := b4.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b5 := testutil.NewBeaconBlock()
|
|
b5.Block.Slot = 5
|
|
b5.Block.ParentRoot = r3[:]
|
|
r5, err := b5.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b6 := testutil.NewBeaconBlock()
|
|
b6.Block.Slot = 6
|
|
b6.Block.ParentRoot = r4[:]
|
|
r6, err := b6.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b7 := testutil.NewBeaconBlock()
|
|
b7.Block.Slot = 7
|
|
b7.Block.ParentRoot = r6[:]
|
|
r7, err := b7.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b8 := testutil.NewBeaconBlock()
|
|
b8.Block.Slot = 8
|
|
b8.Block.ParentRoot = r6[:]
|
|
r8, err := b8.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
st, err := testutil.NewBeaconState()
|
|
require.NoError(t, err)
|
|
|
|
returnedBlocks := make([]*ethpb.SignedBeaconBlock, 0)
|
|
for _, b := range []*ethpb.SignedBeaconBlock{b0, b1, b2, b3, b4, b5, b6, b7, b8} {
|
|
beaconBlock := testutil.NewBeaconBlock()
|
|
beaconBlock.Block.Slot = b.Block.Slot
|
|
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
|
|
if err := beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock)); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
returnedBlocks = append(returnedBlocks, beaconBlock)
|
|
}
|
|
return [][32]byte{r0, r1, r2, r3, r4, r5, r6, r7, r8}, returnedBlocks, nil
|
|
}
|
|
|
|
// tree2 constructs the following tree:
|
|
// B0 - B1
|
|
// \- B2
|
|
// \- B2
|
|
// \- B2
|
|
// \- B2 -- B3
|
|
func tree2(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) {
|
|
b0 := testutil.NewBeaconBlock()
|
|
b0.Block.Slot = 0
|
|
b0.Block.ParentRoot = genesisRoot
|
|
r0, err := b0.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b1 := testutil.NewBeaconBlock()
|
|
b1.Block.Slot = 1
|
|
b1.Block.ParentRoot = r0[:]
|
|
r1, err := b1.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b21 := testutil.NewBeaconBlock()
|
|
b21.Block.Slot = 2
|
|
b21.Block.ParentRoot = r1[:]
|
|
b21.Block.StateRoot = bytesutil.PadTo([]byte{'A'}, 32)
|
|
r21, err := b21.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b22 := testutil.NewBeaconBlock()
|
|
b22.Block.Slot = 2
|
|
b22.Block.ParentRoot = r1[:]
|
|
b22.Block.StateRoot = bytesutil.PadTo([]byte{'B'}, 32)
|
|
r22, err := b22.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b23 := testutil.NewBeaconBlock()
|
|
b23.Block.Slot = 2
|
|
b23.Block.ParentRoot = r1[:]
|
|
b23.Block.StateRoot = bytesutil.PadTo([]byte{'C'}, 32)
|
|
r23, err := b23.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b24 := testutil.NewBeaconBlock()
|
|
b24.Block.Slot = 2
|
|
b24.Block.ParentRoot = r1[:]
|
|
b24.Block.StateRoot = bytesutil.PadTo([]byte{'D'}, 32)
|
|
r24, err := b24.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b3 := testutil.NewBeaconBlock()
|
|
b3.Block.Slot = 3
|
|
b3.Block.ParentRoot = r24[:]
|
|
r3, err := b3.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
st, err := testutil.NewBeaconState()
|
|
require.NoError(t, err)
|
|
|
|
returnedBlocks := make([]*ethpb.SignedBeaconBlock, 0)
|
|
for _, b := range []*ethpb.SignedBeaconBlock{b0, b1, b21, b22, b23, b24, b3} {
|
|
beaconBlock := testutil.NewBeaconBlock()
|
|
beaconBlock.Block.Slot = b.Block.Slot
|
|
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
|
|
beaconBlock.Block.StateRoot = bytesutil.PadTo(b.Block.StateRoot, 32)
|
|
if err := beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock)); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
returnedBlocks = append(returnedBlocks, beaconBlock)
|
|
}
|
|
return [][32]byte{r0, r1, r21, r22, r23, r24, r3}, returnedBlocks, nil
|
|
}
|
|
|
|
// tree3 constructs the following tree:
|
|
// B0 - B1
|
|
// \- B2
|
|
// \- B2
|
|
// \- B2
|
|
// \- B2
|
|
func tree3(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) {
|
|
b0 := testutil.NewBeaconBlock()
|
|
b0.Block.Slot = 0
|
|
b0.Block.ParentRoot = genesisRoot
|
|
r0, err := b0.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b1 := testutil.NewBeaconBlock()
|
|
b1.Block.Slot = 1
|
|
b1.Block.ParentRoot = r0[:]
|
|
r1, err := b1.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b21 := testutil.NewBeaconBlock()
|
|
b21.Block.Slot = 2
|
|
b21.Block.ParentRoot = r1[:]
|
|
b21.Block.StateRoot = bytesutil.PadTo([]byte{'A'}, 32)
|
|
r21, err := b21.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b22 := testutil.NewBeaconBlock()
|
|
b22.Block.Slot = 2
|
|
b22.Block.ParentRoot = r1[:]
|
|
b22.Block.StateRoot = bytesutil.PadTo([]byte{'B'}, 32)
|
|
r22, err := b22.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b23 := testutil.NewBeaconBlock()
|
|
b23.Block.Slot = 2
|
|
b23.Block.ParentRoot = r1[:]
|
|
b23.Block.StateRoot = bytesutil.PadTo([]byte{'C'}, 32)
|
|
r23, err := b23.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b24 := testutil.NewBeaconBlock()
|
|
b24.Block.Slot = 2
|
|
b24.Block.ParentRoot = r1[:]
|
|
b24.Block.StateRoot = bytesutil.PadTo([]byte{'D'}, 32)
|
|
r24, err := b24.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
st, err := testutil.NewBeaconState()
|
|
require.NoError(t, err)
|
|
|
|
returnedBlocks := make([]*ethpb.SignedBeaconBlock, 0)
|
|
for _, b := range []*ethpb.SignedBeaconBlock{b0, b1, b21, b22, b23, b24} {
|
|
beaconBlock := testutil.NewBeaconBlock()
|
|
beaconBlock.Block.Slot = b.Block.Slot
|
|
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
|
|
beaconBlock.Block.StateRoot = bytesutil.PadTo(b.Block.StateRoot, 32)
|
|
if err := beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock)); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
returnedBlocks = append(returnedBlocks, beaconBlock)
|
|
}
|
|
|
|
return [][32]byte{r0, r1, r21, r22, r23, r24}, returnedBlocks, nil
|
|
}
|
|
|
|
// tree4 constructs the following tree:
|
|
// B0
|
|
// \- B2
|
|
// \- B2
|
|
// \- B2
|
|
// \- B2
|
|
func tree4(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][32]byte, []*ethpb.SignedBeaconBlock, error) {
|
|
b0 := testutil.NewBeaconBlock()
|
|
b0.Block.Slot = 0
|
|
b0.Block.ParentRoot = genesisRoot
|
|
r0, err := b0.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b21 := testutil.NewBeaconBlock()
|
|
b21.Block.Slot = 2
|
|
b21.Block.ParentRoot = r0[:]
|
|
b21.Block.StateRoot = bytesutil.PadTo([]byte{'A'}, 32)
|
|
r21, err := b21.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b22 := testutil.NewBeaconBlock()
|
|
b22.Block.Slot = 2
|
|
b22.Block.ParentRoot = r0[:]
|
|
b22.Block.StateRoot = bytesutil.PadTo([]byte{'B'}, 32)
|
|
r22, err := b22.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b23 := testutil.NewBeaconBlock()
|
|
b23.Block.Slot = 2
|
|
b23.Block.ParentRoot = r0[:]
|
|
b23.Block.StateRoot = bytesutil.PadTo([]byte{'C'}, 32)
|
|
r23, err := b23.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
b24 := testutil.NewBeaconBlock()
|
|
b24.Block.Slot = 2
|
|
b24.Block.ParentRoot = r0[:]
|
|
b24.Block.StateRoot = bytesutil.PadTo([]byte{'D'}, 32)
|
|
r24, err := b24.Block.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
st, err := testutil.NewBeaconState()
|
|
require.NoError(t, err)
|
|
|
|
returnedBlocks := make([]*ethpb.SignedBeaconBlock, 0)
|
|
for _, b := range []*ethpb.SignedBeaconBlock{b0, b21, b22, b23, b24} {
|
|
beaconBlock := testutil.NewBeaconBlock()
|
|
beaconBlock.Block.Slot = b.Block.Slot
|
|
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
|
|
beaconBlock.Block.StateRoot = bytesutil.PadTo(b.Block.StateRoot, 32)
|
|
if err := beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(beaconBlock)); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if err := beaconDB.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
returnedBlocks = append(returnedBlocks, beaconBlock)
|
|
}
|
|
|
|
return [][32]byte{r0, r21, r22, r23, r24}, returnedBlocks, nil
|
|
}
|
|
|
|
func TestLoadFinalizedBlocks(t *testing.T) {
|
|
beaconDB := testDB.SetupDB(t)
|
|
ctx := context.Background()
|
|
s := &State{
|
|
beaconDB: beaconDB,
|
|
}
|
|
gBlock := testutil.NewBeaconBlock()
|
|
gRoot, err := gBlock.Block.HashTreeRoot()
|
|
require.NoError(t, err)
|
|
require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(gBlock)))
|
|
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, [32]byte{}))
|
|
roots, _, err := tree1(t, beaconDB, gRoot[:])
|
|
require.NoError(t, err)
|
|
|
|
filteredBlocks, err := s.loadFinalizedBlocks(ctx, 0, 8)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 0, len(filteredBlocks))
|
|
require.NoError(t, beaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Root: roots[8][:]}))
|
|
|
|
require.NoError(t, s.beaconDB.SaveFinalizedCheckpoint(ctx, ðpb.Checkpoint{Root: roots[8][:]}))
|
|
filteredBlocks, err = s.loadFinalizedBlocks(ctx, 0, 8)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 10, len(filteredBlocks))
|
|
}
|