mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 21:38:05 -05:00
837 lines
23 KiB
Go
837 lines
23 KiB
Go
package detect
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/OffchainLabs/prysm/v7/beacon-chain/state"
|
|
"github.com/OffchainLabs/prysm/v7/config/params"
|
|
"github.com/OffchainLabs/prysm/v7/consensus-types/blocks"
|
|
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
|
|
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
|
"github.com/OffchainLabs/prysm/v7/encoding/bytesutil"
|
|
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
|
|
"github.com/OffchainLabs/prysm/v7/runtime/version"
|
|
"github.com/OffchainLabs/prysm/v7/testing/require"
|
|
"github.com/OffchainLabs/prysm/v7/testing/util"
|
|
"github.com/OffchainLabs/prysm/v7/time/slots"
|
|
)
|
|
|
|
func TestSlotFromBlock(t *testing.T) {
|
|
b := util.NewBeaconBlock()
|
|
var slot primitives.Slot = 3
|
|
b.Block.Slot = slot
|
|
bb, err := b.MarshalSSZ()
|
|
require.NoError(t, err)
|
|
sfb, err := slotFromBlock(bb)
|
|
require.NoError(t, err)
|
|
require.Equal(t, slot, sfb)
|
|
|
|
ba := util.NewBeaconBlockAltair()
|
|
ba.Block.Slot = slot
|
|
bab, err := ba.MarshalSSZ()
|
|
require.NoError(t, err)
|
|
sfba, err := slotFromBlock(bab)
|
|
require.NoError(t, err)
|
|
require.Equal(t, slot, sfba)
|
|
|
|
bm := util.NewBeaconBlockBellatrix()
|
|
bm.Block.Slot = slot
|
|
bmb, err := ba.MarshalSSZ()
|
|
require.NoError(t, err)
|
|
sfbm, err := slotFromBlock(bmb)
|
|
require.NoError(t, err)
|
|
require.Equal(t, slot, sfbm)
|
|
}
|
|
|
|
func TestByState(t *testing.T) {
|
|
defer util.HackForksMaxuint(t, []int{version.Electra, version.Fulu})()
|
|
|
|
bc := params.BeaconConfig()
|
|
altairSlot, err := slots.EpochStart(bc.AltairForkEpoch)
|
|
require.NoError(t, err)
|
|
bellaSlot, err := slots.EpochStart(bc.BellatrixForkEpoch)
|
|
require.NoError(t, err)
|
|
capellaSlot, err := slots.EpochStart(bc.CapellaForkEpoch)
|
|
require.NoError(t, err)
|
|
denebSlot, err := slots.EpochStart(bc.DenebForkEpoch)
|
|
require.NoError(t, err)
|
|
electraSlot, err := slots.EpochStart(bc.ElectraForkEpoch)
|
|
require.NoError(t, err)
|
|
fuluSlot, err := slots.EpochStart(bc.FuluForkEpoch)
|
|
require.NoError(t, err)
|
|
cases := []struct {
|
|
name string
|
|
version int
|
|
slot primitives.Slot
|
|
forkversion [4]byte
|
|
}{
|
|
{
|
|
name: "genesis",
|
|
version: version.Phase0,
|
|
slot: 0,
|
|
forkversion: bytesutil.ToBytes4(bc.GenesisForkVersion),
|
|
},
|
|
{
|
|
name: "altair",
|
|
version: version.Altair,
|
|
slot: altairSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.AltairForkVersion),
|
|
},
|
|
{
|
|
name: "bellatrix",
|
|
version: version.Bellatrix,
|
|
slot: bellaSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.BellatrixForkVersion),
|
|
},
|
|
{
|
|
name: "capella",
|
|
version: version.Capella,
|
|
slot: capellaSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.CapellaForkVersion),
|
|
},
|
|
{
|
|
name: "deneb",
|
|
version: version.Deneb,
|
|
slot: denebSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.DenebForkVersion),
|
|
},
|
|
{
|
|
name: "electra",
|
|
version: version.Electra,
|
|
slot: electraSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.ElectraForkVersion),
|
|
},
|
|
{
|
|
name: "fulu",
|
|
version: version.Fulu,
|
|
slot: fuluSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.FuluForkVersion),
|
|
},
|
|
}
|
|
for _, c := range cases {
|
|
st, err := stateForVersion(c.version)
|
|
require.NoError(t, err)
|
|
fork, err := params.Fork(slots.ToEpoch(c.slot))
|
|
require.NoError(t, err)
|
|
require.NoError(t, st.SetFork(fork))
|
|
require.NoError(t, st.SetSlot(c.slot))
|
|
m, err := st.MarshalSSZ()
|
|
require.NoError(t, err)
|
|
cf, err := FromState(m)
|
|
require.NoError(t, err)
|
|
require.Equal(t, c.version, cf.Fork)
|
|
require.Equal(t, c.forkversion, cf.Version)
|
|
require.Equal(t, bc.ConfigName, cf.Config.ConfigName)
|
|
}
|
|
}
|
|
|
|
func stateForVersion(v int) (state.BeaconState, error) {
|
|
switch v {
|
|
case version.Phase0:
|
|
return util.NewBeaconState()
|
|
case version.Altair:
|
|
return util.NewBeaconStateAltair()
|
|
case version.Bellatrix:
|
|
return util.NewBeaconStateBellatrix()
|
|
case version.Capella:
|
|
return util.NewBeaconStateCapella()
|
|
case version.Deneb:
|
|
return util.NewBeaconStateDeneb()
|
|
case version.Electra:
|
|
return util.NewBeaconStateElectra()
|
|
case version.Fulu:
|
|
return util.NewBeaconStateFulu()
|
|
default:
|
|
return nil, fmt.Errorf("unrecognized version %d", v)
|
|
}
|
|
}
|
|
|
|
func TestUnmarshalState(t *testing.T) {
|
|
ctx := t.Context()
|
|
defer util.HackForksMaxuint(t, []int{version.Electra, version.Fulu})()
|
|
|
|
bc := params.BeaconConfig()
|
|
altairSlot, err := slots.EpochStart(bc.AltairForkEpoch)
|
|
require.NoError(t, err)
|
|
bellaSlot, err := slots.EpochStart(bc.BellatrixForkEpoch)
|
|
require.NoError(t, err)
|
|
capellaSlot, err := slots.EpochStart(bc.CapellaForkEpoch)
|
|
require.NoError(t, err)
|
|
denebSlot, err := slots.EpochStart(bc.DenebForkEpoch)
|
|
require.NoError(t, err)
|
|
electraSlot, err := slots.EpochStart(bc.ElectraForkEpoch)
|
|
require.NoError(t, err)
|
|
fuluSlot, err := slots.EpochStart(bc.FuluForkEpoch)
|
|
require.NoError(t, err)
|
|
cases := []struct {
|
|
name string
|
|
version int
|
|
slot primitives.Slot
|
|
forkversion [4]byte
|
|
}{
|
|
{
|
|
name: "genesis",
|
|
version: version.Phase0,
|
|
slot: 0,
|
|
forkversion: bytesutil.ToBytes4(bc.GenesisForkVersion),
|
|
},
|
|
{
|
|
name: "altair",
|
|
version: version.Altair,
|
|
slot: altairSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.AltairForkVersion),
|
|
},
|
|
{
|
|
name: "bellatrix",
|
|
version: version.Bellatrix,
|
|
slot: bellaSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.BellatrixForkVersion),
|
|
},
|
|
{
|
|
name: "capella",
|
|
version: version.Capella,
|
|
slot: capellaSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.CapellaForkVersion),
|
|
},
|
|
{
|
|
name: "deneb",
|
|
version: version.Deneb,
|
|
slot: denebSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.DenebForkVersion),
|
|
},
|
|
{
|
|
name: "electra",
|
|
version: version.Electra,
|
|
slot: electraSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.ElectraForkVersion),
|
|
},
|
|
{
|
|
name: "fulu",
|
|
version: version.Fulu,
|
|
slot: fuluSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.FuluForkVersion),
|
|
},
|
|
}
|
|
for _, c := range cases {
|
|
st, err := stateForVersion(c.version)
|
|
require.NoError(t, err)
|
|
require.NoError(t, st.SetFork(ðpb.Fork{
|
|
PreviousVersion: make([]byte, 4),
|
|
CurrentVersion: c.forkversion[:],
|
|
Epoch: 0,
|
|
}))
|
|
require.NoError(t, st.SetSlot(c.slot))
|
|
m, err := st.MarshalSSZ()
|
|
require.NoError(t, err)
|
|
cf, err := FromState(m)
|
|
require.NoError(t, err)
|
|
s, err := cf.UnmarshalBeaconState(m)
|
|
require.NoError(t, err)
|
|
expected, err := st.HashTreeRoot(ctx)
|
|
require.NoError(t, err)
|
|
actual, err := s.HashTreeRoot(ctx)
|
|
require.NoError(t, err)
|
|
require.DeepEqual(t, expected, actual)
|
|
}
|
|
}
|
|
|
|
func TestDetectAndUnmarshalBlock(t *testing.T) {
|
|
defer util.HackForksMaxuint(t, []int{version.Electra, version.Fulu})()
|
|
|
|
altairS, err := slots.EpochStart(params.BeaconConfig().AltairForkEpoch)
|
|
require.NoError(t, err)
|
|
bellaS, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch)
|
|
require.NoError(t, err)
|
|
capellaS, err := slots.EpochStart(params.BeaconConfig().CapellaForkEpoch)
|
|
require.NoError(t, err)
|
|
denebS, err := slots.EpochStart(params.BeaconConfig().DenebForkEpoch)
|
|
require.NoError(t, err)
|
|
electraS, err := slots.EpochStart(params.BeaconConfig().ElectraForkEpoch)
|
|
require.NoError(t, err)
|
|
fuluS, err := slots.EpochStart(params.BeaconConfig().FuluForkEpoch)
|
|
require.NoError(t, err)
|
|
cases := []struct {
|
|
b func(*testing.T, primitives.Slot) interfaces.ReadOnlySignedBeaconBlock
|
|
name string
|
|
slot primitives.Slot
|
|
errExists bool
|
|
}{
|
|
{
|
|
name: "genesis - slot 0",
|
|
b: signedTestBlockGenesis,
|
|
},
|
|
{
|
|
name: "last slot of phase 0",
|
|
b: signedTestBlockGenesis,
|
|
slot: altairS - 1,
|
|
},
|
|
{
|
|
name: "first slot of altair",
|
|
b: signedTestBlockAltair,
|
|
slot: altairS,
|
|
},
|
|
{
|
|
name: "last slot of altair",
|
|
b: signedTestBlockAltair,
|
|
slot: bellaS - 1,
|
|
},
|
|
{
|
|
name: "first slot of bellatrix",
|
|
b: signedTestBlockBellatrix,
|
|
slot: bellaS,
|
|
},
|
|
{
|
|
name: "first slot of capella",
|
|
b: signedTestBlockCapella,
|
|
slot: capellaS,
|
|
},
|
|
{
|
|
name: "last slot of capella",
|
|
b: signedTestBlockCapella,
|
|
slot: denebS - 1,
|
|
},
|
|
{
|
|
name: "first slot of deneb",
|
|
b: signedTestBlockDeneb,
|
|
slot: denebS,
|
|
},
|
|
{
|
|
name: "first slot of electra",
|
|
b: signedTestBlockElectra,
|
|
slot: electraS,
|
|
},
|
|
{
|
|
name: "first slot of fulu",
|
|
b: signedTestBlockFulu,
|
|
slot: fuluS,
|
|
},
|
|
{
|
|
name: "bellatrix block in altair slot",
|
|
b: signedTestBlockBellatrix,
|
|
slot: bellaS - 1,
|
|
errExists: true,
|
|
},
|
|
{
|
|
name: "genesis block in altair slot",
|
|
b: signedTestBlockGenesis,
|
|
slot: bellaS - 1,
|
|
errExists: true,
|
|
},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
b := c.b(t, c.slot)
|
|
marshaled, err := b.MarshalSSZ()
|
|
require.NoError(t, err)
|
|
cf, err := FromBlock(marshaled)
|
|
require.NoError(t, err)
|
|
bcf, err := cf.UnmarshalBeaconBlock(marshaled)
|
|
if c.errExists {
|
|
require.NotNil(t, err)
|
|
return
|
|
}
|
|
require.NoError(t, err)
|
|
expected, err := b.Block().HashTreeRoot()
|
|
require.NoError(t, err)
|
|
actual, err := bcf.Block().HashTreeRoot()
|
|
require.NoError(t, err)
|
|
require.Equal(t, expected, actual)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUnmarshalBlock(t *testing.T) {
|
|
defer util.HackForksMaxuint(t, []int{version.Electra, version.Fulu})()
|
|
|
|
genv := bytesutil.ToBytes4(params.BeaconConfig().GenesisForkVersion)
|
|
altairv := bytesutil.ToBytes4(params.BeaconConfig().AltairForkVersion)
|
|
bellav := bytesutil.ToBytes4(params.BeaconConfig().BellatrixForkVersion)
|
|
capellaV := bytesutil.ToBytes4(params.BeaconConfig().CapellaForkVersion)
|
|
denebV := bytesutil.ToBytes4(params.BeaconConfig().DenebForkVersion)
|
|
electraV := bytesutil.ToBytes4(params.BeaconConfig().ElectraForkVersion)
|
|
fuluV := bytesutil.ToBytes4(params.BeaconConfig().FuluForkVersion)
|
|
altairS, err := slots.EpochStart(params.BeaconConfig().AltairForkEpoch)
|
|
require.NoError(t, err)
|
|
bellaS, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch)
|
|
require.NoError(t, err)
|
|
capellaS, err := slots.EpochStart(params.BeaconConfig().CapellaForkEpoch)
|
|
require.NoError(t, err)
|
|
denebS, err := slots.EpochStart(params.BeaconConfig().DenebForkEpoch)
|
|
require.NoError(t, err)
|
|
electraS, err := slots.EpochStart(params.BeaconConfig().ElectraForkEpoch)
|
|
require.NoError(t, err)
|
|
fuluS, err := slots.EpochStart(params.BeaconConfig().FuluForkEpoch)
|
|
require.NoError(t, err)
|
|
cases := []struct {
|
|
b func(*testing.T, primitives.Slot) interfaces.ReadOnlySignedBeaconBlock
|
|
name string
|
|
version [4]byte
|
|
slot primitives.Slot
|
|
err error
|
|
}{
|
|
{
|
|
name: "genesis - slot 0",
|
|
b: signedTestBlockGenesis,
|
|
version: genv,
|
|
},
|
|
{
|
|
name: "last slot of phase 0",
|
|
b: signedTestBlockGenesis,
|
|
version: genv,
|
|
slot: altairS - 1,
|
|
},
|
|
{
|
|
name: "first slot of altair",
|
|
b: signedTestBlockAltair,
|
|
version: altairv,
|
|
slot: altairS,
|
|
},
|
|
{
|
|
name: "last slot of altair",
|
|
b: signedTestBlockAltair,
|
|
version: altairv,
|
|
slot: bellaS - 1,
|
|
},
|
|
{
|
|
name: "first slot of bellatrix",
|
|
b: signedTestBlockBellatrix,
|
|
version: bellav,
|
|
slot: bellaS,
|
|
},
|
|
{
|
|
name: "first slot of capella",
|
|
b: signedTestBlockCapella,
|
|
version: capellaV,
|
|
slot: capellaS,
|
|
},
|
|
{
|
|
name: "last slot of capella",
|
|
b: signedTestBlockCapella,
|
|
version: capellaV,
|
|
slot: denebS - 1,
|
|
},
|
|
{
|
|
name: "first slot of deneb",
|
|
b: signedTestBlockDeneb,
|
|
version: denebV,
|
|
slot: denebS,
|
|
},
|
|
{
|
|
name: "first slot of electra",
|
|
b: signedTestBlockElectra,
|
|
version: electraV,
|
|
slot: electraS,
|
|
},
|
|
{
|
|
name: "first slot of fulu",
|
|
b: signedTestBlockFulu,
|
|
version: fuluV,
|
|
slot: fuluS,
|
|
},
|
|
{
|
|
name: "bellatrix block in altair slot",
|
|
b: signedTestBlockBellatrix,
|
|
version: bellav,
|
|
slot: bellaS - 1,
|
|
err: errBlockForkMismatch,
|
|
},
|
|
{
|
|
name: "genesis block in altair slot",
|
|
b: signedTestBlockGenesis,
|
|
version: genv,
|
|
slot: bellaS - 1,
|
|
err: errBlockForkMismatch,
|
|
},
|
|
{
|
|
name: "altair block in genesis slot",
|
|
b: signedTestBlockAltair,
|
|
version: altairv,
|
|
err: errBlockForkMismatch,
|
|
},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
b := c.b(t, c.slot)
|
|
marshaled, err := b.MarshalSSZ()
|
|
require.NoError(t, err)
|
|
cf, err := FromForkVersion(c.version)
|
|
require.NoError(t, err)
|
|
bcf, err := cf.UnmarshalBeaconBlock(marshaled)
|
|
if c.err != nil {
|
|
require.ErrorIs(t, err, c.err)
|
|
return
|
|
}
|
|
require.NoError(t, err)
|
|
expected, err := b.Block().HashTreeRoot()
|
|
require.NoError(t, err)
|
|
actual, err := bcf.Block().HashTreeRoot()
|
|
require.NoError(t, err)
|
|
require.Equal(t, expected, actual)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUnmarshalBlindedBlock(t *testing.T) {
|
|
defer util.HackForksMaxuint(t, []int{version.Electra, version.Fulu})()
|
|
|
|
genv := bytesutil.ToBytes4(params.BeaconConfig().GenesisForkVersion)
|
|
altairv := bytesutil.ToBytes4(params.BeaconConfig().AltairForkVersion)
|
|
bellav := bytesutil.ToBytes4(params.BeaconConfig().BellatrixForkVersion)
|
|
capellaV := bytesutil.ToBytes4(params.BeaconConfig().CapellaForkVersion)
|
|
denebV := bytesutil.ToBytes4(params.BeaconConfig().DenebForkVersion)
|
|
electraV := bytesutil.ToBytes4(params.BeaconConfig().ElectraForkVersion)
|
|
fuluV := bytesutil.ToBytes4(params.BeaconConfig().FuluForkVersion)
|
|
altairS, err := slots.EpochStart(params.BeaconConfig().AltairForkEpoch)
|
|
require.NoError(t, err)
|
|
bellaS, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch)
|
|
require.NoError(t, err)
|
|
capellaS, err := slots.EpochStart(params.BeaconConfig().CapellaForkEpoch)
|
|
require.NoError(t, err)
|
|
denebS, err := slots.EpochStart(params.BeaconConfig().DenebForkEpoch)
|
|
require.NoError(t, err)
|
|
electraS, err := slots.EpochStart(params.BeaconConfig().ElectraForkEpoch)
|
|
require.NoError(t, err)
|
|
fuluS, err := slots.EpochStart(params.BeaconConfig().FuluForkEpoch)
|
|
require.NoError(t, err)
|
|
cases := []struct {
|
|
b func(*testing.T, primitives.Slot) interfaces.ReadOnlySignedBeaconBlock
|
|
name string
|
|
version [4]byte
|
|
slot primitives.Slot
|
|
err error
|
|
}{
|
|
{
|
|
name: "genesis - slot 0",
|
|
b: signedTestBlockGenesis,
|
|
version: genv,
|
|
},
|
|
{
|
|
name: "last slot of phase 0",
|
|
b: signedTestBlockGenesis,
|
|
version: genv,
|
|
slot: altairS - 1,
|
|
},
|
|
{
|
|
name: "first slot of altair",
|
|
b: signedTestBlockAltair,
|
|
version: altairv,
|
|
slot: altairS,
|
|
},
|
|
{
|
|
name: "last slot of altair",
|
|
b: signedTestBlockAltair,
|
|
version: altairv,
|
|
slot: bellaS - 1,
|
|
},
|
|
{
|
|
name: "first slot of bellatrix",
|
|
b: signedTestBlindedBlockBellatrix,
|
|
version: bellav,
|
|
slot: bellaS,
|
|
},
|
|
{
|
|
name: "bellatrix block in altair slot",
|
|
b: signedTestBlindedBlockBellatrix,
|
|
version: bellav,
|
|
slot: bellaS - 1,
|
|
err: errBlockForkMismatch,
|
|
},
|
|
{
|
|
name: "first slot of capella",
|
|
b: signedTestBlindedBlockCapella,
|
|
version: capellaV,
|
|
slot: capellaS,
|
|
},
|
|
{
|
|
name: "last slot of capella",
|
|
b: signedTestBlindedBlockCapella,
|
|
version: capellaV,
|
|
slot: denebS - 1,
|
|
},
|
|
{
|
|
name: "first slot of deneb",
|
|
b: signedTestBlindedBlockDeneb,
|
|
version: denebV,
|
|
slot: denebS,
|
|
},
|
|
{
|
|
name: "first slot of electra",
|
|
b: signedTestBlindedBlockElectra,
|
|
version: electraV,
|
|
slot: electraS,
|
|
},
|
|
{
|
|
name: "first slot of fulu",
|
|
b: signedTestBlindedBlockFulu,
|
|
version: fuluV,
|
|
slot: fuluS,
|
|
},
|
|
{
|
|
name: "genesis block in altair slot",
|
|
b: signedTestBlockGenesis,
|
|
version: genv,
|
|
slot: bellaS - 1,
|
|
err: errBlockForkMismatch,
|
|
},
|
|
{
|
|
name: "altair block in genesis slot",
|
|
b: signedTestBlockAltair,
|
|
version: altairv,
|
|
err: errBlockForkMismatch,
|
|
},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
b := c.b(t, c.slot)
|
|
marshaled, err := b.MarshalSSZ()
|
|
require.NoError(t, err)
|
|
cf, err := FromForkVersion(c.version)
|
|
require.NoError(t, err)
|
|
bcf, err := cf.UnmarshalBlindedBeaconBlock(marshaled)
|
|
if c.err != nil {
|
|
require.ErrorIs(t, err, c.err)
|
|
return
|
|
}
|
|
require.NoError(t, err)
|
|
expected, err := b.Block().HashTreeRoot()
|
|
require.NoError(t, err)
|
|
actual, err := bcf.Block().HashTreeRoot()
|
|
require.NoError(t, err)
|
|
require.Equal(t, expected, actual)
|
|
})
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Phase 0
|
|
// ----------------------------------------------------------------------------
|
|
|
|
func signedTestBlockGenesis(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock {
|
|
b := util.NewBeaconBlock()
|
|
b.Block.Slot = slot
|
|
s, err := blocks.NewSignedBeaconBlock(b)
|
|
require.NoError(t, err)
|
|
return s
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Altair
|
|
// ----------------------------------------------------------------------------
|
|
|
|
func signedTestBlockAltair(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock {
|
|
b := util.NewBeaconBlockAltair()
|
|
b.Block.Slot = slot
|
|
s, err := blocks.NewSignedBeaconBlock(b)
|
|
require.NoError(t, err)
|
|
return s
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Bellatrix
|
|
// ----------------------------------------------------------------------------
|
|
|
|
func signedTestBlockBellatrix(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock {
|
|
b := util.NewBeaconBlockBellatrix()
|
|
b.Block.Slot = slot
|
|
s, err := blocks.NewSignedBeaconBlock(b)
|
|
require.NoError(t, err)
|
|
return s
|
|
}
|
|
|
|
func signedTestBlindedBlockBellatrix(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock {
|
|
b := util.NewBlindedBeaconBlockBellatrix()
|
|
b.Block.Slot = slot
|
|
s, err := blocks.NewSignedBeaconBlock(b)
|
|
require.NoError(t, err)
|
|
return s
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Capella
|
|
// ----------------------------------------------------------------------------
|
|
|
|
func signedTestBlockCapella(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock {
|
|
b := util.NewBeaconBlockCapella()
|
|
b.Block.Slot = slot
|
|
s, err := blocks.NewSignedBeaconBlock(b)
|
|
require.NoError(t, err)
|
|
return s
|
|
}
|
|
|
|
func signedTestBlindedBlockCapella(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock {
|
|
b := util.NewBlindedBeaconBlockCapella()
|
|
b.Block.Slot = slot
|
|
s, err := blocks.NewSignedBeaconBlock(b)
|
|
require.NoError(t, err)
|
|
return s
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Deneb
|
|
// ----------------------------------------------------------------------------
|
|
|
|
func signedTestBlockDeneb(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock {
|
|
b := util.NewBeaconBlockDeneb()
|
|
b.Block.Slot = slot
|
|
s, err := blocks.NewSignedBeaconBlock(b)
|
|
require.NoError(t, err)
|
|
return s
|
|
}
|
|
|
|
func signedTestBlindedBlockDeneb(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock {
|
|
b := util.NewBlindedBeaconBlockDeneb()
|
|
b.Message.Slot = slot
|
|
s, err := blocks.NewSignedBeaconBlock(b)
|
|
require.NoError(t, err)
|
|
return s
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Electra
|
|
// ----------------------------------------------------------------------------
|
|
|
|
func signedTestBlockElectra(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock {
|
|
b := util.NewBeaconBlockElectra()
|
|
b.Block.Slot = slot
|
|
s, err := blocks.NewSignedBeaconBlock(b)
|
|
require.NoError(t, err)
|
|
return s
|
|
}
|
|
|
|
func signedTestBlindedBlockElectra(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock {
|
|
b := util.NewBlindedBeaconBlockElectra()
|
|
b.Message.Slot = slot
|
|
s, err := blocks.NewSignedBeaconBlock(b)
|
|
require.NoError(t, err)
|
|
return s
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Fulu
|
|
// ----------------------------------------------------------------------------
|
|
|
|
func signedTestBlockFulu(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock {
|
|
b := util.NewBeaconBlockFulu()
|
|
b.Block.Slot = slot
|
|
s, err := blocks.NewSignedBeaconBlock(b)
|
|
require.NoError(t, err)
|
|
return s
|
|
}
|
|
|
|
func signedTestBlindedBlockFulu(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock {
|
|
b := util.NewBlindedBeaconBlockFulu()
|
|
b.Message.Slot = slot
|
|
s, err := blocks.NewSignedBeaconBlock(b)
|
|
require.NoError(t, err)
|
|
return s
|
|
}
|
|
|
|
func TestUnmarshalStateStandalone(t *testing.T) {
|
|
ctx := t.Context()
|
|
defer util.HackForksMaxuint(t, []int{version.Electra, version.Fulu})()
|
|
|
|
bc := params.BeaconConfig()
|
|
altairSlot, err := slots.EpochStart(bc.AltairForkEpoch)
|
|
require.NoError(t, err)
|
|
bellaSlot, err := slots.EpochStart(bc.BellatrixForkEpoch)
|
|
require.NoError(t, err)
|
|
capellaSlot, err := slots.EpochStart(bc.CapellaForkEpoch)
|
|
require.NoError(t, err)
|
|
denebSlot, err := slots.EpochStart(bc.DenebForkEpoch)
|
|
require.NoError(t, err)
|
|
electraSlot, err := slots.EpochStart(bc.ElectraForkEpoch)
|
|
require.NoError(t, err)
|
|
fuluSlot, err := slots.EpochStart(bc.FuluForkEpoch)
|
|
require.NoError(t, err)
|
|
|
|
cases := []struct {
|
|
name string
|
|
version int
|
|
slot primitives.Slot
|
|
forkversion [4]byte
|
|
}{
|
|
{
|
|
name: "phase0",
|
|
version: version.Phase0,
|
|
slot: 0,
|
|
forkversion: bytesutil.ToBytes4(bc.GenesisForkVersion),
|
|
},
|
|
{
|
|
name: "altair",
|
|
version: version.Altair,
|
|
slot: altairSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.AltairForkVersion),
|
|
},
|
|
{
|
|
name: "bellatrix",
|
|
version: version.Bellatrix,
|
|
slot: bellaSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.BellatrixForkVersion),
|
|
},
|
|
{
|
|
name: "capella",
|
|
version: version.Capella,
|
|
slot: capellaSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.CapellaForkVersion),
|
|
},
|
|
{
|
|
name: "deneb",
|
|
version: version.Deneb,
|
|
slot: denebSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.DenebForkVersion),
|
|
},
|
|
{
|
|
name: "electra",
|
|
version: version.Electra,
|
|
slot: electraSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.ElectraForkVersion),
|
|
},
|
|
{
|
|
name: "fulu",
|
|
version: version.Fulu,
|
|
slot: fuluSlot,
|
|
forkversion: bytesutil.ToBytes4(bc.FuluForkVersion),
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
// Create a state for the specific version
|
|
originalState, err := stateForVersion(c.version)
|
|
require.NoError(t, err)
|
|
require.NoError(t, originalState.SetFork(ðpb.Fork{
|
|
PreviousVersion: make([]byte, 4),
|
|
CurrentVersion: c.forkversion[:],
|
|
Epoch: 0,
|
|
}))
|
|
require.NoError(t, originalState.SetSlot(c.slot))
|
|
|
|
marshaled, err := originalState.MarshalSSZ()
|
|
require.NoError(t, err)
|
|
|
|
unmarshaledState, err := UnmarshalState(marshaled)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, unmarshaledState)
|
|
|
|
// Verify the unmarshaled state matches the original
|
|
expectedRoot, err := originalState.HashTreeRoot(ctx)
|
|
require.NoError(t, err)
|
|
actualRoot, err := unmarshaledState.HashTreeRoot(ctx)
|
|
require.NoError(t, err)
|
|
require.DeepEqual(t, expectedRoot, actualRoot)
|
|
|
|
// Verify basic state properties
|
|
require.Equal(t, c.slot, unmarshaledState.Slot())
|
|
fork := unmarshaledState.Fork()
|
|
require.DeepEqual(t, c.forkversion[:], fork.CurrentVersion)
|
|
})
|
|
}
|
|
|
|
t.Run("invalid state data", func(t *testing.T) {
|
|
invalidData := []byte("bad")
|
|
_, err := UnmarshalState(invalidData)
|
|
require.ErrorContains(t, "failed to detect version from state", err)
|
|
})
|
|
}
|