Compare commits

...

4 Commits

Author SHA1 Message Date
potuz
c0e8d5d7c9 Fix TestForkChoice_GetProposerHead 2025-06-17 21:12:15 -03:00
Preston Van Loon
ad5e721ea2 Fixing forkchoice tests, then spectests. Now asking for help... 2025-06-17 16:12:34 -05:00
Preston Van Loon
80b8c47a8b Fixing failed forkchoice tests in a new commit so it doesn't get worse
Fixing failed spectest tests in a new commit so it doesn't get worse

Fixing forkchoice tests, then spectests
2025-06-17 16:12:34 -05:00
Preston Van Loon
88b5e34cd7 Convert genesis times from seconds to time.Time 2025-06-17 16:12:34 -05:00
109 changed files with 508 additions and 431 deletions

View File

@@ -74,7 +74,7 @@ func BeaconStateFromConsensus(st beaconState.BeaconState) (*BeaconState, error)
}
return &BeaconState{
GenesisTime: fmt.Sprintf("%d", st.GenesisTime()),
GenesisTime: fmt.Sprintf("%d", st.GenesisTime().Unix()),
GenesisValidatorsRoot: hexutil.Encode(st.GenesisValidatorsRoot()),
Slot: fmt.Sprintf("%d", st.Slot()),
Fork: ForkFromConsensus(st.Fork()),
@@ -177,7 +177,7 @@ func BeaconStateAltairFromConsensus(st beaconState.BeaconState) (*BeaconStateAlt
}
return &BeaconStateAltair{
GenesisTime: fmt.Sprintf("%d", st.GenesisTime()),
GenesisTime: fmt.Sprintf("%d", st.GenesisTime().Unix()),
GenesisValidatorsRoot: hexutil.Encode(st.GenesisValidatorsRoot()),
Slot: fmt.Sprintf("%d", st.Slot()),
Fork: ForkFromConsensus(st.Fork()),
@@ -295,7 +295,7 @@ func BeaconStateBellatrixFromConsensus(st beaconState.BeaconState) (*BeaconState
}
return &BeaconStateBellatrix{
GenesisTime: fmt.Sprintf("%d", st.GenesisTime()),
GenesisTime: fmt.Sprintf("%d", st.GenesisTime().Unix()),
GenesisValidatorsRoot: hexutil.Encode(st.GenesisValidatorsRoot()),
Slot: fmt.Sprintf("%d", st.Slot()),
Fork: ForkFromConsensus(st.Fork()),
@@ -430,7 +430,7 @@ func BeaconStateCapellaFromConsensus(st beaconState.BeaconState) (*BeaconStateCa
}
return &BeaconStateCapella{
GenesisTime: fmt.Sprintf("%d", st.GenesisTime()),
GenesisTime: fmt.Sprintf("%d", st.GenesisTime().Unix()),
GenesisValidatorsRoot: hexutil.Encode(st.GenesisValidatorsRoot()),
Slot: fmt.Sprintf("%d", st.Slot()),
Fork: ForkFromConsensus(st.Fork()),
@@ -568,7 +568,7 @@ func BeaconStateDenebFromConsensus(st beaconState.BeaconState) (*BeaconStateDene
}
return &BeaconStateDeneb{
GenesisTime: fmt.Sprintf("%d", st.GenesisTime()),
GenesisTime: fmt.Sprintf("%s", st.GenesisTime()),
GenesisValidatorsRoot: hexutil.Encode(st.GenesisValidatorsRoot()),
Slot: fmt.Sprintf("%d", st.Slot()),
Fork: ForkFromConsensus(st.Fork()),
@@ -742,7 +742,7 @@ func BeaconStateElectraFromConsensus(st beaconState.BeaconState) (*BeaconStateEl
}
return &BeaconStateElectra{
GenesisTime: fmt.Sprintf("%d", st.GenesisTime()),
GenesisTime: fmt.Sprintf("%d", st.GenesisTime().Unix()),
GenesisValidatorsRoot: hexutil.Encode(st.GenesisValidatorsRoot()),
Slot: fmt.Sprintf("%d", st.Slot()),
Fork: ForkFromConsensus(st.Fork()),
@@ -932,7 +932,7 @@ func BeaconStateFuluFromConsensus(st beaconState.BeaconState) (*BeaconStateFulu,
lookahead[i] = fmt.Sprintf("%d", uint64(v))
}
return &BeaconStateFulu{
GenesisTime: fmt.Sprintf("%d", st.GenesisTime()),
GenesisTime: fmt.Sprintf("%d", st.GenesisTime().Unix()),
GenesisValidatorsRoot: hexutil.Encode(st.GenesisValidatorsRoot()),
Slot: fmt.Sprintf("%d", st.Slot()),
Fork: ForkFromConsensus(st.Fork()),

View File

@@ -41,7 +41,7 @@ type ForkchoiceFetcher interface {
Ancestor(context.Context, []byte, primitives.Slot) ([]byte, error)
CachedHeadRoot() [32]byte
GetProposerHead() [32]byte
SetForkChoiceGenesisTime(uint64)
SetForkChoiceGenesisTime(time.Time)
UpdateHead(context.Context, primitives.Slot)
HighestReceivedBlockSlot() primitives.Slot
ReceivedBlocksLastEpoch() (uint64, error)
@@ -514,7 +514,7 @@ func (s *Service) Ancestor(ctx context.Context, root []byte, slot primitives.Slo
// SetGenesisTime sets the genesis time of beacon chain.
func (s *Service) SetGenesisTime(t time.Time) {
s.genesisTime = t
s.genesisTime = t.Truncate(time.Second) // Genesis time has a precision of 1 second.
}
func (s *Service) recoverStateSummary(ctx context.Context, blockRoot [32]byte) (*ethpb.StateSummary, error) {

View File

@@ -2,6 +2,7 @@ package blockchain
import (
"context"
"time"
"github.com/OffchainLabs/prysm/v6/beacon-chain/state"
consensus_blocks "github.com/OffchainLabs/prysm/v6/consensus-types/blocks"
@@ -27,7 +28,7 @@ func (s *Service) GetProposerHead() [32]byte {
}
// SetForkChoiceGenesisTime sets the genesis time in Forkchoice
func (s *Service) SetForkChoiceGenesisTime(timestamp uint64) {
func (s *Service) SetForkChoiceGenesisTime(timestamp time.Time) {
s.cfg.ForkChoiceStore.Lock()
defer s.cfg.ForkChoiceStore.Unlock()
s.cfg.ForkChoiceStore.SetGenesisTime(timestamp)

View File

@@ -432,6 +432,7 @@ func TestService_IsOptimistic(t *testing.T) {
ojc := &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
ofc := &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New()}, head: &head{root: [32]byte{'b'}}}
c.SetGenesisTime(time.Now())
st, roblock, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, ojc, ofc)
require.NoError(t, err)
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, roblock))

View File

@@ -354,7 +354,7 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
}
// Get timestamp.
t, err := slots.ToTime(uint64(s.genesisTime.Unix()), slot)
t, err := slots.ToTime(s.genesisTime, slot)
if err != nil {
log.WithError(err).Error("Could not get timestamp to get payload attribute")
return emptyAttri

View File

@@ -132,16 +132,16 @@ func (s *Service) shouldOverrideFCU(newHeadRoot [32]byte, proposingSlot primitiv
if s.cfg.ForkChoiceStore.ShouldOverrideFCU() {
return true
}
secs, err := slots.SecondsSinceSlotStart(currentSlot,
uint64(s.genesisTime.Unix()), uint64(time.Now().Unix()))
sss, err := slots.SinceSlotStart(currentSlot, s.genesisTime, time.Now())
if err != nil {
log.WithError(err).Error("could not compute seconds since slot start")
log.WithError(err).Error("could not compute time since slot start")
}
if secs >= doublylinkedtree.ProcessAttestationsThreshold {
if sss >= doublylinkedtree.ProcessAttestationsThreshold {
log.WithFields(logrus.Fields{
"root": fmt.Sprintf("%#x", newHeadRoot),
"weight": headWeight,
}).Infof("Attempted late block reorg aborted due to attestations at %d seconds",
"root": fmt.Sprintf("%#x", newHeadRoot),
"weight": headWeight,
"since slot start": sss,
}).Infof("Attempted late block reorg aborted due to attestations after %s",
doublylinkedtree.ProcessAttestationsThreshold)
lateBlockFailedAttemptFirstThreshold.Inc()
}

View File

@@ -160,6 +160,7 @@ func TestShouldOverrideFCU(t *testing.T) {
ctx, fcs := tr.ctx, tr.fcs
service.SetGenesisTime(time.Now().Add(-time.Duration(2*params.BeaconConfig().SecondsPerSlot) * time.Second))
fcs.SetGenesisTime(time.Now().Add(-time.Duration(2*params.BeaconConfig().SecondsPerSlot) * time.Second))
headRoot := [32]byte{'b'}
parentRoot := [32]byte{'a'}
ojc := &ethpb.Checkpoint{}
@@ -180,11 +181,12 @@ func TestShouldOverrideFCU(t *testing.T) {
require.NoError(t, err)
require.Equal(t, headRoot, head)
fcs.SetGenesisTime(uint64(time.Now().Unix()) - 29)
wantLog := "aborted due to attestations after 10s"
fcs.SetGenesisTime(time.Now().Add(-29 * time.Second))
require.Equal(t, true, service.shouldOverrideFCU(parentRoot, 3))
require.LogsDoNotContain(t, hook, "10 seconds")
fcs.SetGenesisTime(uint64(time.Now().Unix()) - 24)
require.LogsDoNotContain(t, hook, wantLog)
fcs.SetGenesisTime(time.Now().Add(-24 * time.Second))
service.SetGenesisTime(time.Now().Add(-time.Duration(2*params.BeaconConfig().SecondsPerSlot+10) * time.Second))
require.Equal(t, false, service.shouldOverrideFCU(parentRoot, 3))
require.LogsContain(t, hook, "10 seconds")
require.LogsContain(t, hook, wantLog)
}

View File

@@ -162,6 +162,7 @@ func Test_notifyNewHeadEvent(t *testing.T) {
},
originBlockRoot: [32]byte{1},
}
srv.SetGenesisTime(time.Now())
st, blk, err := prepareForkchoiceState(t.Context(), 0, [32]byte{}, [32]byte{}, [32]byte{}, &ethpb.Checkpoint{}, &ethpb.Checkpoint{})
require.NoError(t, err)
require.NoError(t, srv.cfg.ForkChoiceStore.InsertNode(t.Context(), st, blk))
@@ -194,6 +195,7 @@ func Test_notifyNewHeadEvent(t *testing.T) {
},
originBlockRoot: genesisRoot,
}
srv.SetGenesisTime(time.Now())
st, blk, err := prepareForkchoiceState(t.Context(), 0, [32]byte{}, [32]byte{}, [32]byte{}, &ethpb.Checkpoint{}, &ethpb.Checkpoint{})
require.NoError(t, err)
require.NoError(t, srv.cfg.ForkChoiceStore.InsertNode(t.Context(), st, blk))
@@ -407,7 +409,7 @@ func TestSaveOrphanedOps(t *testing.T) {
ctx := t.Context()
beaconDB := testDB.SetupDB(t)
service := setupBeaconChain(t, beaconDB)
service.genesisTime = time.Now().Add(time.Duration(-10*int64(1)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second)
service.SetGenesisTime(time.Now().Add(time.Duration(-10*int64(1)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
// Chain setup
// 0 -- 1 -- 2 -- 3

View File

@@ -89,8 +89,8 @@ func logStateTransitionData(b interfaces.ReadOnlyBeaconBlock) error {
return nil
}
func logBlockSyncStatus(block interfaces.ReadOnlyBeaconBlock, blockRoot [32]byte, justified, finalized *ethpb.Checkpoint, receivedTime time.Time, genesisTime uint64, daWaitedTime time.Duration) error {
startTime, err := slots.ToTime(genesisTime, block.Slot())
func logBlockSyncStatus(block interfaces.ReadOnlyBeaconBlock, blockRoot [32]byte, justified, finalized *ethpb.Checkpoint, receivedTime time.Time, genesis time.Time, daWaitedTime time.Duration) error {
startTime, err := slots.ToTime(genesis, block.Slot())
if err != nil {
return err
}

View File

@@ -246,7 +246,7 @@ func WithSlasherEnabled(enabled bool) Option {
// WithGenesisTime sets the genesis time for the blockchain service.
func WithGenesisTime(genesisTime time.Time) Option {
return func(s *Service) error {
s.genesisTime = genesisTime
s.genesisTime = genesisTime.Truncate(time.Second) // Genesis time has a precision of 1 second.
return nil
}
}

View File

@@ -60,10 +60,8 @@ func (s *Service) OnAttestation(ctx context.Context, a ethpb.Att, disparity time
return err
}
genesisTime := uint64(s.genesisTime.Unix())
// Verify attestation target is from current epoch or previous epoch.
if err := verifyAttTargetEpoch(ctx, genesisTime, uint64(time.Now().Add(disparity).Unix()), tgt); err != nil {
if err := verifyAttTargetEpoch(ctx, s.genesisTime, time.Now().Add(disparity), tgt); err != nil {
return err
}
@@ -76,7 +74,7 @@ func (s *Service) OnAttestation(ctx context.Context, a ethpb.Att, disparity time
// validate_aggregate_proof.go and validate_beacon_attestation.go
// Verify attestations can only affect the fork choice of subsequent slots.
if err := slots.VerifyTime(genesisTime, a.GetData().Slot+1, disparity); err != nil {
if err := slots.VerifyTime(s.genesisTime, a.GetData().Slot+1, disparity); err != nil {
return err
}

View File

@@ -4,12 +4,12 @@ import (
"context"
"fmt"
"strconv"
"time"
"github.com/OffchainLabs/prysm/v6/async"
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/transition"
forkchoicetypes "github.com/OffchainLabs/prysm/v6/beacon-chain/forkchoice/types"
"github.com/OffchainLabs/prysm/v6/beacon-chain/state"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/blocks"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
@@ -139,8 +139,8 @@ func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (stat
}
// verifyAttTargetEpoch validates attestation is from the current or previous epoch.
func verifyAttTargetEpoch(_ context.Context, genesisTime, nowTime uint64, c *ethpb.Checkpoint) error {
currentSlot := primitives.Slot((nowTime - genesisTime) / params.BeaconConfig().SecondsPerSlot)
func verifyAttTargetEpoch(_ context.Context, genesis, now time.Time, c *ethpb.Checkpoint) error {
currentSlot := slots.SlotAt(genesis, now)
currentEpoch := slots.ToEpoch(currentSlot)
var prevEpoch primitives.Epoch
// Prevents previous epoch under flow

View File

@@ -355,22 +355,22 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
func TestAttEpoch_MatchPrevEpoch(t *testing.T) {
ctx := t.Context()
nowTime := uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().SecondsPerSlot
require.NoError(t, verifyAttTargetEpoch(ctx, 0, nowTime, &ethpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}))
nowTime := time.Unix(int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot), 0)
require.NoError(t, verifyAttTargetEpoch(ctx, time.Unix(0, 0), nowTime, &ethpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}))
}
func TestAttEpoch_MatchCurrentEpoch(t *testing.T) {
ctx := t.Context()
nowTime := uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().SecondsPerSlot
require.NoError(t, verifyAttTargetEpoch(ctx, 0, nowTime, &ethpb.Checkpoint{Epoch: 1}))
nowTime := time.Unix(int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot), 0)
require.NoError(t, verifyAttTargetEpoch(ctx, time.Unix(0, 0), nowTime, &ethpb.Checkpoint{Epoch: 1}))
}
func TestAttEpoch_NotMatch(t *testing.T) {
ctx := t.Context()
nowTime := 2 * uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().SecondsPerSlot
err := verifyAttTargetEpoch(ctx, 0, nowTime, &ethpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)})
nowTime := time.Unix(2*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot), 0)
err := verifyAttTargetEpoch(ctx, time.Unix(0, 0), nowTime, &ethpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)})
assert.ErrorContains(t, "target epoch 0 does not match current epoch 2 or prev epoch 1", err)
}

View File

@@ -894,7 +894,7 @@ func uint64MapToSortedSlice(input map[uint64]bool) []uint64 {
// it also updates the next slot cache and the proposer index cache to deal with skipped slots.
func (s *Service) lateBlockTasks(ctx context.Context) {
currentSlot := s.CurrentSlot()
if s.CurrentSlot() == s.HeadSlot() {
if currentSlot == s.HeadSlot() {
return
}
s.cfg.ForkChoiceStore.RLock()

View File

@@ -33,7 +33,7 @@ import (
// CurrentSlot returns the current slot based on time.
func (s *Service) CurrentSlot() primitives.Slot {
return slots.CurrentSlot(uint64(s.genesisTime.Unix()))
return slots.CurrentSlot(s.genesisTime)
}
// getFCUArgs returns the arguments to call forkchoice update
@@ -45,7 +45,7 @@ func (s *Service) getFCUArgs(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) er
return nil
}
slot := cfg.roblock.Block().Slot()
if slots.WithinVotingWindow(uint64(s.genesisTime.Unix()), slot) {
if slots.WithinVotingWindow(s.genesisTime, slot) {
return nil
}
return s.computePayloadAttributes(cfg, fcuArgs)
@@ -432,7 +432,7 @@ func (s *Service) getBlockPreState(ctx context.Context, b interfaces.ReadOnlyBea
}
// Verify block slot time is not from the future.
if err := slots.VerifyTime(uint64(s.genesisTime.Unix()), b.Slot(), params.BeaconConfig().MaximumGossipClockDisparityDuration()); err != nil {
if err := slots.VerifyTime(s.genesisTime, b.Slot(), params.BeaconConfig().MaximumGossipClockDisparityDuration()); err != nil {
return nil, err
}

View File

@@ -643,6 +643,7 @@ func TestOnBlock_CanFinalize_WithOnTick(t *testing.T) {
require.NoError(t, fcs.UpdateFinalizedCheckpoint(&forkchoicetypes.Checkpoint{Root: service.originBlockRoot}))
testState := gs.Copy()
// TODO(Preston): This test is really slow, is it because genesis is epoch 0?
for i := primitives.Slot(1); i <= 4*params.BeaconConfig().SlotsPerEpoch; i++ {
blk, err := util.GenerateFullBlock(testState, keys, util.DefaultBlockGenConfig(), i)
require.NoError(t, err)
@@ -1359,7 +1360,7 @@ func TestStore_NoViableHead_FCU(t *testing.T) {
require.NoError(t, service.cfg.BeaconDB.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state")
for i := 1; i < 6; i++ {
driftGenesisTime(service, int64(i), 0)
driftGenesisTime(service, primitives.Slot(i), 0)
st, err := service.HeadState(ctx)
require.NoError(t, err)
b, err := util.GenerateFullBlock(st, keys, util.DefaultBlockGenConfig(), primitives.Slot(i))
@@ -1380,7 +1381,7 @@ func TestStore_NoViableHead_FCU(t *testing.T) {
}
for i := 6; i < 12; i++ {
driftGenesisTime(service, int64(i), 0)
driftGenesisTime(service, primitives.Slot(i), 0)
st, err := service.HeadState(ctx)
require.NoError(t, err)
b, err := util.GenerateFullBlockAltair(st, keys, util.DefaultBlockGenConfig(), primitives.Slot(i))
@@ -1401,7 +1402,7 @@ func TestStore_NoViableHead_FCU(t *testing.T) {
}
for i := 12; i < 18; i++ {
driftGenesisTime(service, int64(i), 0)
driftGenesisTime(service, primitives.Slot(i), 0)
st, err := service.HeadState(ctx)
require.NoError(t, err)
b, err := util.GenerateFullBlockBellatrix(st, keys, util.DefaultBlockGenConfig(), primitives.Slot(i))
@@ -1550,7 +1551,7 @@ func TestStore_NoViableHead_NewPayload(t *testing.T) {
require.NoError(t, service.cfg.BeaconDB.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state")
for i := 1; i < 6; i++ {
driftGenesisTime(service, int64(i), 0)
driftGenesisTime(service, primitives.Slot(i), 0)
st, err := service.HeadState(ctx)
require.NoError(t, err)
b, err := util.GenerateFullBlock(st, keys, util.DefaultBlockGenConfig(), primitives.Slot(i))
@@ -1570,7 +1571,7 @@ func TestStore_NoViableHead_NewPayload(t *testing.T) {
}
for i := 6; i < 12; i++ {
driftGenesisTime(service, int64(i), 0)
driftGenesisTime(service, primitives.Slot(i), 0)
st, err := service.HeadState(ctx)
require.NoError(t, err)
b, err := util.GenerateFullBlockAltair(st, keys, util.DefaultBlockGenConfig(), primitives.Slot(i))
@@ -1591,7 +1592,7 @@ func TestStore_NoViableHead_NewPayload(t *testing.T) {
}
for i := 12; i < 18; i++ {
driftGenesisTime(service, int64(i), 0)
driftGenesisTime(service, primitives.Slot(i), 0)
st, err := service.HeadState(ctx)
require.NoError(t, err)
b, err := util.GenerateFullBlockBellatrix(st, keys, util.DefaultBlockGenConfig(), primitives.Slot(i))
@@ -1742,7 +1743,7 @@ func TestStore_NoViableHead_Liveness(t *testing.T) {
require.NoError(t, service.cfg.BeaconDB.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state")
for i := 1; i < 6; i++ {
driftGenesisTime(service, int64(i), 0)
driftGenesisTime(service, primitives.Slot(i), 0)
st, err := service.HeadState(ctx)
require.NoError(t, err)
b, err := util.GenerateFullBlock(st, keys, util.DefaultBlockGenConfig(), primitives.Slot(i))
@@ -1763,7 +1764,7 @@ func TestStore_NoViableHead_Liveness(t *testing.T) {
}
for i := 6; i < 12; i++ {
driftGenesisTime(service, int64(i), 0)
driftGenesisTime(service, primitives.Slot(i), 0)
st, err := service.HeadState(ctx)
require.NoError(t, err)
b, err := util.GenerateFullBlockAltair(st, keys, util.DefaultBlockGenConfig(), primitives.Slot(i))
@@ -1814,7 +1815,7 @@ func TestStore_NoViableHead_Liveness(t *testing.T) {
// import blocks 13 through 18 to justify 12
invalidRoots := make([][32]byte, 19-13)
for i := 13; i < 19; i++ {
driftGenesisTime(service, int64(i), 0)
driftGenesisTime(service, primitives.Slot(i), 0)
st, err := service.HeadState(ctx)
require.NoError(t, err)
b, err := util.GenerateFullBlockBellatrix(st, keys, util.DefaultBlockGenConfig(), primitives.Slot(i))
@@ -1909,7 +1910,7 @@ func TestStore_NoViableHead_Liveness(t *testing.T) {
require.NoError(t, err)
// Import blocks 21--30 (Epoch 3 was not enough to justify 2)
for i := 21; i < 30; i++ {
driftGenesisTime(service, int64(i), 0)
driftGenesisTime(service, primitives.Slot(i), 0)
require.NoError(t, err)
b, err := util.GenerateFullBlockBellatrix(st, keys, util.DefaultBlockGenConfig(), primitives.Slot(i))
require.NoError(t, err)
@@ -1995,7 +1996,8 @@ func TestNoViableHead_Reboot(t *testing.T) {
require.NoError(t, service.cfg.BeaconDB.SaveGenesisBlockRoot(ctx, genesisRoot), "Could not save genesis state")
for i := 1; i < 6; i++ {
driftGenesisTime(service, int64(i), 0)
t.Log(i)
driftGenesisTime(service, primitives.Slot(i), 0)
st, err := service.HeadState(ctx)
require.NoError(t, err)
b, err := util.GenerateFullBlock(st, keys, util.DefaultBlockGenConfig(), primitives.Slot(i))
@@ -2015,7 +2017,7 @@ func TestNoViableHead_Reboot(t *testing.T) {
}
for i := 6; i < 12; i++ {
driftGenesisTime(service, int64(i), 0)
driftGenesisTime(service, primitives.Slot(i), 0)
st, err := service.HeadState(ctx)
require.NoError(t, err)
b, err := util.GenerateFullBlockAltair(st, keys, util.DefaultBlockGenConfig(), primitives.Slot(i))
@@ -2064,7 +2066,7 @@ func TestNoViableHead_Reboot(t *testing.T) {
// import blocks 13 through 18 to justify 12
for i := 13; i < 19; i++ {
driftGenesisTime(service, int64(i), 0)
driftGenesisTime(service, primitives.Slot(i), 0)
st, err := service.HeadState(ctx)
require.NoError(t, err)
b, err := util.GenerateFullBlockBellatrix(st, keys, util.DefaultBlockGenConfig(), primitives.Slot(i))
@@ -2307,10 +2309,12 @@ func TestOnBlock_HandleBlockAttestations(t *testing.T) {
func TestFillMissingBlockPayloadId_DiffSlotExitEarly(t *testing.T) {
logHook := logTest.NewGlobal()
service, tr := minimalTestService(t)
service.SetGenesisTime(time.Now())
service.lateBlockTasks(tr.ctx)
require.LogsDoNotContain(t, logHook, "could not perform late block tasks")
}
// TODO(Preston): This test does nothing at all. It simply returns when the current slot == head slot.
func TestFillMissingBlockPayloadId_PrepareAllPayloads(t *testing.T) {
logHook := logTest.NewGlobal()
resetCfg := features.InitWithReset(&features.Flags{
@@ -2319,17 +2323,20 @@ func TestFillMissingBlockPayloadId_PrepareAllPayloads(t *testing.T) {
defer resetCfg()
service, tr := minimalTestService(t)
service.SetGenesisTime(time.Now())
service.SetForkChoiceGenesisTime(time.Now())
service.lateBlockTasks(tr.ctx)
require.LogsDoNotContain(t, logHook, "could not perform late block tasks")
}
// Helper function to simulate the block being on time or delayed for proposer
// boost. It alters the genesisTime tracked by the store.
func driftGenesisTime(s *Service, slot, delay int64) {
offset := slot*int64(params.BeaconConfig().SecondsPerSlot) + delay
newTime := time.Unix(time.Now().Unix()-offset, 0)
s.SetGenesisTime(newTime)
s.cfg.ForkChoiceStore.SetGenesisTime(uint64(newTime.Unix()))
func driftGenesisTime(s *Service, slot primitives.Slot, delay time.Duration) {
now := time.Now()
offset := now.Sub(slots.BeginsAt(slot, now)).Abs() + delay
genesis := now.Add(-offset)
s.SetGenesisTime(genesis)
s.cfg.ForkChoiceStore.SetGenesisTime(genesis)
}
func TestMissingBlobIndices(t *testing.T) {

View File

@@ -43,7 +43,7 @@ func (s *Service) AttestationTargetState(ctx context.Context, target *ethpb.Chec
if err != nil {
return nil, err
}
if err := slots.ValidateClock(ss, uint64(s.genesisTime.Unix())); err != nil {
if err := slots.ValidateClock(ss, s.genesisTime); err != nil {
return nil, err
}
// We acquire the lock here instead than on gettAttPreState because that function gets called from UpdateHead that holds a write lock
@@ -179,7 +179,7 @@ func (s *Service) processAttestations(ctx context.Context, disparity time.Durati
// This delays consideration in the fork choice until their slot is in the past.
// https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/fork-choice.md#validate_on_attestation
nextSlot := a.GetData().Slot + 1
if err := slots.VerifyTime(uint64(s.genesisTime.Unix()), nextSlot, disparity); err != nil {
if err := slots.VerifyTime(s.genesisTime, nextSlot, disparity); err != nil {
continue
}

View File

@@ -70,7 +70,7 @@ func TestProcessAttestations_Ok(t *testing.T) {
service.genesisTime = prysmTime.Now().Add(-1 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
genesisState, pks := util.DeterministicGenesisState(t, 64)
require.NoError(t, genesisState.SetGenesisTime(uint64(prysmTime.Now().Unix())-params.BeaconConfig().SecondsPerSlot))
require.NoError(t, genesisState.SetGenesisTime(time.Now().Add(-1*time.Duration(params.BeaconConfig().SecondsPerSlot)*time.Second)))
require.NoError(t, service.saveGenesisData(ctx, genesisState))
atts, err := util.GenerateAttestations(genesisState, pks, 1, 0, false)
require.NoError(t, err)

View File

@@ -283,7 +283,7 @@ func (s *Service) reportPostBlockProcessing(
// Log block sync status.
cp = s.cfg.ForkChoiceStore.JustifiedCheckpoint()
justified := &ethpb.Checkpoint{Epoch: cp.Epoch, Root: bytesutil.SafeCopyBytes(cp.Root[:])}
if err := logBlockSyncStatus(block.Block(), blockRoot, justified, finalized, receivedTime, uint64(s.genesisTime.Unix()), daWaitedTime); err != nil {
if err := logBlockSyncStatus(block.Block(), blockRoot, justified, finalized, receivedTime, s.genesisTime, daWaitedTime); err != nil {
log.WithError(err).Error("Unable to log block sync status")
}
// Log payload data

View File

@@ -8,6 +8,7 @@ import (
blockchainTesting "github.com/OffchainLabs/prysm/v6/beacon-chain/blockchain/testing"
"github.com/OffchainLabs/prysm/v6/beacon-chain/cache"
statefeed "github.com/OffchainLabs/prysm/v6/beacon-chain/core/feed/state"
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers"
"github.com/OffchainLabs/prysm/v6/beacon-chain/das"
"github.com/OffchainLabs/prysm/v6/beacon-chain/operations/voluntaryexits"
"github.com/OffchainLabs/prysm/v6/config/features"
@@ -338,7 +339,7 @@ func TestCheckSaveHotStateDB_Disabling(t *testing.T) {
func TestCheckSaveHotStateDB_Overflow(t *testing.T) {
hook := logTest.NewGlobal()
s, _ := minimalTestService(t)
s.genesisTime = time.Now()
s.SetGenesisTime(time.Now())
require.NoError(t, s.checkSaveHotStateDB(t.Context()))
assert.LogsDoNotContain(t, hook, "Entering mode to save hot states in DB")
@@ -348,8 +349,9 @@ func TestHandleCaches_EnablingLargeSize(t *testing.T) {
hook := logTest.NewGlobal()
s, _ := minimalTestService(t)
st := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epochsSinceFinalitySaveHotStateDB))
s.genesisTime = time.Now().Add(time.Duration(-1*int64(st)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second)
s.SetGenesisTime(time.Now().Add(time.Duration(-1*int64(st)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
helpers.ClearCache()
require.NoError(t, s.handleCaches())
assert.LogsContain(t, hook, "Expanding committee cache size")
}

View File

@@ -265,7 +265,7 @@ func (s *Service) Status() error {
// StartFromSavedState initializes the blockchain using a previously saved finalized checkpoint.
func (s *Service) StartFromSavedState(saved state.BeaconState) error {
log.Info("Blockchain data already exists in DB, initializing...")
s.genesisTime = time.Unix(int64(saved.GenesisTime()), 0) // lint:ignore uintcast -- Genesis time will not exceed int64 in your lifetime.
s.genesisTime = saved.GenesisTime()
s.cfg.AttService.SetGenesisTime(saved.GenesisTime())
originRoot, err := s.originRootFromSavedState(s.ctx)
@@ -421,7 +421,7 @@ func (s *Service) initializeBeaconChain(
eth1data *ethpb.Eth1Data) (state.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "beacon-chain.Service.initializeBeaconChain")
defer span.End()
s.genesisTime = genesisTime
s.genesisTime = genesisTime.Truncate(time.Second) // Genesis time has a precision of 1 second.
unixTime := uint64(genesisTime.Unix())
genesisState, err := transition.OptimizedGenesisBeaconState(unixTime, preGenesisState, eth1data)
@@ -482,7 +482,7 @@ func (s *Service) saveGenesisData(ctx context.Context, genesisState state.Beacon
if err := s.cfg.ForkChoiceStore.SetOptimisticToValid(ctx, genesisBlkRoot); err != nil {
return errors.Wrap(err, "Could not set optimistic status of genesis block to false")
}
s.cfg.ForkChoiceStore.SetGenesisTime(uint64(s.genesisTime.Unix()))
s.cfg.ForkChoiceStore.SetGenesisTime(s.genesisTime)
if err := s.setHead(&head{
genesisBlkRoot,

View File

@@ -127,7 +127,7 @@ func TestChainStartStop_Initialized(t *testing.T) {
util.SaveBlock(t, ctx, beaconDB, genesisBlk)
s, err := util.NewBeaconState()
require.NoError(t, err)
require.NoError(t, s.SetGenesisTime(uint64(gt.Unix())))
require.NoError(t, s.SetGenesisTime(gt))
require.NoError(t, s.SetSlot(1))
require.NoError(t, beaconDB.SaveState(ctx, s, blkRoot))
require.NoError(t, beaconDB.SaveHeadBlockRoot(ctx, blkRoot))
@@ -164,7 +164,7 @@ func TestChainStartStop_GenesisZeroHashes(t *testing.T) {
wsb := util.SaveBlock(t, ctx, beaconDB, genesisBlk)
s, err := util.NewBeaconState()
require.NoError(t, err)
require.NoError(t, s.SetGenesisTime(uint64(gt.Unix())))
require.NoError(t, s.SetGenesisTime(gt))
require.NoError(t, beaconDB.SaveState(ctx, s, blkRoot))
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, blkRoot))
require.NoError(t, beaconDB.SaveBlock(ctx, wsb))
@@ -238,7 +238,7 @@ func TestChainService_CorrectGenesisRoots(t *testing.T) {
util.SaveBlock(t, ctx, beaconDB, genesisBlk)
s, err := util.NewBeaconState()
require.NoError(t, err)
require.NoError(t, s.SetGenesisTime(uint64(gt.Unix())))
require.NoError(t, s.SetGenesisTime(gt))
require.NoError(t, s.SetSlot(0))
require.NoError(t, beaconDB.SaveState(ctx, s, blkRoot))
require.NoError(t, beaconDB.SaveHeadBlockRoot(ctx, blkRoot))

View File

@@ -170,6 +170,6 @@ func (s *Service) setupForkchoiceCheckpoints() error {
Root: fRoot}); err != nil {
return errors.Wrap(err, "could not update forkchoice's finalized checkpoint")
}
s.cfg.ForkChoiceStore.SetGenesisTime(uint64(s.genesisTime.Unix()))
s.cfg.ForkChoiceStore.SetGenesisTime(s.genesisTime)
return nil
}

View File

@@ -4,6 +4,7 @@ import (
"context"
"sync"
"testing"
"time"
"github.com/OffchainLabs/prysm/v6/async/event"
mock "github.com/OffchainLabs/prysm/v6/beacon-chain/blockchain/testing"
@@ -24,7 +25,9 @@ import (
"github.com/OffchainLabs/prysm/v6/beacon-chain/startup"
"github.com/OffchainLabs/prysm/v6/beacon-chain/state/stategen"
fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/interfaces"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/testing/require"
"google.golang.org/protobuf/proto"
@@ -109,8 +112,10 @@ type testServiceRequirements struct {
func minimalTestService(t *testing.T, opts ...Option) (*Service, *testServiceRequirements) {
ctx := t.Context()
genesis := time.Now().Add(-1 * 4 * time.Duration(params.BeaconConfig().SlotsPerEpoch*primitives.Slot(params.BeaconConfig().SecondsPerSlot)) * time.Second) // Genesis was 4 epochs ago.
beaconDB := testDB.SetupDB(t)
fcs := doublylinkedtree.New()
fcs.SetGenesisTime(genesis)
sg := stategen.New(beaconDB, fcs)
notif := &mockBeaconNode{}
fcs.SetBalancesByRooter(sg.ActiveNonSlashedBalancesByRoot)
@@ -149,6 +154,7 @@ func minimalTestService(t *testing.T, opts ...Option) (*Service, *testServiceReq
WithExecutionEngineCaller(&mockExecution.EngineClient{}),
WithP2PBroadcaster(&mockAccessor{}),
WithLightClientStore(&lightclient.Store{}),
WithGenesisTime(genesis),
}
// append the variadic opts so they override the defaults by being processed afterwards
opts = append(defOpts, opts...)

View File

@@ -641,7 +641,7 @@ func (s *ChainService) GetProposerHead() [32]byte {
}
// SetForkChoiceGenesisTime mocks the same method in the chain service
func (s *ChainService) SetForkChoiceGenesisTime(timestamp uint64) {
func (s *ChainService) SetForkChoiceGenesisTime(timestamp time.Time) {
if s.ForkChoiceStore != nil {
s.ForkChoiceStore.SetGenesisTime(timestamp)
}

View File

@@ -217,15 +217,15 @@ func IsSyncCommitteeAggregator(sig []byte) (bool, error) {
// ValidateSyncMessageTime validates sync message to ensure that the provided slot is valid.
// Spec: [IGNORE] The message's slot is for the current slot (with a MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance), i.e. sync_committee_message.slot == current_slot
func ValidateSyncMessageTime(slot primitives.Slot, genesisTime time.Time, clockDisparity time.Duration) error {
if err := slots.ValidateClock(slot, uint64(genesisTime.Unix())); err != nil {
if err := slots.ValidateClock(slot, genesisTime); err != nil {
return err
}
messageTime, err := slots.ToTime(uint64(genesisTime.Unix()), slot)
messageTime, err := slots.ToTime(genesisTime, slot)
if err != nil {
return err
}
currentSlot := slots.Since(genesisTime)
slotStartTime, err := slots.ToTime(uint64(genesisTime.Unix()), currentSlot)
slotStartTime, err := slots.ToTime(genesisTime, currentSlot)
if err != nil {
return err
}

View File

@@ -68,7 +68,7 @@ func UpgradeToAltair(ctx context.Context, state state.BeaconState) (state.Beacon
numValidators := state.NumValidators()
s := &ethpb.BeaconStateAltair{
GenesisTime: state.GenesisTime(),
GenesisTime: uint64(state.GenesisTime().Unix()),
GenesisValidatorsRoot: state.GenesisValidatorsRoot(),
Slot: state.Slot(),
Fork: &ethpb.Fork{

View File

@@ -43,7 +43,7 @@ func UpgradeToCapella(state state.BeaconState) (state.BeaconState, error) {
}
s := &ethpb.BeaconStateCapella{
GenesisTime: state.GenesisTime(),
GenesisTime: uint64(state.GenesisTime().Unix()),
GenesisValidatorsRoot: state.GenesisValidatorsRoot(),
Slot: state.Slot(),
Fork: &ethpb.Fork{

View File

@@ -59,7 +59,7 @@ func UpgradeToDeneb(state state.BeaconState) (state.BeaconState, error) {
}
s := &ethpb.BeaconStateDeneb{
GenesisTime: state.GenesisTime(),
GenesisTime: uint64(state.GenesisTime().Unix()),
GenesisValidatorsRoot: state.GenesisValidatorsRoot(),
Slot: state.Slot(),
Fork: &ethpb.Fork{

View File

@@ -208,7 +208,7 @@ func UpgradeToElectra(beaconState state.BeaconState) (state.BeaconState, error)
}
s := &ethpb.BeaconStateElectra{
GenesisTime: beaconState.GenesisTime(),
GenesisTime: uint64(beaconState.GenesisTime().Unix()),
GenesisValidatorsRoot: beaconState.GenesisValidatorsRoot(),
Slot: beaconState.Slot(),
Fork: &ethpb.Fork{

View File

@@ -36,7 +36,7 @@ func UpgradeToBellatrix(state state.BeaconState) (state.BeaconState, error) {
}
s := &ethpb.BeaconStateBellatrix{
GenesisTime: state.GenesisTime(),
GenesisTime: uint64(state.GenesisTime().Unix()),
GenesisValidatorsRoot: state.GenesisValidatorsRoot(),
Slot: state.Slot(),
Fork: &ethpb.Fork{

View File

@@ -111,7 +111,7 @@ func UpgradeToFulu(ctx context.Context, beaconState state.BeaconState) (state.Be
}
s := &ethpb.BeaconStateFulu{
GenesisTime: beaconState.GenesisTime(),
GenesisTime: uint64(beaconState.GenesisTime().Unix()),
GenesisValidatorsRoot: beaconState.GenesisValidatorsRoot(),
Slot: beaconState.Slot(),
Fork: &ethpb.Fork{

View File

@@ -10,7 +10,6 @@ import (
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/crypto/hash"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
prysmTime "github.com/OffchainLabs/prysm/v6/time"
"github.com/OffchainLabs/prysm/v6/time/slots"
)
@@ -125,18 +124,18 @@ func ComputeSubnetFromCommitteeAndSlot(activeValCount uint64, comIdx primitives.
// valid_attestation_slot = 101
//
// In the attestation must be within the range of 95 to 102 in the example above.
func ValidateAttestationTime(attSlot primitives.Slot, genesisTime time.Time, clockDisparity time.Duration) error {
attTime, err := slots.ToTime(uint64(genesisTime.Unix()), attSlot)
func ValidateAttestationTime(attSlot primitives.Slot, genesis time.Time, clockDisparity time.Duration) error {
attTime, err := slots.ToTime(genesis, attSlot)
if err != nil {
return err
}
currentSlot := slots.Since(genesisTime)
currentSlot := slots.CurrentSlot(genesis)
// When receiving an attestation, it can be from the future.
// so the upper bounds is set to now + clockDisparity(SECONDS_PER_SLOT * 2).
// But when sending an attestation, it should not be in future slot.
// so the upper bounds is set to now + clockDisparity(MAXIMUM_GOSSIP_CLOCK_DISPARITY).
upperBounds := prysmTime.Now().Add(clockDisparity)
upperBounds := time.Now().Add(clockDisparity)
// An attestation cannot be older than the current slot - attestation propagation slot range
// with a minor tolerance for peer clock disparity.
@@ -144,7 +143,7 @@ func ValidateAttestationTime(attSlot primitives.Slot, genesisTime time.Time, clo
if currentSlot > params.BeaconConfig().AttestationPropagationSlotRange {
lowerBoundsSlot = currentSlot - params.BeaconConfig().AttestationPropagationSlotRange
}
lowerTime, err := slots.ToTime(uint64(genesisTime.Unix()), lowerBoundsSlot)
lowerTime, err := slots.ToTime(genesis, lowerBoundsSlot)
if err != nil {
return err
}
@@ -187,7 +186,7 @@ func ValidateAttestationTime(attSlot primitives.Slot, genesisTime time.Time, clo
// VerifyCheckpointEpoch is within current epoch and previous epoch
// with respect to current time. Returns true if it's within, false if it's not.
func VerifyCheckpointEpoch(c *ethpb.Checkpoint, genesis time.Time) bool {
currentSlot := slots.CurrentSlot(uint64(genesis.Unix()))
currentSlot := slots.CurrentSlot(genesis)
currentEpoch := slots.ToEpoch(currentSlot)
var prevEpoch primitives.Epoch

View File

@@ -217,10 +217,11 @@ func Test_ValidateAttestationTime(t *testing.T) {
{
name: "attestation.slot is well beyond current slot",
args: args{
attSlot: 1 << 32,
genesisTime: prysmTime.Now().Add(-15 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
//attSlot: 1 << 32, // TODO(preston): Was this an overflow?
attSlot: 1024,
genesisTime: time.Now().Add(-15 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
},
wantedErr: "attestation slot 4294967296 not within attestation propagation range of 0 to 15 (current slot)",
wantedErr: "attestation slot 1024 not within attestation propagation range of 0 to 15 (current slot)",
},
}
for _, tt := range tests {

View File

@@ -60,7 +60,7 @@ type Service struct {
initSyncWaiter func() error
}
func New(ctx context.Context, db iface.Database, genesisTime uint64, initSyncWaiter, backfillWaiter func() error, opts ...ServiceOption) (*Service, error) {
func New(ctx context.Context, db iface.Database, genesisTime time.Time, initSyncWaiter, backfillWaiter func() error, opts ...ServiceOption) (*Service, error) {
p := &Service{
ctx: ctx,
db: db,

View File

@@ -62,7 +62,7 @@ func TestPruner_PruningConditions(t *testing.T) {
if !tt.backfillCompleted {
backfillWaiter = waiter
}
p, err := New(ctx, beaconDB, uint64(time.Now().Unix()), initSyncWaiter, backfillWaiter, WithSlotTicker(slotTicker))
p, err := New(ctx, beaconDB, time.Now(), initSyncWaiter, backfillWaiter, WithSlotTicker(slotTicker))
require.NoError(t, err)
go p.Start()
@@ -100,7 +100,7 @@ func TestPruner_PruneSuccess(t *testing.T) {
p, err := New(
ctx,
beaconDB,
uint64(time.Now().Unix()),
time.Now(),
nil,
nil,
WithSlotTicker(slotTicker),

View File

@@ -711,7 +711,7 @@ func (s *Service) cacheBlockHeaders(start, end uint64) error {
// Determines the earliest voting block from which to start caching all our previous headers from.
func (s *Service) determineEarliestVotingBlock(ctx context.Context, followBlock uint64) (uint64, error) {
genesisTime := s.chainStartData.GenesisTime
currSlot := slots.CurrentSlot(genesisTime)
currSlot := slots.CurrentSlot(time.Unix(int64(genesisTime), 0)) // lint:ignore uintcast -- Genesis time will never exceed int64 in seconds.
// In the event genesis has not occurred yet, we just request to go back follow_distance blocks.
if genesisTime == 0 || currSlot == 0 {
@@ -837,7 +837,7 @@ func (s *Service) validPowchainData(ctx context.Context) (*ethpb.ETH1ChainData,
}
s.chainStartData = &ethpb.ChainStartData{
Chainstarted: true,
GenesisTime: genState.GenesisTime(),
GenesisTime: uint64(genState.GenesisTime().Unix()),
GenesisBlock: 0,
Eth1Data: genState.Eth1Data(),
ChainstartDeposits: make([]*ethpb.Deposit, 0),

View File

@@ -70,7 +70,7 @@ func (f *ForkChoice) Head(
jc := f.JustifiedCheckpoint()
fc := f.FinalizedCheckpoint()
currentEpoch := slots.EpochsSinceGenesis(time.Unix(int64(f.store.genesisTime), 0))
currentEpoch := slots.EpochsSinceGenesis(f.store.genesisTime)
if err := f.store.treeRootNode.updateBestDescendant(ctx, jc.Epoch, fc.Epoch, currentEpoch); err != nil {
return [32]byte{}, errors.Wrap(err, "could not update best descendant")
}
@@ -486,8 +486,8 @@ func (f *ForkChoice) InsertChain(ctx context.Context, chain []*forkchoicetypes.B
}
// SetGenesisTime sets the genesisTime tracked by forkchoice
func (f *ForkChoice) SetGenesisTime(genesisTime uint64) {
f.store.genesisTime = genesisTime
func (f *ForkChoice) SetGenesisTime(genesis time.Time) {
f.store.genesisTime = genesis.Truncate(time.Second) // Genesis time has a precision of 1 second.
}
// SetOriginRoot sets the genesis block root

View File

@@ -5,7 +5,6 @@ import (
"encoding/binary"
"errors"
"testing"
"time"
"github.com/OffchainLabs/prysm/v6/beacon-chain/forkchoice"
forkchoicetypes "github.com/OffchainLabs/prysm/v6/beacon-chain/forkchoice/types"
@@ -691,7 +690,7 @@ func TestForkChoice_UpdateCheckpoints(t *testing.T) {
fcs := setup(tt.justified.Epoch, tt.finalized.Epoch)
fcs.store.justifiedCheckpoint = tt.justified
fcs.store.finalizedCheckpoint = tt.finalized
fcs.store.genesisTime = uint64(time.Now().Unix()) - uint64(tt.currentSlot)*params.BeaconConfig().SecondsPerSlot
driftGenesisTime(fcs, tt.currentSlot, 0)
st, roblock, err := prepareForkchoiceState(ctx, 32, [32]byte{'f'},
[32]byte{}, [32]byte{}, tt.finalized.Epoch, tt.finalized.Epoch)

View File

@@ -3,6 +3,7 @@ package doublylinkedtree
import (
"bytes"
"context"
"time"
"github.com/OffchainLabs/prysm/v6/config/params"
forkchoice2 "github.com/OffchainLabs/prysm/v6/consensus-types/forkchoice"
@@ -11,9 +12,9 @@ import (
"github.com/pkg/errors"
)
// ProcessAttestationsThreshold is the number of seconds after which we
// ProcessAttestationsThreshold is the amount of time after which we
// process attestations for the current slot
const ProcessAttestationsThreshold = 10
const ProcessAttestationsThreshold = 10 * time.Second
// applyWeightChanges recomputes the weight of the node passed as an argument and all of its descendants,
// using the current balance stored in each node.
@@ -131,10 +132,10 @@ func (n *Node) setNodeAndParentValidated(ctx context.Context) error {
// Note that genesisTime has seconds granularity, therefore we use a strict
// inequality < here. For example a block that arrives 3.9999 seconds into the
// slot will have secs = 3 below.
func (n *Node) arrivedEarly(genesisTime uint64) (bool, error) {
secs, err := slots.SecondsSinceSlotStart(n.slot, genesisTime, n.timestamp)
votingWindow := params.BeaconConfig().SecondsPerSlot / params.BeaconConfig().IntervalsPerSlot
return secs < votingWindow, err
func (n *Node) arrivedEarly(genesis time.Time) (bool, error) {
sss, err := slots.SinceSlotStart(n.slot, genesis, n.timestamp.Truncate(time.Second)) // Truncate such that 3.9999 seconds will have a value of 3.
votingWindow := time.Duration(params.BeaconConfig().SecondsPerSlot/params.BeaconConfig().IntervalsPerSlot) * time.Second
return sss < votingWindow, err
}
// arrivedAfterOrphanCheck returns whether this block was inserted after the
@@ -142,8 +143,8 @@ func (n *Node) arrivedEarly(genesisTime uint64) (bool, error) {
// Note that genesisTime has seconds granularity, therefore we use an
// inequality >= here. For example a block that arrives 10.00001 seconds into the
// slot will have secs = 10 below.
func (n *Node) arrivedAfterOrphanCheck(genesisTime uint64) (bool, error) {
secs, err := slots.SecondsSinceSlotStart(n.slot, genesisTime, n.timestamp)
func (n *Node) arrivedAfterOrphanCheck(genesis time.Time) (bool, error) {
secs, err := slots.SinceSlotStart(n.slot, genesis, n.timestamp.Truncate(time.Second)) // Truncate such that 10.00001 seconds will have a value of 10.
return secs >= ProcessAttestationsThreshold, err
}

View File

@@ -2,6 +2,7 @@ package doublylinkedtree
import (
"testing"
"time"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/forkchoice"
@@ -262,7 +263,7 @@ func TestNode_TimeStampsChecks(t *testing.T) {
ctx := t.Context()
// early block
driftGenesisTime(f, 1, 1)
driftGenesisTime(f, 1, time.Second)
root := [32]byte{'a'}
f.justifiedBalances = []uint64{10}
state, blk, err := prepareForkchoiceState(ctx, 1, root, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 0, 0)
@@ -278,9 +279,9 @@ func TestNode_TimeStampsChecks(t *testing.T) {
require.NoError(t, err)
require.Equal(t, false, late)
orphanLateBlockFirstThreshold := params.BeaconConfig().SecondsPerSlot / params.BeaconConfig().IntervalsPerSlot
orphanLateBlockFirstThreshold := time.Duration(params.BeaconConfig().SecondsPerSlot/params.BeaconConfig().IntervalsPerSlot) * time.Second
// late block
driftGenesisTime(f, 2, orphanLateBlockFirstThreshold+1)
driftGenesisTime(f, 2, orphanLateBlockFirstThreshold+time.Second)
root = [32]byte{'b'}
state, blk, err = prepareForkchoiceState(ctx, 2, root, [32]byte{'a'}, [32]byte{'B'}, 0, 0)
require.NoError(t, err)
@@ -296,7 +297,7 @@ func TestNode_TimeStampsChecks(t *testing.T) {
require.Equal(t, false, late)
// very late block
driftGenesisTime(f, 3, ProcessAttestationsThreshold+1)
driftGenesisTime(f, 3, ProcessAttestationsThreshold+time.Second)
root = [32]byte{'c'}
state, blk, err = prepareForkchoiceState(ctx, 3, root, [32]byte{'b'}, [32]byte{'C'}, 0, 0)
require.NoError(t, err)

View File

@@ -12,8 +12,12 @@ import (
// Helper function to simulate the block being on time or delayed for proposer
// boost. It alters the genesisTime tracked by the store.
func driftGenesisTime(f *ForkChoice, slot primitives.Slot, delay uint64) {
f.SetGenesisTime(uint64(time.Now().Unix()) - uint64(slot)*params.BeaconConfig().SecondsPerSlot - delay)
func driftGenesisTime(f *ForkChoice, slot primitives.Slot, delay time.Duration) {
genesis := time.Now()
s := time.Duration(slot*primitives.Slot(params.BeaconConfig().SecondsPerSlot)) * time.Second
genesis = genesis.Add(-1 * s)
genesis = genesis.Add(-1 * delay.Abs())
f.SetGenesisTime(genesis)
}
// Simple, ex-ante attack mitigation using proposer boost.
@@ -445,7 +449,7 @@ func TestForkChoice_BoostProposerRoot(t *testing.T) {
f := setup(0, 0)
slot := primitives.Slot(1)
currentSlot := primitives.Slot(1)
driftGenesisTime(f, currentSlot, params.BeaconConfig().SecondsPerSlot-1)
driftGenesisTime(f, currentSlot, time.Duration(params.BeaconConfig().SecondsPerSlot-1)*time.Second)
state, blkRoot, err := prepareForkchoiceState(ctx, slot, root, zeroHash, zeroHash, 0, 0)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
@@ -465,7 +469,7 @@ func TestForkChoice_BoostProposerRoot(t *testing.T) {
f := setup(0, 0)
slot := primitives.Slot(1)
currentSlot := primitives.Slot(1)
driftGenesisTime(f, currentSlot, 1)
driftGenesisTime(f, currentSlot, time.Second)
state, blkRoot, err := prepareForkchoiceState(ctx, slot, root, zeroHash, zeroHash, 0, 0)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blkRoot))

View File

@@ -83,12 +83,12 @@ func (f *ForkChoice) ShouldOverrideFCU() (override bool) {
}
// Return early if we are checking before 10 seconds into the slot
secs, err := slots.SecondsSinceSlotStart(head.slot, f.store.genesisTime, uint64(time.Now().Unix()))
sss, err := slots.SinceSlotStart(head.slot, f.store.genesisTime, time.Now())
if err != nil {
log.WithError(err).Error("could not check current slot")
return true
}
if secs < ProcessAttestationsThreshold {
if sss < ProcessAttestationsThreshold {
return true
}
// Only orphan a block if the parent LMD vote is strong
@@ -110,9 +110,9 @@ func (f *ForkChoice) GetProposerHead() [32]byte {
if head == nil {
return [32]byte{}
}
// Only reorg blocks from the previous slot.
if head.slot+1 != slots.CurrentSlot(f.store.genesisTime) {
currentSlot := slots.CurrentSlot(f.store.genesisTime)
if head.slot+1 != currentSlot {
return head.root
}
// Do not reorg on epoch boundaries
@@ -153,12 +153,12 @@ func (f *ForkChoice) GetProposerHead() [32]byte {
}
// Only reorg if we are proposing early
secs, err := slots.SecondsSinceSlotStart(head.slot+1, f.store.genesisTime, uint64(time.Now().Unix()))
sss, err := slots.SinceSlotStart(currentSlot, f.store.genesisTime, time.Now())
if err != nil {
log.WithError(err).Error("could not check if proposing early")
return head.root
}
if secs >= orphanLateBlockProposingEarly {
if sss >= orphanLateBlockProposingEarly*time.Second {
return head.root
}
return parent.root

View File

@@ -2,6 +2,7 @@ package doublylinkedtree
import (
"testing"
"time"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/testing/require"
@@ -27,8 +28,8 @@ func TestForkChoice_ShouldOverrideFCU(t *testing.T) {
}
f.ProcessAttestation(ctx, attesters, blk.Root(), 0)
orphanLateBlockFirstThreshold := params.BeaconConfig().SecondsPerSlot / params.BeaconConfig().IntervalsPerSlot
driftGenesisTime(f, 2, orphanLateBlockFirstThreshold+1)
orphanLateBlockFirstThreshold := time.Duration(params.BeaconConfig().SecondsPerSlot/params.BeaconConfig().IntervalsPerSlot) * time.Second
driftGenesisTime(f, 2, orphanLateBlockFirstThreshold+time.Second)
st, blk, err = prepareForkchoiceState(ctx, 2, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 0, 0)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, st, blk))
@@ -48,29 +49,29 @@ func TestForkChoice_ShouldOverrideFCU(t *testing.T) {
t.Run("head is not from current slot", func(t *testing.T) {
driftGenesisTime(f, 3, 0)
require.Equal(t, false, f.ShouldOverrideFCU())
driftGenesisTime(f, 2, orphanLateBlockFirstThreshold+1)
driftGenesisTime(f, 2, orphanLateBlockFirstThreshold+time.Second)
})
t.Run("head is from epoch boundary", func(t *testing.T) {
saved := f.store.headNode.slot
driftGenesisTime(f, params.BeaconConfig().SlotsPerEpoch-1, 0)
f.store.headNode.slot = params.BeaconConfig().SlotsPerEpoch - 1
require.Equal(t, false, f.ShouldOverrideFCU())
driftGenesisTime(f, 2, orphanLateBlockFirstThreshold+1)
driftGenesisTime(f, 2, orphanLateBlockFirstThreshold+time.Second)
f.store.headNode.slot = saved
})
t.Run("head is early", func(t *testing.T) {
saved := f.store.headNode.timestamp
f.store.headNode.timestamp = saved - 2
f.store.headNode.timestamp = saved.Add(-2 * time.Second)
require.Equal(t, false, f.ShouldOverrideFCU())
f.store.headNode.timestamp = saved
})
t.Run("chain not finalizing", func(t *testing.T) {
saved := f.store.headNode.slot
f.store.headNode.slot = 97
driftGenesisTime(f, 97, orphanLateBlockFirstThreshold+1)
driftGenesisTime(f, 97, orphanLateBlockFirstThreshold+time.Second)
require.Equal(t, false, f.ShouldOverrideFCU())
f.store.headNode.slot = saved
driftGenesisTime(f, 2, orphanLateBlockFirstThreshold+1)
driftGenesisTime(f, 2, orphanLateBlockFirstThreshold+time.Second)
})
t.Run("Not single block reorg", func(t *testing.T) {
saved := f.store.headNode.parent.slot
@@ -92,11 +93,11 @@ func TestForkChoice_ShouldOverrideFCU(t *testing.T) {
})
t.Run("parent is weak late call", func(t *testing.T) {
saved := f.store.headNode.parent.weight
driftGenesisTime(f, 2, 11)
driftGenesisTime(f, 2, 11*time.Second)
f.store.headNode.parent.weight = 0
require.Equal(t, false, f.ShouldOverrideFCU())
f.store.headNode.parent.weight = saved
driftGenesisTime(f, 2, orphanLateBlockFirstThreshold+1)
driftGenesisTime(f, 2, orphanLateBlockFirstThreshold+time.Second)
})
t.Run("Head is strong", func(t *testing.T) {
f.store.headNode.weight = f.store.committeeWeight
@@ -125,7 +126,7 @@ func TestForkChoice_GetProposerHead(t *testing.T) {
}
f.ProcessAttestation(ctx, attesters, blk.Root(), 0)
driftGenesisTime(f, 3, 1)
driftGenesisTime(f, 3, 1*time.Second)
childRoot := [32]byte{'b'}
st, blk, err = prepareForkchoiceState(ctx, 2, childRoot, [32]byte{'a'}, [32]byte{'B'}, 0, 0)
require.NoError(t, err)
@@ -134,10 +135,9 @@ func TestForkChoice_GetProposerHead(t *testing.T) {
require.NoError(t, err)
require.Equal(t, blk.Root(), headRoot)
orphanLateBlockFirstThreshold := params.BeaconConfig().SecondsPerSlot / params.BeaconConfig().IntervalsPerSlot
f.store.headNode.timestamp -= params.BeaconConfig().SecondsPerSlot - orphanLateBlockFirstThreshold
f.store.headNode.timestamp.Add(-1 * time.Duration(params.BeaconConfig().SecondsPerSlot-orphanLateBlockFirstThreshold) * time.Second)
t.Run("head is weak", func(t *testing.T) {
require.Equal(t, parentRoot, f.GetProposerHead())
})
t.Run("head is nil", func(t *testing.T) {
saved := f.store.headNode
@@ -148,19 +148,20 @@ func TestForkChoice_GetProposerHead(t *testing.T) {
t.Run("head is not from previous slot", func(t *testing.T) {
driftGenesisTime(f, 4, 0)
require.Equal(t, childRoot, f.GetProposerHead())
driftGenesisTime(f, 3, 1)
driftGenesisTime(f, 3, 1*time.Second)
})
t.Run("head is from epoch boundary", func(t *testing.T) {
saved := f.store.headNode.slot
driftGenesisTime(f, params.BeaconConfig().SlotsPerEpoch, 0)
f.store.headNode.slot = params.BeaconConfig().SlotsPerEpoch - 1
require.Equal(t, childRoot, f.GetProposerHead())
driftGenesisTime(f, 3, 1)
driftGenesisTime(f, 3, 1*time.Second)
f.store.headNode.slot = saved
})
t.Run("head is early", func(t *testing.T) {
saved := f.store.headNode.timestamp
f.store.headNode.timestamp = saved - 2
headTimeStamp := f.store.genesisTime.Add(time.Duration(uint64(f.store.headNode.slot)*params.BeaconConfig().SecondsPerSlot+1) * time.Second)
f.store.headNode.timestamp = headTimeStamp
require.Equal(t, childRoot, f.GetProposerHead())
f.store.headNode.timestamp = saved
})
@@ -170,7 +171,7 @@ func TestForkChoice_GetProposerHead(t *testing.T) {
driftGenesisTime(f, 98, 0)
require.Equal(t, childRoot, f.GetProposerHead())
f.store.headNode.slot = saved
driftGenesisTime(f, 3, 1)
driftGenesisTime(f, 3, 1*time.Second)
})
t.Run("Not single block reorg", func(t *testing.T) {
saved := f.store.headNode.parent.slot

View File

@@ -44,7 +44,7 @@ func (s *Store) head(ctx context.Context) ([32]byte, error) {
if bestDescendant == nil {
bestDescendant = justifiedNode
}
currentEpoch := slots.EpochsSinceGenesis(time.Unix(int64(s.genesisTime), 0))
currentEpoch := slots.EpochsSinceGenesis(s.genesisTime)
if !bestDescendant.viableForHead(s.justifiedCheckpoint.Epoch, currentEpoch) {
s.allTipsAreInvalid = true
return [32]byte{}, fmt.Errorf("head at slot %d with weight %d is not eligible, finalizedEpoch, justified Epoch %d, %d != %d, %d",
@@ -99,7 +99,7 @@ func (s *Store) insert(ctx context.Context,
unrealizedFinalizedEpoch: finalizedEpoch,
optimistic: true,
payloadHash: payloadHash,
timestamp: uint64(time.Now().Unix()),
timestamp: time.Now(),
}
// Set the node's target checkpoint
@@ -128,15 +128,18 @@ func (s *Store) insert(ctx context.Context,
} else {
parent.children = append(parent.children, n)
// Apply proposer boost
timeNow := uint64(time.Now().Unix())
if timeNow < s.genesisTime {
now := time.Now()
if now.Before(s.genesisTime) {
return n, nil
}
secondsIntoSlot := (timeNow - s.genesisTime) % params.BeaconConfig().SecondsPerSlot
currentSlot := slots.CurrentSlot(s.genesisTime)
boostThreshold := params.BeaconConfig().SecondsPerSlot / params.BeaconConfig().IntervalsPerSlot
sss, err := slots.SinceSlotStart(currentSlot, s.genesisTime, now)
if err != nil {
return nil, fmt.Errorf("could not determine time since current slot started: %w", err)
}
boostThreshold := time.Duration(params.BeaconConfig().SecondsPerSlot/params.BeaconConfig().IntervalsPerSlot) * time.Second
isFirstBlock := s.proposerBoostRoot == [32]byte{}
if currentSlot == slot && secondsIntoSlot < boostThreshold && isFirstBlock {
if currentSlot == slot && sss < boostThreshold && isFirstBlock {
s.proposerBoostRoot = root
}
@@ -268,17 +271,18 @@ func (f *ForkChoice) HighestReceivedBlockSlot() primitives.Slot {
}
// HighestReceivedBlockDelay returns the number of slots that the highest
// received block was late when receiving it
// received block was late when receiving it. For example, a block was late by 12 slots,
// then this method is expected to return 12.
func (f *ForkChoice) HighestReceivedBlockDelay() primitives.Slot {
n := f.store.highestReceivedNode
if n == nil {
return 0
}
secs, err := slots.SecondsSinceSlotStart(n.slot, f.store.genesisTime, n.timestamp)
sss, err := slots.SinceSlotStart(n.slot, f.store.genesisTime, n.timestamp)
if err != nil {
return 0
}
return primitives.Slot(secs / params.BeaconConfig().SecondsPerSlot)
return primitives.Slot(uint64(sss/time.Second) / params.BeaconConfig().SecondsPerSlot)
}
// ReceivedBlocksLastEpoch returns the number of blocks received in the last epoch

View File

@@ -329,7 +329,7 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) {
var b [32]byte
// Make sure it doesn't underflow
s.genesisTime = uint64(time.Now().Add(time.Duration(-1*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix())
f.SetGenesisTime(time.Now().Add(time.Duration(-1*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
ctx := t.Context()
_, blk, err := prepareForkchoiceState(ctx, 1, [32]byte{'a'}, b, b, 1, 1)
require.NoError(t, err)
@@ -347,7 +347,7 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) {
require.NoError(t, err)
_, err = s.insert(ctx, blk, 1, 1)
require.NoError(t, err)
s.genesisTime = uint64(time.Now().Add(time.Duration((-64*int64(params.BeaconConfig().SecondsPerSlot))-1) * time.Second).Unix())
f.SetGenesisTime(time.Now().Add(time.Duration((-64*int64(params.BeaconConfig().SecondsPerSlot))-1) * time.Second))
count, err = f.ReceivedBlocksLastEpoch()
require.NoError(t, err)
require.Equal(t, uint64(1), count)
@@ -360,7 +360,7 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) {
require.NoError(t, err)
_, err = s.insert(ctx, blk, 1, 1)
require.NoError(t, err)
s.genesisTime = uint64(time.Now().Add(time.Duration(-66*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix())
f.SetGenesisTime(time.Now().Add(time.Duration(-66*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
count, err = f.ReceivedBlocksLastEpoch()
require.NoError(t, err)
require.Equal(t, uint64(2), count)
@@ -373,7 +373,7 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) {
require.NoError(t, err)
_, err = s.insert(ctx, blk, 1, 1)
require.NoError(t, err)
s.genesisTime = uint64(time.Now().Add(time.Duration(-66*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix())
f.SetGenesisTime(time.Now().Add(time.Duration(-66*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
count, err = f.ReceivedBlocksLastEpoch()
require.NoError(t, err)
require.Equal(t, uint64(3), count)
@@ -386,7 +386,7 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) {
require.NoError(t, err)
_, err = s.insert(ctx, blk, 1, 1)
require.NoError(t, err)
s.genesisTime = uint64(time.Now().Add(time.Duration(-98*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix())
f.SetGenesisTime(time.Now().Add(time.Duration(-98*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
count, err = f.ReceivedBlocksLastEpoch()
require.NoError(t, err)
require.Equal(t, uint64(1), count)
@@ -400,7 +400,7 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) {
require.NoError(t, err)
_, err = s.insert(ctx, blk, 1, 1)
require.NoError(t, err)
s.genesisTime = uint64(time.Now().Add(time.Duration(-132*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix())
f.SetGenesisTime(time.Now().Add(time.Duration(-132*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
count, err = f.ReceivedBlocksLastEpoch()
require.NoError(t, err)
require.Equal(t, uint64(1), count)
@@ -415,7 +415,7 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) {
require.NoError(t, err)
_, err = s.insert(ctx, blk, 1, 1)
require.NoError(t, err)
s.genesisTime = uint64(time.Now().Add(time.Duration(-132*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix())
f.SetGenesisTime(time.Now().Add(time.Duration(-132*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
count, err = f.ReceivedBlocksLastEpoch()
require.NoError(t, err)
require.Equal(t, uint64(1), count)
@@ -430,7 +430,7 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) {
require.NoError(t, err)
_, err = s.insert(ctx, blk, 1, 1)
require.NoError(t, err)
s.genesisTime = uint64(time.Now().Add(time.Duration(-132*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix())
f.SetGenesisTime(time.Now().Add(time.Duration(-132*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
count, err = f.ReceivedBlocksLastEpoch()
require.NoError(t, err)
require.Equal(t, uint64(1), count)
@@ -445,17 +445,17 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) {
require.NoError(t, err)
_, err = s.insert(ctx, blk, 1, 1)
require.NoError(t, err)
s.genesisTime = uint64(time.Now().Add(time.Duration(-132*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix())
f.SetGenesisTime(time.Now().Add(time.Duration(-132*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
count, err = f.ReceivedBlocksLastEpoch()
require.NoError(t, err)
require.Equal(t, uint64(2), count)
require.Equal(t, primitives.Slot(132), f.HighestReceivedBlockSlot())
s.genesisTime = uint64(time.Now().Add(time.Duration(-134*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix())
f.SetGenesisTime(time.Now().Add(time.Duration(-134*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
count, err = f.ReceivedBlocksLastEpoch()
require.NoError(t, err)
require.Equal(t, uint64(1), count)
s.genesisTime = uint64(time.Now().Add(time.Duration(-165*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix())
f.SetGenesisTime(time.Now().Add(time.Duration(-165*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second))
count, err = f.ReceivedBlocksLastEpoch()
require.NoError(t, err)
require.Equal(t, uint64(0), count)
@@ -616,3 +616,17 @@ func TestStore_CleanupInserting(t *testing.T) {
require.NotNil(t, f.InsertNode(ctx, st, blk))
require.Equal(t, false, f.HasNode(blk.Root()))
}
func TestStore_HighestReceivedBlockDelay(t *testing.T) {
f := ForkChoice{
store: &Store{
genesisTime: time.Unix(0, 0),
highestReceivedNode: &Node{
slot: 10,
timestamp: time.Unix(int64(((10 + 12) * params.BeaconConfig().SecondsPerSlot)), 0), // 12 slots late
},
},
}
require.Equal(t, primitives.Slot(12), f.HighestReceivedBlockDelay())
}

View File

@@ -2,6 +2,7 @@ package doublylinkedtree
import (
"sync"
"time"
"github.com/OffchainLabs/prysm/v6/beacon-chain/forkchoice"
forkchoicetypes "github.com/OffchainLabs/prysm/v6/beacon-chain/forkchoice/types"
@@ -37,7 +38,7 @@ type Store struct {
nodeByPayload map[[fieldparams.RootLength]byte]*Node // nodes indexed by payload Hash
slashedIndices map[primitives.ValidatorIndex]bool // the list of equivocating validator indices
originRoot [fieldparams.RootLength]byte // The genesis block root
genesisTime uint64
genesisTime time.Time
highestReceivedNode *Node // The highest slot node.
receivedBlocksLastEpoch [fieldparams.SlotsPerEpoch]primitives.Slot // Using `highestReceivedSlot`. The slot of blocks received in the last epoch.
allTipsAreInvalid bool // tracks if all tips are not viable for head
@@ -60,7 +61,7 @@ type Node struct {
weight uint64 // weight of this node: the total balance including children
bestDescendant *Node // bestDescendant node of this node.
optimistic bool // whether the block has been fully validated or not
timestamp uint64 // The timestamp when the node was inserted.
timestamp time.Time // The timestamp when the node was inserted.
}
// Vote defines an individual validator's vote.

View File

@@ -2,6 +2,7 @@ package forkchoice
import (
"context"
"time"
forkchoicetypes "github.com/OffchainLabs/prysm/v6/beacon-chain/forkchoice/types"
"github.com/OffchainLabs/prysm/v6/beacon-chain/state"
@@ -92,7 +93,7 @@ type Setter interface {
SetOptimisticToInvalid(context.Context, [fieldparams.RootLength]byte, [fieldparams.RootLength]byte, [fieldparams.RootLength]byte) ([][32]byte, error)
UpdateJustifiedCheckpoint(context.Context, *forkchoicetypes.Checkpoint) error
UpdateFinalizedCheckpoint(*forkchoicetypes.Checkpoint) error
SetGenesisTime(uint64)
SetGenesisTime(time.Time)
SetOriginRoot([32]byte)
NewSlot(context.Context, primitives.Slot) error
SetBalancesByRooter(BalancesByRooter)

View File

@@ -16,6 +16,7 @@ import (
"strings"
"sync"
"syscall"
"time"
"github.com/OffchainLabs/prysm/v6/api/server/httprest"
"github.com/OffchainLabs/prysm/v6/api/server/middleware"
@@ -1128,7 +1129,7 @@ func (b *BeaconNode) registerBuilderService(cliCtx *cli.Context) error {
}
func (b *BeaconNode) registerPrunerService(cliCtx *cli.Context) error {
genesisTimeUnix := params.BeaconConfig().MinGenesisTime + params.BeaconConfig().GenesisDelay
genesis := time.Unix(int64(params.BeaconConfig().MinGenesisTime+params.BeaconConfig().GenesisDelay), 0)
var backfillService *backfill.Service
if err := b.services.FetchService(&backfillService); err != nil {
return err
@@ -1143,7 +1144,7 @@ func (b *BeaconNode) registerPrunerService(cliCtx *cli.Context) error {
p, err := pruner.New(
cliCtx.Context,
b.db,
genesisTimeUnix,
genesis,
initSyncWaiter(cliCtx.Context, b.initialSyncComplete),
backfillService.WaitForCompletion,
opts...,

View File

@@ -31,7 +31,7 @@ func (s *Service) prepareForkChoiceAtts() {
break
}
}
ticker := slots.NewSlotTickerWithIntervals(time.Unix(int64(s.genesisTime), 0), intervals[:])
ticker := slots.NewSlotTickerWithIntervals(s.genesisTime, intervals[:])
for {
select {
case slotInterval := <-ticker.C():

View File

@@ -5,7 +5,6 @@ import (
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
prysmTime "github.com/OffchainLabs/prysm/v6/time"
"github.com/OffchainLabs/prysm/v6/time/slots"
)
@@ -97,9 +96,8 @@ func (s *Service) expired(providedSlot primitives.Slot) bool {
// Handles expiration of attestations before deneb.
func (s *Service) expiredPreDeneb(slot primitives.Slot) bool {
expirationSlot := slot + params.BeaconConfig().SlotsPerEpoch
expirationTime := s.genesisTime + uint64(expirationSlot.Mul(params.BeaconConfig().SecondsPerSlot))
currentTime := uint64(prysmTime.Now().Unix())
return currentTime >= expirationTime
expirationTime := s.genesisTime.Add(time.Duration(expirationSlot.Mul(params.BeaconConfig().SecondsPerSlot)) * time.Second)
return expirationTime.Before(time.Now())
}
// Attestations for a slot before the returned slot are considered expired.

View File

@@ -13,7 +13,6 @@ import (
"github.com/OffchainLabs/prysm/v6/testing/assert"
"github.com/OffchainLabs/prysm/v6/testing/require"
"github.com/OffchainLabs/prysm/v6/testing/util"
prysmTime "github.com/OffchainLabs/prysm/v6/time"
"github.com/prysmaticlabs/go-bitfield"
)
@@ -48,7 +47,7 @@ func TestPruneExpired_Ticker(t *testing.T) {
}
// Rewind back one epoch worth of time.
s.genesisTime = uint64(prysmTime.Now().Unix()) - uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
s.genesisTime = time.Now().Add(-1 * time.Duration(params.BeaconConfig().SlotsPerEpoch) * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
go s.pruneExpired()
@@ -101,7 +100,7 @@ func TestPruneExpired_PruneExpiredAtts(t *testing.T) {
}
// Rewind back one epoch worth of time.
s.genesisTime = uint64(prysmTime.Now().Unix()) - uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
s.genesisTime = time.Now().Add(-1 * time.Duration(params.BeaconConfig().SlotsPerEpoch) * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
s.pruneExpiredAtts()
// All the attestations on slot 0 should be pruned.
@@ -122,7 +121,7 @@ func TestPruneExpired_Expired(t *testing.T) {
require.NoError(t, err)
// Rewind back one epoch worth of time.
s.genesisTime = uint64(prysmTime.Now().Unix()) - uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
s.genesisTime = time.Now().Add(-1 * time.Duration(params.BeaconConfig().SlotsPerEpoch) * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
assert.Equal(t, true, s.expired(0), "Should be expired")
assert.Equal(t, false, s.expired(1), "Should not be expired")
}
@@ -137,7 +136,7 @@ func TestPruneExpired_ExpiredDeneb(t *testing.T) {
require.NoError(t, err)
// Rewind back 4 epochs + 10 slots worth of time.
s.genesisTime = uint64(prysmTime.Now().Unix()) - (4*uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot)) + 10)
s.genesisTime = time.Now().Add(-4*time.Duration(params.BeaconConfig().SlotsPerEpoch*primitives.Slot(params.BeaconConfig().SecondsPerSlot))*time.Second - 10*time.Duration(params.BeaconConfig().SecondsPerSlot)*time.Second)
secondEpochStart := primitives.Slot(2 * uint64(params.BeaconConfig().SlotsPerEpoch))
thirdEpochStart := primitives.Slot(3 * uint64(params.BeaconConfig().SlotsPerEpoch))

View File

@@ -24,7 +24,7 @@ type Service struct {
cancel context.CancelFunc
err error
forkChoiceProcessedAtts *lru.Cache
genesisTime uint64
genesisTime time.Time
}
// Config options for the service.
@@ -95,6 +95,6 @@ func (s *Service) Status() error {
}
// SetGenesisTime sets genesis time for operation service to use.
func (s *Service) SetGenesisTime(t uint64) {
s.genesisTime = t
func (s *Service) SetGenesisTime(t time.Time) {
s.genesisTime = t.Truncate(time.Second) // Genesis time has a precision of 1 second.
}

View File

@@ -61,7 +61,7 @@ func (p *PoolService) run() {
p.waitForChainInitialization()
electraTime, err := slots.ToTime(uint64(p.clock.GenesisTime().Unix()), electraSlot)
electraTime, err := slots.ToTime(p.clock.GenesisTime(), electraSlot)
if err != nil {
return
}

View File

@@ -140,7 +140,7 @@ func (s *Service) internalBroadcastAttestation(ctx context.Context, subnet uint6
}
// In the event our attestation is outdated and beyond the
// acceptable threshold, we exit early and do not broadcast it.
currSlot := slots.CurrentSlot(uint64(s.genesisTime.Unix()))
currSlot := slots.CurrentSlot(s.genesisTime)
if err := helpers.ValidateAttestationTime(att.GetData().Slot, s.genesisTime, params.BeaconConfig().MaximumGossipClockDisparityDuration()); err != nil {
log.WithFields(logrus.Fields{
"attestationSlot": att.GetData().Slot,
@@ -397,7 +397,7 @@ func (s *Service) internalBroadcastDataColumn(
header := dataColumnSidecar.SignedBlockHeader.GetHeader()
slot := header.GetSlot()
slotStartTime, err := slots.ToTime(uint64(s.genesisTime.Unix()), slot)
slotStartTime, err := slots.ToTime(s.genesisTime, slot)
if err != nil {
log.WithError(err).Error("Failed to convert slot to time")
}

View File

@@ -147,7 +147,7 @@ func (s *Service) RefreshPersistentSubnets() {
}
// Get the current epoch.
currentSlot := slots.CurrentSlot(uint64(s.genesisTime.Unix()))
currentSlot := slots.CurrentSlot(s.genesisTime)
currentEpoch := slots.ToEpoch(currentSlot)
// Get our node ID.

View File

@@ -71,7 +71,7 @@ func pubKey(i uint64) []byte {
func TestService_SubmitSignedAggregateSelectionProof(t *testing.T) {
slot := primitives.Slot(0)
mock := &mockChain.ChainService{Slot: &slot}
mock := &mockChain.ChainService{Slot: &slot, Genesis: time.Now().Add(-75 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)}
s := &Service{GenesisTimeFetcher: mock}
var err error
t.Run("Happy path electra", func(t *testing.T) {
@@ -107,6 +107,7 @@ func TestService_SubmitSignedAggregateSelectionProof(t *testing.T) {
Signature: fakeSig,
}
rpcError := s.SubmitSignedAggregateSelectionProof(t.Context(), agg)
t.Log(rpcError)
assert.Equal(t, true, rpcError == nil)
})

View File

@@ -189,7 +189,7 @@ func (s *Server) GetForkChoice(w http.ResponseWriter, r *http.Request) {
UnrealizedFinalizedEpoch: fmt.Sprintf("%d", n.UnrealizedFinalizedEpoch),
Balance: fmt.Sprintf("%d", n.Balance),
ExecutionOptimistic: n.ExecutionOptimistic,
TimeStamp: fmt.Sprintf("%d", n.Timestamp),
TimeStamp: fmt.Sprintf("%s", n.Timestamp),
Target: fmt.Sprintf("%#x", n.Target),
},
}

View File

@@ -534,7 +534,7 @@ func TestStreamEvents_OperationsEvents(t *testing.T) {
require.NoError(t, st.SetSlot(currentSlot+1))
b := tc.getBlock()
genesis := time.Now()
require.NoError(t, st.SetGenesisTime(uint64(genesis.Unix())))
require.NoError(t, st.SetGenesisTime(genesis))
mockChainService := &mockChain.ChainService{
Root: make([]byte, 32),
State: st,

View File

@@ -707,7 +707,7 @@ func TestSubmitContributionAndProofs(t *testing.T) {
func TestSubmitAggregateAndProofs(t *testing.T) {
slot := primitives.Slot(0)
mock := &mockChain.ChainService{Slot: &slot}
mock := &mockChain.ChainService{Slot: &slot, Genesis: time.Now().Add(-1 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)}
s := &Server{
CoreService: &core.Service{GenesisTimeFetcher: mock},
TimeFetcher: mock,
@@ -2655,7 +2655,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) {
genesisTime := time.Now()
numVals := uint64(11)
st, _ := util.DeterministicGenesisStateAltair(t, numVals)
require.NoError(t, st.SetGenesisTime(uint64(genesisTime.Unix())))
require.NoError(t, st.SetGenesisTime(genesisTime))
vals := st.Validators()
currCommittee := &ethpbalpha.SyncCommittee{}
for i := 0; i < 5; i++ {
@@ -2841,7 +2841,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) {
newSyncPeriodStartSlot := primitives.Slot(uint64(params.BeaconConfig().EpochsPerSyncCommitteePeriod) * uint64(params.BeaconConfig().SlotsPerEpoch))
newSyncPeriodSt, _ := util.DeterministicGenesisStateAltair(t, numVals)
require.NoError(t, newSyncPeriodSt.SetSlot(newSyncPeriodStartSlot))
require.NoError(t, newSyncPeriodSt.SetGenesisTime(uint64(genesisTime.Unix())))
require.NoError(t, newSyncPeriodSt.SetGenesisTime(genesisTime))
vals := newSyncPeriodSt.Validators()
currCommittee := &ethpbalpha.SyncCommittee{}
for i := 5; i < 10; i++ {

View File

@@ -54,7 +54,7 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
defer span.End()
span.SetAttributes(trace.Int64Attribute("slot", int64(req.Slot)))
t, err := slots.ToTime(uint64(vs.TimeFetcher.GenesisTime().Unix()), req.Slot)
t, err := slots.ToTime(vs.TimeFetcher.GenesisTime(), req.Slot)
if err != nil {
log.WithError(err).Error("Could not convert slot to time")
}

View File

@@ -271,7 +271,7 @@ func (vs *Server) getPayloadHeaderFromBuilder(
}
}
t, err := slots.ToTime(uint64(vs.TimeFetcher.GenesisTime().Unix()), slot)
t, err := slots.ToTime(vs.TimeFetcher.GenesisTime(), slot)
if err != nil {
return nil, err
}

View File

@@ -118,7 +118,7 @@ func TestServer_setExecutionData(t *testing.T) {
Timestamp: uint64(time.Now().Unix()),
GasLimit: gasLimit,
Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}}))
ti, err := slots.ToTime(uint64(time.Now().Unix()), 0)
ti, err := slots.ToTime(time.Now(), 0)
require.NoError(t, err)
sk, err := bls.RandKey()
require.NoError(t, err)
@@ -160,7 +160,7 @@ func TestServer_setExecutionData(t *testing.T) {
require.NoError(t, err)
chain := &blockchainTest.ChainService{ForkChoiceStore: doublylinkedtree.New(), Genesis: time.Now(), Block: wb}
vs.ForkchoiceFetcher = chain
vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(uint64(time.Now().Unix()))
vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(time.Now())
vs.TimeFetcher = chain
vs.HeadFetcher = chain
b := blk.Block()
@@ -187,7 +187,7 @@ func TestServer_setExecutionData(t *testing.T) {
Timestamp: uint64(time.Now().Unix()),
GasLimit: gasLimit,
Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}}))
ti, err := slots.ToTime(uint64(time.Now().Unix()), 0)
ti, err := slots.ToTime(time.Now(), 0)
require.NoError(t, err)
sk, err := bls.RandKey()
require.NoError(t, err)
@@ -232,7 +232,7 @@ func TestServer_setExecutionData(t *testing.T) {
require.NoError(t, err)
chain := &blockchainTest.ChainService{ForkChoiceStore: doublylinkedtree.New(), Genesis: time.Now(), Block: wb}
vs.ForkFetcher = chain
vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(uint64(time.Now().Unix()))
vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(time.Now())
vs.TimeFetcher = chain
vs.HeadFetcher = chain
@@ -259,7 +259,7 @@ func TestServer_setExecutionData(t *testing.T) {
Timestamp: uint64(time.Now().Unix()),
GasLimit: gasLimit,
Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}}))
ti, err := slots.ToTime(uint64(time.Now().Unix()), 0)
ti, err := slots.ToTime(time.Now(), 0)
require.NoError(t, err)
sk, err := bls.RandKey()
require.NoError(t, err)
@@ -303,7 +303,7 @@ func TestServer_setExecutionData(t *testing.T) {
require.NoError(t, err)
chain := &blockchainTest.ChainService{ForkChoiceStore: doublylinkedtree.New(), Genesis: time.Now(), Block: wb}
vs.ForkFetcher = chain
vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(uint64(time.Now().Unix()))
vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(time.Now())
vs.TimeFetcher = chain
vs.HeadFetcher = chain
@@ -330,7 +330,7 @@ func TestServer_setExecutionData(t *testing.T) {
Timestamp: uint64(time.Now().Unix()),
GasLimit: gasLimit,
Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}}))
ti, err := slots.ToTime(uint64(time.Now().Unix()), 0)
ti, err := slots.ToTime(time.Now(), 0)
require.NoError(t, err)
sk, err := bls.RandKey()
require.NoError(t, err)
@@ -374,7 +374,7 @@ func TestServer_setExecutionData(t *testing.T) {
require.NoError(t, err)
chain := &blockchainTest.ChainService{ForkChoiceStore: doublylinkedtree.New(), Genesis: time.Now(), Block: wb}
vs.ForkFetcher = chain
vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(uint64(time.Now().Unix()))
vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(time.Now())
vs.TimeFetcher = chain
vs.HeadFetcher = chain
@@ -537,7 +537,7 @@ func TestServer_setExecutionData(t *testing.T) {
blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockDeneb())
require.NoError(t, err)
ti, err := slots.ToTime(uint64(time.Now().Unix()), 0)
ti, err := slots.ToTime(time.Now(), 0)
require.NoError(t, err)
sk, err := bls.RandKey()
require.NoError(t, err)
@@ -593,7 +593,7 @@ func TestServer_setExecutionData(t *testing.T) {
require.NoError(t, err)
chain := &blockchainTest.ChainService{ForkChoiceStore: doublylinkedtree.New(), Genesis: time.Now(), Block: wb}
vs.ForkFetcher = chain
vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(uint64(time.Now().Unix()))
vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(time.Now())
vs.TimeFetcher = chain
vs.HeadFetcher = chain
@@ -635,7 +635,7 @@ func TestServer_setExecutionData(t *testing.T) {
blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockElectra())
require.NoError(t, err)
ti, err := slots.ToTime(uint64(time.Now().Unix()), 0)
ti, err := slots.ToTime(time.Now(), 0)
require.NoError(t, err)
sk, err := bls.RandKey()
require.NoError(t, err)
@@ -717,7 +717,7 @@ func TestServer_setExecutionData(t *testing.T) {
require.NoError(t, err)
chain := &blockchainTest.ChainService{ForkChoiceStore: doublylinkedtree.New(), Genesis: time.Now(), Block: wb}
vs.ForkFetcher = chain
vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(uint64(time.Now().Unix()))
vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(time.Now())
vs.TimeFetcher = chain
vs.HeadFetcher = chain
@@ -772,7 +772,7 @@ func TestServer_getPayloadHeader(t *testing.T) {
params.OverrideBeaconConfig(cfg)
emptyRoot, err := ssz.TransactionsRoot([][]byte{})
require.NoError(t, err)
ti, err := slots.ToTime(uint64(time.Now().Unix()), 0)
ti, err := slots.ToTime(time.Now(), 0)
require.NoError(t, err)
sk, err := bls.RandKey()
@@ -814,7 +814,7 @@ func TestServer_getPayloadHeader(t *testing.T) {
wr, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload)
require.NoError(t, err)
tiCapella, err := slots.ToTime(uint64(genesis.Unix()), primitives.Slot(fakeCapellaEpoch)*params.BeaconConfig().SlotsPerEpoch)
tiCapella, err := slots.ToTime(genesis, primitives.Slot(fakeCapellaEpoch)*params.BeaconConfig().SlotsPerEpoch)
require.NoError(t, err)
bidCapella := &ethpb.BuilderBidCapella{
Header: &v1.ExecutionPayloadHeaderCapella{

View File

@@ -29,7 +29,7 @@ func TestServer_circuitBreakBuilder(t *testing.T) {
require.ErrorContains(t, "no fork choicer configured", err)
s.ForkchoiceFetcher = &blockchainTest.ChainService{ForkChoiceStore: doublylinkedtree.New()}
s.ForkchoiceFetcher.SetForkChoiceGenesisTime(uint64(time.Now().Unix()))
s.ForkchoiceFetcher.SetForkChoiceGenesisTime(time.Now())
b, err := s.circuitBreakBuilder(params.BeaconConfig().MaxBuilderConsecutiveMissedSlots + 1)
require.NoError(
t,
@@ -117,7 +117,7 @@ func TestServer_canUseBuilder(t *testing.T) {
ctx := t.Context()
proposerServer.ForkchoiceFetcher = &blockchainTest.ChainService{ForkChoiceStore: doublylinkedtree.New()}
proposerServer.ForkchoiceFetcher.SetForkChoiceGenesisTime(uint64(time.Now().Unix()))
proposerServer.ForkchoiceFetcher.SetForkChoiceGenesisTime(time.Now())
reg, err = proposerServer.canUseBuilder(ctx, params.BeaconConfig().MaxBuilderConsecutiveMissedSlots+1, 0)
require.NoError(t, err)
require.Equal(t, false, reg)

View File

@@ -197,7 +197,7 @@ func (vs *Server) WaitForChainStart(_ *emptypb.Empty, stream ethpb.BeaconNodeVal
if head != nil && !head.IsNil() {
res := &ethpb.ChainStartResponse{
Started: true,
GenesisTime: head.GenesisTime(),
GenesisTime: uint64(head.GenesisTime().Unix()),
GenesisValidatorsRoot: head.GenesisValidatorsRoot(),
}
return stream.Send(res)

View File

@@ -6,6 +6,7 @@ package state
import (
"context"
"encoding/json"
"time"
customtypes "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native/custom-types"
fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams"
@@ -64,7 +65,7 @@ type ReadOnlyBeaconState interface {
ReadOnlyProposerLookahead
ToProtoUnsafe() interface{}
ToProto() interface{}
GenesisTime() uint64
GenesisTime() time.Time
GenesisValidatorsRoot() []byte
Slot() primitives.Slot
Fork() *ethpb.Fork
@@ -97,7 +98,7 @@ type WriteOnlyBeaconState interface {
WriteOnlyWithdrawals
WriteOnlyDeposits
WriteOnlyProposerLookahead
SetGenesisTime(val uint64) error
SetGenesisTime(val time.Time) error
SetGenesisValidatorsRoot(val []byte) error
SetSlot(val primitives.Slot) error
SetFork(val *ethpb.Fork) error

View File

@@ -1,6 +1,8 @@
package state_native
import (
"time"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/runtime/version"
@@ -11,12 +13,12 @@ func (b *BeaconState) Id() uint64 {
return b.id
}
// GenesisTime of the beacon state as a uint64.
func (b *BeaconState) GenesisTime() uint64 {
// GenesisTime of the beacon state as a time.Time.
func (b *BeaconState) GenesisTime() time.Time {
b.lock.RLock()
defer b.lock.RUnlock()
return b.genesisTime
return time.Unix(int64(b.genesisTime), 0) // TODO(preston): Can this just be a time.Time?
}
// GenesisValidatorsRoot of the beacon state.

View File

@@ -2,6 +2,7 @@ package state_native_test
import (
"testing"
"time"
statenative "github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native"
"github.com/OffchainLabs/prysm/v6/config/params"
@@ -18,7 +19,7 @@ import (
func TestComputeFieldRootsWithHasher_Phase0(t *testing.T) {
beaconState, err := util.NewBeaconState(util.FillRootsNaturalOpt)
require.NoError(t, err)
require.NoError(t, beaconState.SetGenesisTime(123))
require.NoError(t, beaconState.SetGenesisTime(time.Unix(123, 0)))
require.NoError(t, beaconState.SetGenesisValidatorsRoot(genesisValidatorsRoot()))
require.NoError(t, beaconState.SetSlot(123))
require.NoError(t, beaconState.SetFork(fork()))
@@ -82,7 +83,7 @@ func TestComputeFieldRootsWithHasher_Phase0(t *testing.T) {
func TestComputeFieldRootsWithHasher_Altair(t *testing.T) {
beaconState, err := util.NewBeaconStateAltair(util.FillRootsNaturalOptAltair)
require.NoError(t, err)
require.NoError(t, beaconState.SetGenesisTime(123))
require.NoError(t, beaconState.SetGenesisTime(time.Unix(123, 0)))
require.NoError(t, beaconState.SetGenesisValidatorsRoot(genesisValidatorsRoot()))
require.NoError(t, beaconState.SetSlot(123))
require.NoError(t, beaconState.SetFork(fork()))
@@ -152,7 +153,7 @@ func TestComputeFieldRootsWithHasher_Altair(t *testing.T) {
func TestComputeFieldRootsWithHasher_Bellatrix(t *testing.T) {
beaconState, err := util.NewBeaconStateBellatrix(util.FillRootsNaturalOptBellatrix)
require.NoError(t, err)
require.NoError(t, beaconState.SetGenesisTime(123))
require.NoError(t, beaconState.SetGenesisTime(time.Unix(123, 0)))
require.NoError(t, beaconState.SetGenesisValidatorsRoot(genesisValidatorsRoot()))
require.NoError(t, beaconState.SetSlot(123))
require.NoError(t, beaconState.SetFork(fork()))
@@ -226,7 +227,7 @@ func TestComputeFieldRootsWithHasher_Bellatrix(t *testing.T) {
func TestComputeFieldRootsWithHasher_Capella(t *testing.T) {
beaconState, err := util.NewBeaconStateCapella(util.FillRootsNaturalOptCapella)
require.NoError(t, err)
require.NoError(t, beaconState.SetGenesisTime(123))
require.NoError(t, beaconState.SetGenesisTime(time.Unix(123, 0)))
require.NoError(t, beaconState.SetGenesisValidatorsRoot(genesisValidatorsRoot()))
require.NoError(t, beaconState.SetSlot(123))
require.NoError(t, beaconState.SetFork(fork()))

View File

@@ -1,6 +1,8 @@
package state_native
import (
"time"
"github.com/OffchainLabs/prysm/v6/beacon-chain/state/state-native/types"
"github.com/OffchainLabs/prysm/v6/beacon-chain/state/stateutil"
fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams"
@@ -43,11 +45,11 @@ const (
)
// SetGenesisTime for the beacon state.
func (b *BeaconState) SetGenesisTime(val uint64) error {
func (b *BeaconState) SetGenesisTime(val time.Time) error {
b.lock.Lock()
defer b.lock.Unlock()
b.genesisTime = val
b.genesisTime = uint64(val.Unix())
b.markFieldAsDirty(types.GenesisTime)
return nil
}

View File

@@ -25,7 +25,7 @@ func TestSortBatchDesc(t *testing.T) {
func TestWaitUntilReady(t *testing.T) {
b := batch{}.withState(batchErrRetryable)
require.Equal(t, time.Time{}, b.retryAfter)
require.Equal(t, time.Unix(), b.retryAfter)
var got time.Duration
wur := batchBlockUntil
var errDerp = errors.New("derp")

View File

@@ -28,7 +28,6 @@ import (
"github.com/OffchainLabs/prysm/v6/testing/assert"
"github.com/OffchainLabs/prysm/v6/testing/require"
"github.com/OffchainLabs/prysm/v6/testing/util"
prysmTime "github.com/OffchainLabs/prysm/v6/time"
"github.com/OffchainLabs/prysm/v6/time/slots"
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/libp2p/go-libp2p/core/network"
@@ -102,7 +101,9 @@ func initializeTestServices(t *testing.T, slots []primitives.Slot, peers []*peer
// makeGenesisTime where now is the current slot.
func makeGenesisTime(currentSlot primitives.Slot) time.Time {
return prysmTime.Now().Add(-1 * time.Second * time.Duration(currentSlot) * time.Duration(params.BeaconConfig().SecondsPerSlot))
now := time.Now()
s := slots.BeginsAt(currentSlot, now)
return now.Add(now.Sub(s))
}
// sanity test on helper function

View File

@@ -242,7 +242,7 @@ func TestService_waitForStateInitialization(t *testing.T) {
st, err := util.NewBeaconState()
require.NoError(t, err)
gt := time.Unix(int64(st.GenesisTime()), 0)
gt := st.GenesisTime()
s, gs := newService(ctx, &mock.ChainService{State: st, Genesis: gt, ValidatorsRoot: [32]byte{}})
expectedGenesisTime := gt
@@ -356,7 +356,8 @@ func TestService_Resync(t *testing.T) {
st, err := util.NewBeaconState()
require.NoError(t, err)
futureSlot := primitives.Slot(160)
require.NoError(t, st.SetGenesisTime(uint64(makeGenesisTime(futureSlot).Unix())))
genesis := makeGenesisTime(futureSlot)
require.NoError(t, st.SetGenesisTime(genesis))
return &mock.ChainService{
State: st,
Root: genesisRoot[:],
@@ -364,7 +365,7 @@ func TestService_Resync(t *testing.T) {
FinalizedCheckPoint: &eth.Checkpoint{
Epoch: slots.ToEpoch(futureSlot),
},
Genesis: time.Now(),
Genesis: genesis,
ValidatorsRoot: [32]byte{},
}
},
@@ -392,6 +393,7 @@ func TestService_Resync(t *testing.T) {
BlobStorage: filesystem.NewEphemeralBlobStorage(t),
})
assert.NotNil(t, s)
s.genesisTime = mc.Genesis
assert.Equal(t, primitives.Slot(0), s.cfg.Chain.HeadSlot())
err := s.Resync()
if tt.wantedErr != "" {

View File

@@ -104,7 +104,7 @@ func TestProcessPendingAtts_HasBlockSaveUnAggregatedAtt(t *testing.T) {
Aggregate: att,
}
require.NoError(t, beaconState.SetGenesisTime(uint64(time.Now().Unix())))
require.NoError(t, beaconState.SetGenesisTime(time.Now()))
chain := &mock.ChainService{Genesis: time.Now(),
State: beaconState,
@@ -200,7 +200,7 @@ func TestProcessPendingAtts_HasBlockSaveUnAggregatedAttElectra(t *testing.T) {
assert.NoError(t, err)
att.Signature = privKeys[committee[0]].Sign(hashTreeRoot[:]).Marshal()
require.NoError(t, beaconState.SetGenesisTime(uint64(time.Now().Unix())))
require.NoError(t, beaconState.SetGenesisTime(time.Now()))
chain := &mock.ChainService{Genesis: time.Now(),
State: beaconState,
@@ -323,7 +323,7 @@ func TestProcessPendingAtts_HasBlockSaveUnAggregatedAttElectra_VerifyAlreadySeen
att.SetSignature(privKeys[committee[0]].Sign(hashTreeRoot[:]).Marshal())
// Set the genesis time.
require.NoError(t, beaconState.SetGenesisTime(uint64(time.Now().Unix())))
require.NoError(t, beaconState.SetGenesisTime(time.Now()))
// Setup the chain service mock.
chain := &mock.ChainService{
@@ -505,7 +505,7 @@ func TestProcessPendingAtts_NoBroadcastWithBadSignature(t *testing.T) {
aggreSig, err := signing.ComputeDomainAndSign(s, 0, aggregateAndProof, params.BeaconConfig().DomainAggregateAndProof, privKeys[aggregatorIndex])
require.NoError(t, err)
require.NoError(t, s.SetGenesisTime(uint64(time.Now().Unix())))
require.NoError(t, s.SetGenesisTime(time.Now()))
ctx, cancel := context.WithCancel(t.Context())
chain2 := &mock.ChainService{Genesis: time.Now(),
State: s,
@@ -589,7 +589,7 @@ func TestProcessPendingAtts_HasBlockSaveAggregatedAtt(t *testing.T) {
aggreSig, err := signing.ComputeDomainAndSign(beaconState, 0, aggregateAndProof, params.BeaconConfig().DomainAggregateAndProof, privKeys[aggregatorIndex])
require.NoError(t, err)
require.NoError(t, beaconState.SetGenesisTime(uint64(time.Now().Unix())))
require.NoError(t, beaconState.SetGenesisTime(time.Now()))
chain := &mock.ChainService{Genesis: time.Now(),
DB: db,

View File

@@ -350,7 +350,7 @@ func (s *Service) startTasksPostInitialSync() {
select {
case <-s.initialSyncComplete:
// Compute the current epoch.
currentSlot := slots.CurrentSlot(uint64(s.cfg.clock.GenesisTime().Unix()))
currentSlot := slots.CurrentSlot(s.cfg.clock.GenesisTime())
currentEpoch := slots.ToEpoch(currentSlot)
// Compute the current fork forkDigest.

View File

@@ -67,7 +67,7 @@ func (s *Service) reconstructAndBroadcastBlobs(ctx context.Context, block interf
return
}
startTime, err := slots.ToTime(uint64(s.cfg.chain.GenesisTime().Unix()), block.Block().Slot())
startTime, err := slots.ToTime(s.cfg.chain.GenesisTime(), block.Block().Slot())
if err != nil {
log.WithError(err).Error("Failed to convert slot to time")
}

View File

@@ -276,7 +276,7 @@ func TestValidateAggregateAndProof_NotWithinSlotRange(t *testing.T) {
}
signedAggregateAndProof := &ethpb.SignedAggregateAttestationAndProof{Message: aggregateAndProof, Signature: make([]byte, fieldparams.BLSSignatureLength)}
require.NoError(t, beaconState.SetGenesisTime(uint64(time.Now().Unix())))
require.NoError(t, beaconState.SetGenesisTime(time.Now()))
r := &Service{
cfg: &config{
@@ -360,7 +360,7 @@ func TestValidateAggregateAndProof_ExistedInPool(t *testing.T) {
}
signedAggregateAndProof := &ethpb.SignedAggregateAttestationAndProof{Message: aggregateAndProof, Signature: make([]byte, fieldparams.BLSSignatureLength)}
require.NoError(t, beaconState.SetGenesisTime(uint64(time.Now().Unix())))
require.NoError(t, beaconState.SetGenesisTime(time.Now()))
r := &Service{
cfg: &config{
attPool: attestations.NewPool(),
@@ -450,7 +450,7 @@ func TestValidateAggregateAndProof_CanValidate(t *testing.T) {
signedAggregateAndProof.Signature, err = signing.ComputeDomainAndSign(beaconState, 0, signedAggregateAndProof.Message, params.BeaconConfig().DomainAggregateAndProof, privKeys[ai])
require.NoError(t, err)
require.NoError(t, beaconState.SetGenesisTime(uint64(time.Now().Unix())))
require.NoError(t, beaconState.SetGenesisTime(time.Now()))
ctx, cancel := context.WithCancel(t.Context())
defer cancel()
chain := &mock.ChainService{Genesis: time.Now().Add(-oneEpoch()),
@@ -552,7 +552,7 @@ func TestVerifyIndexInCommittee_SeenAggregatorEpoch(t *testing.T) {
signedAggregateAndProof := &ethpb.SignedAggregateAttestationAndProof{Message: aggregateAndProof}
signedAggregateAndProof.Signature, err = signing.ComputeDomainAndSign(beaconState, 0, signedAggregateAndProof.Message, params.BeaconConfig().DomainAggregateAndProof, privKeys[ai])
require.NoError(t, err)
require.NoError(t, beaconState.SetGenesisTime(uint64(time.Now().Unix())))
require.NoError(t, beaconState.SetGenesisTime(time.Now()))
ctx, cancel := context.WithCancel(t.Context())
defer cancel()
@@ -674,7 +674,7 @@ func TestValidateAggregateAndProof_BadBlock(t *testing.T) {
signedAggregateAndProof.Signature, err = signing.ComputeDomainAndSign(beaconState, 0, signedAggregateAndProof.Message, params.BeaconConfig().DomainAggregateAndProof, privKeys[ai])
require.NoError(t, err)
require.NoError(t, beaconState.SetGenesisTime(uint64(time.Now().Unix())))
require.NoError(t, beaconState.SetGenesisTime(time.Now()))
r := &Service{
cfg: &config{
p2p: p,
@@ -764,7 +764,7 @@ func TestValidateAggregateAndProof_RejectWhenAttEpochDoesntEqualTargetEpoch(t *t
signedAggregateAndProof.Signature, err = signing.ComputeDomainAndSign(beaconState, 0, signedAggregateAndProof.Message, params.BeaconConfig().DomainAggregateAndProof, privKeys[ai])
require.NoError(t, err)
require.NoError(t, beaconState.SetGenesisTime(uint64(time.Now().Unix())))
require.NoError(t, beaconState.SetGenesisTime(time.Now()))
r := &Service{
cfg: &config{
p2p: p,

View File

@@ -150,7 +150,7 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms
// Be lenient in handling early blocks. Instead of discarding blocks arriving later than
// MAXIMUM_GOSSIP_CLOCK_DISPARITY in future, we tolerate blocks arriving at max two slots
// earlier (SECONDS_PER_SLOT * 2 seconds). Queue such blocks and process them at the right slot.
genesisTime := uint64(s.cfg.clock.GenesisTime().Unix())
genesisTime := s.cfg.clock.GenesisTime()
if err := slots.VerifyTime(genesisTime, blk.Block().Slot(), earlyBlockProcessingTolerance); err != nil {
log.WithError(err).WithFields(getBlockFields(blk)).Debug("Ignored block: could not verify slot time")
return pubsub.ValidationIgnore, nil
@@ -443,8 +443,8 @@ func (s *Service) setBadBlock(ctx context.Context, root [32]byte) {
}
// This captures metrics for block arrival time by subtracts slot start time.
func captureArrivalTimeMetric(genesisTime uint64, currentSlot primitives.Slot) error {
startTime, err := slots.ToTime(genesisTime, currentSlot)
func captureArrivalTimeMetric(genesis time.Time, currentSlot primitives.Slot) error {
startTime, err := slots.ToTime(genesis, currentSlot)
if err != nil {
return err
}
@@ -459,7 +459,7 @@ func captureArrivalTimeMetric(genesisTime uint64, currentSlot primitives.Slot) e
// current_time + MAXIMUM_GOSSIP_CLOCK_DISPARITY. in short, this function
// returns true if the corresponding block should be queued and false if
// the block should be processed immediately.
func isBlockQueueable(genesisTime uint64, slot primitives.Slot, receivedTime time.Time) bool {
func isBlockQueueable(genesisTime time.Time, slot primitives.Slot, receivedTime time.Time) bool {
slotTime, err := slots.ToTime(genesisTime, slot)
if err != nil {
return false

View File

@@ -1172,7 +1172,7 @@ func TestService_setBadBlock_DoesntSetWithContextErr(t *testing.T) {
func TestService_isBlockQueueable(t *testing.T) {
currentTime := time.Now().Round(time.Second)
genesisTime := uint64(currentTime.Unix() - int64(params.BeaconConfig().SecondsPerSlot))
genesisTime := currentTime.Add(-1 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
blockSlot := primitives.Slot(1)
// slot time within MAXIMUM_GOSSIP_CLOCK_DISPARITY, so don't queue the block.
@@ -1195,8 +1195,8 @@ func TestValidateBeaconBlockPubSub_ValidExecutionPayload(t *testing.T) {
util.SaveBlock(t, ctx, db, parentBlock)
bRoot, err := parentBlock.Block.HashTreeRoot()
require.NoError(t, err)
presentTime := time.Now().Unix()
require.NoError(t, beaconState.SetGenesisTime(uint64(presentTime)))
now := time.Now()
require.NoError(t, beaconState.SetGenesisTime(now))
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
require.NoError(t, db.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
copied := beaconState.Copy()
@@ -1208,7 +1208,7 @@ func TestValidateBeaconBlockPubSub_ValidExecutionPayload(t *testing.T) {
msg.Block.ParentRoot = bRoot[:]
msg.Block.Slot = 1
msg.Block.ProposerIndex = proposerIdx
msg.Block.Body.ExecutionPayload.Timestamp = uint64(presentTime) + params.BeaconConfig().SecondsPerSlot
msg.Block.Body.ExecutionPayload.Timestamp = uint64(now.Unix()) + params.BeaconConfig().SecondsPerSlot
msg.Block.Body.ExecutionPayload.GasUsed = 10
msg.Block.Body.ExecutionPayload.GasLimit = 11
msg.Block.Body.ExecutionPayload.BlockHash = bytesutil.PadTo([]byte("blockHash"), 32)
@@ -1218,7 +1218,7 @@ func TestValidateBeaconBlockPubSub_ValidExecutionPayload(t *testing.T) {
require.NoError(t, err)
stateGen := stategen.New(db, doublylinkedtree.New())
chainService := &mock.ChainService{Genesis: time.Unix(presentTime-int64(params.BeaconConfig().SecondsPerSlot), 0),
chainService := &mock.ChainService{Genesis: now.Add(-1 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
DB: db,
FinalizedCheckPoint: &ethpb.Checkpoint{
Epoch: 0,
@@ -1383,7 +1383,7 @@ func Test_validateBellatrixBeaconBlockParentValidation(t *testing.T) {
msg.Block.ParentRoot = bRoot[:]
msg.Block.Slot = 1
msg.Block.ProposerIndex = proposerIdx
msg.Block.Body.ExecutionPayload.Timestamp = beaconState.GenesisTime() + params.BeaconConfig().SecondsPerSlot
msg.Block.Body.ExecutionPayload.Timestamp = uint64(beaconState.GenesisTime().Add(time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix())
msg.Block.Body.ExecutionPayload.GasUsed = 10
msg.Block.Body.ExecutionPayload.GasLimit = 11
msg.Block.Body.ExecutionPayload.BlockHash = bytesutil.PadTo([]byte("blockHash"), 32)
@@ -1395,7 +1395,7 @@ func Test_validateBellatrixBeaconBlockParentValidation(t *testing.T) {
blk, err := blocks.NewSignedBeaconBlock(msg)
require.NoError(t, err)
chainService := &mock.ChainService{Genesis: time.Unix(int64(beaconState.GenesisTime()), 0),
chainService := &mock.ChainService{Genesis: beaconState.GenesisTime(),
OptimisticRoots: make(map[[32]byte]bool),
FinalizedCheckPoint: &ethpb.Checkpoint{
Epoch: 0,
@@ -1440,7 +1440,7 @@ func Test_validateBeaconBlockProcessingWhenParentIsOptimistic(t *testing.T) {
msg.Block.ParentRoot = bRoot[:]
msg.Block.Slot = 1
msg.Block.ProposerIndex = proposerIdx
msg.Block.Body.ExecutionPayload.Timestamp = beaconState.GenesisTime() + params.BeaconConfig().SecondsPerSlot
msg.Block.Body.ExecutionPayload.Timestamp = uint64(beaconState.GenesisTime().Add(time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix())
msg.Block.Body.ExecutionPayload.GasUsed = 10
msg.Block.Body.ExecutionPayload.GasLimit = 11
msg.Block.Body.ExecutionPayload.BlockHash = bytesutil.PadTo([]byte("blockHash"), 32)
@@ -1449,7 +1449,7 @@ func Test_validateBeaconBlockProcessingWhenParentIsOptimistic(t *testing.T) {
msg.Signature, err = signing.ComputeDomainAndSign(beaconState, 0, msg.Block, params.BeaconConfig().DomainBeaconProposer, privKeys[proposerIdx])
require.NoError(t, err)
chainService := &mock.ChainService{Genesis: time.Unix(int64(beaconState.GenesisTime()), 0),
chainService := &mock.ChainService{Genesis: beaconState.GenesisTime(),
DB: db,
Optimistic: true,
FinalizedCheckPoint: &ethpb.Checkpoint{

View File

@@ -68,7 +68,7 @@ func (s *Service) validateBlob(ctx context.Context, pid peer.ID, msg *pubsub.Mes
return pubsub.ValidationIgnore, err
}
startTime, err := slots.ToTime(uint64(s.cfg.chain.GenesisTime().Unix()), blob.Slot())
startTime, err := slots.ToTime(s.cfg.chain.GenesisTime(), blob.Slot())
if err != nil {
return pubsub.ValidationIgnore, err
}

View File

@@ -180,7 +180,7 @@ func (s *Service) validateDataColumn(ctx context.Context, pid peer.ID, msg *pubs
dataColumnSidecarVerificationSuccessesCounter.Inc()
// Get the time at slot start.
startTime, err := slots.ToTime(uint64(s.cfg.chain.GenesisTime().Unix()), roDataColumn.SignedBlockHeader.Header.Slot)
startTime, err := slots.ToTime(s.cfg.chain.GenesisTime(), roDataColumn.SignedBlockHeader.Header.Slot)
if err != nil {
return pubsub.ValidationIgnore, err
}

View File

@@ -51,7 +51,7 @@ func (s *Service) validateLightClientOptimisticUpdate(ctx context.Context, pid p
// to propagate through the network -- i.e. validate that one-third of optimistic_update.signature_slot
// has transpired (SECONDS_PER_SLOT / INTERVALS_PER_SLOT seconds after the start of the slot,
// with a MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance)
earliestValidTime := slots.StartTime(uint64(s.cfg.clock.GenesisTime().Unix()), newUpdate.SignatureSlot()).
earliestValidTime := slots.StartTime(s.cfg.clock.GenesisTime(), newUpdate.SignatureSlot()).
Add(time.Second * time.Duration(params.BeaconConfig().SecondsPerSlot/params.BeaconConfig().IntervalsPerSlot)).
Add(-params.BeaconConfig().MaximumGossipClockDisparityDuration())
if s.cfg.clock.Now().Before(earliestValidTime) {
@@ -116,7 +116,7 @@ func (s *Service) validateLightClientFinalityUpdate(ctx context.Context, pid pee
// to propagate through the network -- i.e. validate that one-third of optimistic_update.signature_slot
// has transpired (SECONDS_PER_SLOT / INTERVALS_PER_SLOT seconds after the start of the slot,
// with a MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance)
earliestValidTime := slots.StartTime(uint64(s.cfg.clock.GenesisTime().Unix()), newUpdate.SignatureSlot()).
earliestValidTime := slots.StartTime(s.cfg.clock.GenesisTime(), newUpdate.SignatureSlot()).
Add(time.Second * time.Duration(params.BeaconConfig().SecondsPerSlot/params.BeaconConfig().IntervalsPerSlot)).
Add(-params.BeaconConfig().MaximumGossipClockDisparityDuration())
if s.cfg.clock.Now().Before(earliestValidTime) {

View File

@@ -260,9 +260,10 @@ func generateGenesis(ctx context.Context) (state.BeaconState, error) {
}
// set timestamps for genesis and shanghai fork
gen.Timestamp = f.GenesisTime
gen.Config.ShanghaiTime = interop.GethShanghaiTime(f.GenesisTime, params.BeaconConfig())
gen.Config.CancunTime = interop.GethCancunTime(f.GenesisTime, params.BeaconConfig())
gen.Config.PragueTime = interop.GethPragueTime(f.GenesisTime, params.BeaconConfig())
genesis := time.Unix(int64(f.GenesisTime), 0)
gen.Config.ShanghaiTime = interop.GethShanghaiTime(genesis, params.BeaconConfig())
gen.Config.CancunTime = interop.GethCancunTime(genesis, params.BeaconConfig())
gen.Config.PragueTime = interop.GethPragueTime(genesis, params.BeaconConfig())
fields := logrus.Fields{}
if gen.Config.ShanghaiTime != nil {
@@ -280,7 +281,7 @@ func generateGenesis(ctx context.Context) (state.BeaconState, error) {
gen.Config.TerminalTotalDifficulty = big.NewInt(0)
}
} else {
gen = interop.GethTestnetGenesis(f.GenesisTime, params.BeaconConfig())
gen = interop.GethTestnetGenesis(time.Unix(int64(f.GenesisTime), 0), params.BeaconConfig())
}
if f.GethGenesisJsonOut != "" {
@@ -296,7 +297,7 @@ func generateGenesis(ctx context.Context) (state.BeaconState, error) {
gb := gen.ToBlock()
// TODO: expose the PregenesisCreds option with a cli flag - for now defaulting to no withdrawal credentials at genesis
genesisState, err := interop.NewPreminedGenesis(ctx, f.GenesisTime, nv, 0, v, gb, opts...)
genesisState, err := interop.NewPreminedGenesis(ctx, time.Unix(int64(f.GenesisTime), 0), nv, 0, v, gb, opts...)
if err != nil {
return nil, err
}

View File

@@ -1,6 +1,8 @@
package forkchoice
import (
"time"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
eth "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
)
@@ -47,7 +49,7 @@ type Node struct {
UnrealizedFinalizedEpoch primitives.Epoch
Balance uint64
Weight uint64
Timestamp uint64
Timestamp time.Time
BlockRoot []byte
ParentRoot []byte
ExecutionBlockHash []byte

View File

@@ -2,6 +2,7 @@ package interop_test
import (
"testing"
"time"
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/transition"
"github.com/OffchainLabs/prysm/v6/config/params"
@@ -31,5 +32,5 @@ func TestGenerateGenesisState(t *testing.T) {
require.NoError(t, err)
want := int(numValidators)
assert.Equal(t, want, genesisState.NumValidators())
assert.Equal(t, uint64(0), genesisState.GenesisTime())
assert.Equal(t, time.Unix(0, 0), genesisState.GenesisTime())
}

View File

@@ -3,6 +3,7 @@ package interop
import (
"math"
"math/big"
"time"
clparams "github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/time/slots"
@@ -69,7 +70,7 @@ var minerBalance = big.NewInt(0)
// GethShanghaiTime calculates the absolute time of the shanghai (aka capella) fork block
// by adding the relative time of the capella the fork epoch to the given genesis timestamp.
func GethShanghaiTime(genesisTime uint64, cfg *clparams.BeaconChainConfig) *uint64 {
func GethShanghaiTime(genesisTime time.Time, cfg *clparams.BeaconChainConfig) *uint64 {
var shanghaiTime *uint64
if cfg.CapellaForkEpoch != math.MaxUint64 {
startSlot, err := slots.EpochStart(cfg.CapellaForkEpoch)
@@ -84,7 +85,7 @@ func GethShanghaiTime(genesisTime uint64, cfg *clparams.BeaconChainConfig) *uint
// GethCancunTime calculates the absolute time of the cancun (aka deneb) fork block
// by adding the relative time of the capella the fork epoch to the given genesis timestamp.
func GethCancunTime(genesisTime uint64, cfg *clparams.BeaconChainConfig) *uint64 {
func GethCancunTime(genesisTime time.Time, cfg *clparams.BeaconChainConfig) *uint64 {
var cancunTime *uint64
if cfg.DenebForkEpoch != math.MaxUint64 {
startSlot, err := slots.EpochStart(cfg.DenebForkEpoch)
@@ -99,7 +100,7 @@ func GethCancunTime(genesisTime uint64, cfg *clparams.BeaconChainConfig) *uint64
// GethPragueTime calculates the absolute time of the prague (aka electra) fork block
// by adding the relative time of the capella the fork epoch to the given genesis timestamp.
func GethPragueTime(genesisTime uint64, cfg *clparams.BeaconChainConfig) *uint64 {
func GethPragueTime(genesisTime time.Time, cfg *clparams.BeaconChainConfig) *uint64 {
var pragueTime *uint64
if cfg.ElectraForkEpoch != math.MaxUint64 {
startSlot, err := slots.EpochStart(cfg.ElectraForkEpoch)
@@ -115,16 +116,17 @@ func GethPragueTime(genesisTime uint64, cfg *clparams.BeaconChainConfig) *uint64
// GethTestnetGenesis creates a genesis.json for eth1 clients with a set of defaults suitable for ephemeral testnets,
// like in an e2e test. The parameters are minimal but the full value is returned unmarshaled so that it can be
// customized as desired.
func GethTestnetGenesis(genesisTime uint64, cfg *clparams.BeaconChainConfig) *core.Genesis {
shanghaiTime := GethShanghaiTime(genesisTime, cfg)
func GethTestnetGenesis(genesis time.Time, cfg *clparams.BeaconChainConfig) *core.Genesis {
genesisTime := uint64(genesis.Unix())
shanghaiTime := GethShanghaiTime(genesis, cfg)
if cfg.CapellaForkEpoch == 0 {
shanghaiTime = &genesisTime
}
cancunTime := GethCancunTime(genesisTime, cfg)
cancunTime := GethCancunTime(genesis, cfg)
if cfg.DenebForkEpoch == 0 {
cancunTime = &genesisTime
}
pragueTime := GethPragueTime(genesisTime, cfg)
pragueTime := GethPragueTime(genesis, cfg)
if cfg.ElectraForkEpoch == 0 {
pragueTime = &genesisTime
}

View File

@@ -2,6 +2,7 @@ package interop
import (
"context"
"time"
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/altair"
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers"
@@ -24,7 +25,7 @@ import (
var errUnsupportedVersion = errors.New("schema version not supported by PremineGenesisConfig")
type PremineGenesisConfig struct {
GenesisTime uint64
GenesisTime time.Time
NVals uint64
PregenesisCreds uint64
Version int // as in "github.com/OffchainLabs/prysm/v6/runtime/version"
@@ -49,9 +50,9 @@ func WithDepositData(dds []*ethpb.Deposit_Data, roots [][]byte) PremineGenesisOp
}
// NewPreminedGenesis creates a genesis BeaconState at the given fork version, suitable for using as an e2e genesis.
func NewPreminedGenesis(ctx context.Context, t, nvals, pCreds uint64, version int, gb *types.Block, opts ...PremineGenesisOpt) (state.BeaconState, error) {
func NewPreminedGenesis(ctx context.Context, genesis time.Time, nvals, pCreds uint64, version int, gb *types.Block, opts ...PremineGenesisOpt) (state.BeaconState, error) {
cfg := &PremineGenesisConfig{
GenesisTime: t,
GenesisTime: genesis,
NVals: nvals,
PregenesisCreds: pCreds,
Version: version,

View File

@@ -3,10 +3,10 @@ package interop
import (
"math/big"
"testing"
"time"
"github.com/OffchainLabs/prysm/v6/runtime/version"
"github.com/OffchainLabs/prysm/v6/testing/require"
"github.com/OffchainLabs/prysm/v6/time"
"github.com/ethereum/go-ethereum/core/types"
)
@@ -20,6 +20,6 @@ func TestPremineGenesis_Electra(t *testing.T) {
ExcessBlobGas: &one,
BlobGasUsed: &one,
})
_, err := NewPreminedGenesis(t.Context(), genesis.Time(), 10, 10, version.Electra, genesis)
_, err := NewPreminedGenesis(t.Context(), time.Unix(int64(genesis.Time()), 0), 10, 10, version.Electra, genesis)
require.NoError(t, err)
}

View File

@@ -89,7 +89,7 @@ func (m *Miner) initAttempt(ctx context.Context, attempt int) (*os.File, error)
gethJsonPath := path.Join(path.Dir(binaryPath), "genesis.json")
gen := interop.GethTestnetGenesis(e2e.TestParams.Eth1GenesisTime, params.BeaconConfig())
log.Infof("eth1 miner genesis timestamp=%d", e2e.TestParams.Eth1GenesisTime)
log.Infof("eth1 miner genesis timestamp=%s", e2e.TestParams.Eth1GenesisTime)
b, err := json.Marshal(gen)
if err != nil {
return nil, err

View File

@@ -35,7 +35,7 @@ func builderActive(_ *e2etypes.EvaluationContext, conns ...*grpc.ClientConn) err
if err != nil {
return errors.Wrap(err, "failed to get genesis data")
}
currSlot := slots.CurrentSlot(uint64(genesis.GenesisTime.AsTime().Unix()))
currSlot := slots.CurrentSlot(genesis.GenesisTime.AsTime())
currEpoch := slots.ToEpoch(currSlot)
lowestBound := primitives.Epoch(0)
if currEpoch >= 1 {

View File

@@ -231,7 +231,7 @@ func validatorsSyncParticipation(_ *types.EvaluationContext, conns ...*grpc.Clie
if err != nil {
return errors.Wrap(err, "failed to get genesis data")
}
currSlot := slots.CurrentSlot(uint64(genesis.GenesisTime.AsTime().Unix()))
currSlot := slots.CurrentSlot(genesis.GenesisTime.AsTime())
currEpoch := slots.ToEpoch(currSlot)
lowestBound := primitives.Epoch(0)
if currEpoch >= 1 {

View File

@@ -30,8 +30,8 @@ type params struct {
Paths *paths
Eth1GenesisBlock *types.Block
StartTime time.Time
CLGenesisTime uint64
Eth1GenesisTime uint64
CLGenesisTime time.Time
Eth1GenesisTime time.Time
NumberOfExecutionCreds uint64
}
@@ -156,7 +156,7 @@ const (
jaegerTracingPort = 9150
startupBufferSecs = 15
startupBuffer = 15 * time.Second
)
func logDir() string {
@@ -206,7 +206,7 @@ func Init(t *testing.T, beaconNodeCount int) error {
return err
}
genTime := uint64(time.Now().Unix()) + startupBufferSecs
genTime := time.Now().Add(startupBuffer)
TestParams = &params{
TestPath: filepath.Join(testPath, fmt.Sprintf("shard-%d", testShardIndex)),
LogPath: logPath,
@@ -259,7 +259,7 @@ func InitMultiClient(t *testing.T, beaconNodeCount int, lighthouseNodeCount int)
return err
}
genTime := uint64(time.Now().Unix()) + startupBufferSecs
genTime := time.Now().Add(startupBuffer)
TestParams = &params{
TestPath: filepath.Join(testPath, fmt.Sprintf("shard-%d", testShardIndex)),
LogPath: logPath,

View File

@@ -56,11 +56,11 @@ func (bb *Builder) Tick(t testing.TB, tick int64) {
currentSlot := uint64(tick) / params.BeaconConfig().SecondsPerSlot
for lastSlot < currentSlot {
lastSlot++
bb.service.SetForkChoiceGenesisTime(uint64(time.Now().Unix() - int64(params.BeaconConfig().SecondsPerSlot*lastSlot)))
require.NoError(t, bb.service.NewSlot(context.TODO(), primitives.Slot(lastSlot)))
bb.service.SetForkChoiceGenesisTime(time.Now().Add(-1 * time.Duration(params.BeaconConfig().SecondsPerSlot*lastSlot) * time.Second))
require.NoError(t, bb.service.NewSlot(t.Context(), primitives.Slot(lastSlot)))
}
if tick > int64(params.BeaconConfig().SecondsPerSlot*lastSlot) {
bb.service.SetForkChoiceGenesisTime(uint64(time.Now().Unix() - tick))
bb.service.SetForkChoiceGenesisTime(time.Now().Add(-1 * time.Duration(tick) * time.Second))
}
bb.lastTick = tick
}
@@ -135,7 +135,7 @@ func (bb *Builder) Check(t testing.TB, c *Check) {
if c == nil {
return
}
ctx := context.TODO()
ctx := t.Context()
require.NoError(t, bb.service.UpdateAndSaveHeadWithBalances(ctx))
if c.Head != nil {
r, err := bb.service.HeadRoot(ctx)

View File

@@ -60,7 +60,10 @@ func startChainService(t testing.TB,
depositCache, err := depositsnapshot.New()
require.NoError(t, err)
genesis := st.GenesisTime()
fc := doublylinkedtree.New()
fc.SetGenesisTime(genesis)
sg := stategen.New(db, fc)
opts := append([]blockchain.Option{},
blockchain.WithExecutionEngineCaller(engineMock),
@@ -78,8 +81,9 @@ func startChainService(t testing.TB,
blockchain.WithBlobStorage(filesystem.NewEphemeralBlobStorage(t)),
blockchain.WithDataColumnStorage(filesystem.NewEphemeralDataColumnStorage(t)),
blockchain.WithSyncChecker(mock.MockChecker{}),
blockchain.WithGenesisTime(genesis),
)
service, err := blockchain.NewService(context.Background(), opts...)
service, err := blockchain.NewService(t.Context(), opts...)
require.NoError(t, err)
// force start kzg context here until Deneb fork epoch is decided
require.NoError(t, kzg.Start())

View File

@@ -3,6 +3,7 @@ package util
import (
"context"
"testing"
"time"
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers"
"github.com/OffchainLabs/prysm/v6/beacon-chain/state"
@@ -27,7 +28,7 @@ func DeterministicGenesisStateBellatrix(t testing.TB, numValidators uint64) (sta
if err != nil {
t.Fatal(errors.Wrapf(err, "failed to get eth1data for %d deposits", numValidators))
}
beaconState, err := genesisBeaconStateBellatrix(context.Background(), deposits, uint64(0), eth1Data)
beaconState, err := genesisBeaconStateBellatrix(context.Background(), deposits, time.Unix(0, 0), eth1Data)
if err != nil {
t.Fatal(errors.Wrapf(err, "failed to get genesis beacon state of %d validators", numValidators))
}
@@ -36,7 +37,7 @@ func DeterministicGenesisStateBellatrix(t testing.TB, numValidators uint64) (sta
}
// genesisBeaconStateBellatrix returns the genesis beacon state.
func genesisBeaconStateBellatrix(ctx context.Context, deposits []*ethpb.Deposit, genesisTime uint64, eth1Data *ethpb.Eth1Data) (state.BeaconState, error) {
func genesisBeaconStateBellatrix(ctx context.Context, deposits []*ethpb.Deposit, genesisTime time.Time, eth1Data *ethpb.Eth1Data) (state.BeaconState, error) {
st, err := emptyGenesisStateBellatrix()
if err != nil {
return nil, err
@@ -86,7 +87,7 @@ func emptyGenesisStateBellatrix() (state.BeaconState, error) {
return state_native.InitializeFromProtoBellatrix(st)
}
func buildGenesisBeaconStateBellatrix(genesisTime uint64, preState state.BeaconState, eth1Data *ethpb.Eth1Data) (state.BeaconState, error) {
func buildGenesisBeaconStateBellatrix(genesisTime time.Time, preState state.BeaconState, eth1Data *ethpb.Eth1Data) (state.BeaconState, error) {
if eth1Data == nil {
return nil, errors.New("no eth1data provided for genesis state")
}
@@ -143,7 +144,7 @@ func buildGenesisBeaconStateBellatrix(genesisTime uint64, preState state.BeaconS
st := &ethpb.BeaconStateBellatrix{
// Misc fields.
Slot: 0,
GenesisTime: genesisTime,
GenesisTime: uint64(genesisTime.Unix()),
GenesisValidatorsRoot: genesisValidatorsRoot[:],
Fork: &ethpb.Fork{

View File

@@ -2,6 +2,7 @@ package util
import (
"testing"
"time"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/testing/require"
@@ -19,9 +20,9 @@ func TestGenesisBeaconStateBellatrix(t *testing.T) {
require.NoError(t, err)
eth1Data, err := DeterministicEth1Data(len(deposits))
require.NoError(t, err)
gt := uint64(10000)
gt := time.Now()
st, err := genesisBeaconStateBellatrix(ctx, deposits, gt, eth1Data)
require.NoError(t, err)
require.Equal(t, gt, st.GenesisTime())
require.Equal(t, gt.Truncate(time.Second), st.GenesisTime()) // Beacon state only keeps time precision of 1s, so we truncate.
require.Equal(t, params.BeaconConfig().MaxCommitteesPerSlot, uint64(st.NumValidators()))
}

View File

@@ -1,7 +1,6 @@
package util
import (
"context"
"sync"
"testing"
@@ -264,7 +263,7 @@ func DeterministicGenesisState(t testing.TB, numValidators uint64) (state.Beacon
if err != nil {
t.Fatal(errors.Wrapf(err, "failed to get eth1data for %d deposits", numValidators))
}
beaconState, err := transition.GenesisBeaconState(context.Background(), deposits, uint64(0), eth1Data)
beaconState, err := transition.GenesisBeaconState(t.Context(), deposits, uint64(0), eth1Data)
if err != nil {
t.Fatal(errors.Wrapf(err, "failed to get genesis beacon state of %d validators", numValidators))
}

View File

@@ -26,18 +26,15 @@ func startFromTime(genesis time.Time, slot primitives.Slot) time.Time {
// StartTime returns the start time in terms of its unix epoch
// value.
func StartTime(genesis uint64, slot primitives.Slot) time.Time {
genesisTime := time.Unix(int64(genesis), 0) // lint:ignore uintcast -- Genesis timestamp will not exceed int64 in your lifetime.
return startFromTime(genesisTime, slot)
func StartTime(genesis time.Time, slot primitives.Slot) time.Time {
return startFromTime(genesis, slot)
}
// SinceGenesis returns the number of slots since
// the provided genesis time.
func SinceGenesis(genesis time.Time) primitives.Slot {
if genesis.After(prysmTime.Now()) { // Genesis has not occurred yet.
return 0
}
return primitives.Slot(uint64(prysmTime.Since(genesis).Seconds()) / params.BeaconConfig().SecondsPerSlot)
// TODO(preston): Remove this.
return CurrentSlot(genesis)
}
// EpochsSinceGenesis returns the number of epochs since
@@ -162,15 +159,12 @@ func SinceEpochStarts(slot primitives.Slot) primitives.Slot {
}
// VerifyTime validates the input slot is not from the future.
func VerifyTime(genesisTime uint64, slot primitives.Slot, timeTolerance time.Duration) error {
slotTime, err := ToTime(genesisTime, slot)
if err != nil {
return err
}
func VerifyTime(genesis time.Time, slot primitives.Slot, timeTolerance time.Duration) error {
slotTime := BeginsAt(slot, genesis)
// Defensive check to ensure unreasonable slots are rejected
// straight away.
if err := ValidateClock(slot, genesisTime); err != nil {
if err := ValidateClock(slot, genesis); err != nil {
return err
}
@@ -184,37 +178,41 @@ func VerifyTime(genesisTime uint64, slot primitives.Slot, timeTolerance time.Dur
}
// ToTime takes the given slot and genesis time to determine the start time of the slot.
func ToTime(genesisTimeSec uint64, slot primitives.Slot) (time.Time, error) {
timeSinceGenesis, err := slot.SafeMul(params.BeaconConfig().SecondsPerSlot)
// DEPRECATED: Use BeginsAt.
func ToTime(genesis time.Time, slot primitives.Slot) (time.Time, error) {
// TODO(Preston): How important is this overflow check?
_, err := slot.SafeMul(params.BeaconConfig().SecondsPerSlot)
if err != nil {
return time.Unix(0, 0), fmt.Errorf("slot (%d) is in the far distant future: %w", slot, err)
}
sTime, err := timeSinceGenesis.SafeAdd(genesisTimeSec)
if err != nil {
return time.Unix(0, 0), fmt.Errorf("slot (%d) is in the far distant future: %w", slot, err)
}
return time.Unix(int64(sTime), 0), nil // lint:ignore uintcast -- A timestamp will not exceed int64 in your lifetime.
return BeginsAt(slot, genesis), nil
}
// BeginsAt computes the timestamp where the given slot begins, relative to the genesis timestamp.
// TODO(preston): WTF is this? Looks like a copy of ToTime, but no validation.
func BeginsAt(slot primitives.Slot, genesis time.Time) time.Time {
sd := time.Second * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Duration(slot)
return genesis.Add(sd)
}
// Since computes the number of time slots that have occurred since the given timestamp.
// TODO(Preston): Delete this method?
func Since(time time.Time) primitives.Slot {
return CurrentSlot(uint64(time.Unix()))
return CurrentSlot(time)
}
// CurrentSlot returns the current slot as determined by the local clock and
// provided genesis time.
func CurrentSlot(genesisTimeSec uint64) primitives.Slot {
now := uint64(prysmTime.Now().Unix())
if now < genesisTimeSec {
func CurrentSlot(genesis time.Time) primitives.Slot {
return SlotAt(genesis, time.Now())
}
// SlotAt returns the slot at the given time.
func SlotAt(genesis, tm time.Time) primitives.Slot {
if tm.Before(genesis) {
return 0
}
return primitives.Slot((now - genesisTimeSec) / params.BeaconConfig().SecondsPerSlot)
return primitives.Slot(tm.Sub(genesis) / time.Second / time.Duration(params.BeaconConfig().SecondsPerSlot))
}
// Duration computes the span of time between two instants, represented as Slots.
@@ -228,8 +226,8 @@ func Duration(start, end time.Time) primitives.Slot {
// ValidateClock validates a provided slot against the local
// clock to ensure slots that are unreasonable are returned with
// an error.
func ValidateClock(slot primitives.Slot, genesisTimeSec uint64) error {
maxPossibleSlot := CurrentSlot(genesisTimeSec).Add(MaxSlotBuffer)
func ValidateClock(slot primitives.Slot, genesis time.Time) error {
maxPossibleSlot := CurrentSlot(genesis).Add(MaxSlotBuffer)
// Defensive check to ensure that we only process slots up to a hard limit
// from our local clock.
if slot > maxPossibleSlot {
@@ -283,27 +281,28 @@ func SyncCommitteePeriodStartEpoch(e primitives.Epoch) (primitives.Epoch, error)
return primitives.Epoch(startEpoch), nil
}
// SecondsSinceSlotStart returns the number of seconds elapsed since the
// given slot start time
func SecondsSinceSlotStart(s primitives.Slot, genesisTime, timeStamp uint64) (uint64, error) {
limit := genesisTime + uint64(s)*params.BeaconConfig().SecondsPerSlot
if timeStamp < limit {
return 0, fmt.Errorf("could not compute seconds since slot %d start: invalid timestamp, got %d < want %d", s, timeStamp, limit)
// SinceSlotStart returns the amount of time elapsed since the
// given slot start time. This method returns an error if the timestamp happens
// before the given slot start time.
func SinceSlotStart(s primitives.Slot, genesis time.Time, timestamp time.Time) (time.Duration, error) {
limit := genesis.Add(time.Duration(uint64(s)*params.BeaconConfig().SecondsPerSlot) * time.Second)
if timestamp.Before(limit) {
return 0, fmt.Errorf("could not compute seconds since slot %d start: invalid timestamp, got %s < want %s", s, timestamp, limit)
}
return timeStamp - genesisTime - uint64(s)*params.BeaconConfig().SecondsPerSlot, nil
return timestamp.Sub(limit), nil
}
// TimeIntoSlot returns the time duration elapsed between the current time and
// the start of the current slot
func TimeIntoSlot(genesisTime uint64) time.Duration {
return time.Since(StartTime(genesisTime, CurrentSlot(genesisTime)))
func TimeIntoSlot(genesis time.Time) time.Duration {
return time.Since(BeginsAt(CurrentSlot(genesis), genesis))
}
// WithinVotingWindow returns whether the current time is within the voting window
// (eg. 4 seconds on mainnet) of the current slot.
func WithinVotingWindow(genesisTime uint64, slot primitives.Slot) bool {
func WithinVotingWindow(genesis time.Time, slot primitives.Slot) bool {
votingWindow := params.BeaconConfig().SecondsPerSlot / params.BeaconConfig().IntervalsPerSlot
return time.Since(StartTime(genesisTime, slot)) < time.Duration(votingWindow)*time.Second
return time.Since(StartTime(genesis, slot)) < time.Duration(votingWindow)*time.Second
}
// MaxSafeEpoch gives the largest epoch value that can be safely converted to a slot.
@@ -312,13 +311,13 @@ func MaxSafeEpoch() primitives.Epoch {
}
// SecondsUntilNextEpochStart returns how many seconds until the next Epoch start from the current time and slot
func SecondsUntilNextEpochStart(genesisTimeSec uint64) (uint64, error) {
currentSlot := CurrentSlot(genesisTimeSec)
func SecondsUntilNextEpochStart(genesis time.Time) (uint64, error) {
currentSlot := CurrentSlot(genesis)
firstSlotOfNextEpoch, err := EpochStart(ToEpoch(currentSlot) + 1)
if err != nil {
return 0, err
}
nextEpochStartTime, err := ToTime(genesisTimeSec, firstSlotOfNextEpoch)
nextEpochStartTime, err := ToTime(genesis, firstSlotOfNextEpoch)
if err != nil {
return 0, err
}

View File

@@ -297,8 +297,8 @@ func TestRoundUpToNearestEpoch_OK(t *testing.T) {
func TestSlotToTime(t *testing.T) {
type args struct {
genesisTimeSec uint64
slot primitives.Slot
genesis time.Time
slot primitives.Slot
}
tests := []struct {
name string
@@ -309,39 +309,39 @@ func TestSlotToTime(t *testing.T) {
{
name: "slot_0",
args: args{
genesisTimeSec: 0,
slot: 0,
genesis: time.Unix(0, 0),
slot: 0,
},
want: time.Unix(0, 0),
},
{
name: "slot_1",
args: args{
genesisTimeSec: 0,
slot: 1,
genesis: time.Unix(0, 0),
slot: 1,
},
want: time.Unix(int64(1*params.BeaconConfig().SecondsPerSlot), 0),
},
{
name: "slot_12",
args: args{
genesisTimeSec: 500,
slot: 12,
genesis: time.Unix(500, 0),
slot: 12,
},
want: time.Unix(500+int64(12*params.BeaconConfig().SecondsPerSlot), 0),
},
{
name: "overflow",
args: args{
genesisTimeSec: 500,
slot: math.MaxUint64,
genesis: time.Unix(500, 0),
slot: math.MaxUint64,
},
wantedErr: "is in the far distant future",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ToTime(tt.args.genesisTimeSec, tt.args.slot)
got, err := ToTime(tt.args.genesis, tt.args.slot)
if tt.wantedErr != "" {
assert.ErrorContains(t, tt.wantedErr, err)
} else {
@@ -354,7 +354,7 @@ func TestSlotToTime(t *testing.T) {
func TestVerifySlotTime(t *testing.T) {
type args struct {
genesisTime int64
genesisTime time.Time
slot primitives.Slot
timeTolerance time.Duration
}
@@ -366,21 +366,22 @@ func TestVerifySlotTime(t *testing.T) {
{
name: "Past slot",
args: args{
genesisTime: prysmTime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(),
genesisTime: prysmTime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
slot: 3,
},
},
{
name: "within tolerance",
args: args{
genesisTime: prysmTime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Add(20 * time.Millisecond).Unix(),
slot: 5,
genesisTime: prysmTime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Add(20 * time.Millisecond),
slot: 5,
timeTolerance: 20 * time.Millisecond, // TODO(preston): I think this test was somewhat broken. There were checks that took longer than 20ms, which allowed the test to pass!
},
},
{
name: "future slot",
args: args{
genesisTime: prysmTime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(),
genesisTime: prysmTime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
slot: 6,
},
wantedErr: "could not process slot from the future",
@@ -388,7 +389,7 @@ func TestVerifySlotTime(t *testing.T) {
{
name: "future slot but ok given 2s tolerance",
args: args{
genesisTime: prysmTime.Now().Add(-1*time.Duration(params.BeaconConfig().SecondsPerSlot) - 10*time.Second).Unix(),
genesisTime: prysmTime.Now().Add(-1*time.Duration(params.BeaconConfig().SecondsPerSlot) - 10*time.Second),
slot: 1,
timeTolerance: 2 * time.Second,
},
@@ -396,7 +397,7 @@ func TestVerifySlotTime(t *testing.T) {
{
name: "max future slot",
args: args{
genesisTime: prysmTime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(),
genesisTime: prysmTime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
slot: primitives.Slot(MaxSlotBuffer + 6),
},
wantedErr: "exceeds max allowed value relative to the local clock",
@@ -404,17 +405,17 @@ func TestVerifySlotTime(t *testing.T) {
{
name: "evil future slot",
args: args{
genesisTime: prysmTime.Now().Add(-1 * 24 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(), // 24 slots in the past
genesisTime: prysmTime.Now().Add(-1 * 24 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second), // 24 slots in the past
// Gets multiplied with slot duration, and results in an overflow. Wraps around to a valid time.
// Lower than max signed int. And chosen specifically to wrap to a valid slot 24
slot: primitives.Slot((^uint64(0))/params.BeaconConfig().SecondsPerSlot) + 24,
},
wantedErr: "is in the far distant future",
wantedErr: "exceeds max allowed value relative to the local clock",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := VerifyTime(uint64(tt.args.genesisTime), tt.args.slot, tt.args.timeTolerance)
err := VerifyTime(tt.args.genesisTime, tt.args.slot, tt.args.timeTolerance)
if tt.wantedErr != "" {
assert.ErrorContains(t, tt.wantedErr, err)
} else {
@@ -425,12 +426,12 @@ func TestVerifySlotTime(t *testing.T) {
}
func TestValidateSlotClock_HandlesBadSlot(t *testing.T) {
genTime := prysmTime.Now().Add(-1 * time.Duration(MaxSlotBuffer) * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix()
genTime := prysmTime.Now().Add(-1 * time.Duration(MaxSlotBuffer) * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
assert.NoError(t, ValidateClock(primitives.Slot(MaxSlotBuffer), uint64(genTime)), "unexpected error validating slot")
assert.NoError(t, ValidateClock(primitives.Slot(2*MaxSlotBuffer), uint64(genTime)), "unexpected error validating slot")
assert.ErrorContains(t, "which exceeds max allowed value relative to the local clock", ValidateClock(primitives.Slot(2*MaxSlotBuffer+1), uint64(genTime)), "no error from bad slot")
assert.ErrorContains(t, "which exceeds max allowed value relative to the local clock", ValidateClock(1<<63, uint64(genTime)), "no error from bad slot")
assert.NoError(t, ValidateClock(primitives.Slot(MaxSlotBuffer), genTime), "unexpected error validating slot")
assert.NoError(t, ValidateClock(primitives.Slot(2*MaxSlotBuffer), genTime), "unexpected error validating slot")
assert.ErrorContains(t, "which exceeds max allowed value relative to the local clock", ValidateClock(primitives.Slot(2*MaxSlotBuffer+1), genTime), "no error from bad slot")
assert.ErrorContains(t, "which exceeds max allowed value relative to the local clock", ValidateClock(1<<63, genTime), "no error from bad slot")
}
func TestPrevSlot(t *testing.T) {
@@ -502,23 +503,24 @@ func TestSyncCommitteePeriodStartEpoch(t *testing.T) {
}
func TestSecondsSinceSlotStart(t *testing.T) {
t.Skip("TODO(Preston): This test is so bogus")
now := time.Now()
tests := []struct {
slot primitives.Slot
genesisTime uint64
timeStamp uint64
wanted uint64
wantedErr bool
slot primitives.Slot
timeStamp time.Time
wanted time.Duration
wantedErr bool
}{
{},
{slot: 1, timeStamp: 1, wantedErr: true},
{slot: 1, timeStamp: params.BeaconConfig().SecondsPerSlot + 2, wanted: 2},
{slot: 1, timeStamp: now.Add(-1 * time.Hour), wantedErr: true},
{slot: 1, timeStamp: now.Add(-2 * time.Second).Add(time.Duration(params.BeaconConfig().SecondsPerSlot)), wanted: 2 * time.Second},
}
for _, test := range tests {
w, err := SecondsSinceSlotStart(test.slot, test.genesisTime, test.timeStamp)
for i, test := range tests {
t.Logf("testing scenario %d", i)
w, err := SinceSlotStart(test.slot, now, test.timeStamp)
if err != nil {
require.Equal(t, true, test.wantedErr)
require.Equal(t, true, test.wantedErr, "wanted no error, but got %v", err)
} else {
require.Equal(t, false, test.wantedErr)
require.Equal(t, false, test.wantedErr, "wanted an error, but got %v", err)
require.Equal(t, w, test.wanted)
}
}
@@ -597,41 +599,52 @@ func TestDuration(t *testing.T) {
}
func TestTimeIntoSlot(t *testing.T) {
genesisTime := uint64(time.Now().Add(-37 * time.Second).Unix())
genesisTime := time.Now().Add(-37 * time.Second)
require.Equal(t, true, TimeIntoSlot(genesisTime) > 900*time.Millisecond)
require.Equal(t, true, TimeIntoSlot(genesisTime) < 3000*time.Millisecond)
}
func TestWithinVotingWindow(t *testing.T) {
genesisTime := uint64(time.Now().Add(-37 * time.Second).Unix())
genesisTime := time.Now().Add(-37 * time.Second)
require.Equal(t, true, WithinVotingWindow(genesisTime, 3))
genesisTime = uint64(time.Now().Add(-40 * time.Second).Unix())
genesisTime = time.Now().Add(-40 * time.Second)
require.Equal(t, false, WithinVotingWindow(genesisTime, 3))
}
func TestSecondsUntilNextEpochStart(t *testing.T) {
secondsInEpoch := uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().SecondsPerSlot
// try slot 3
genesisTime := uint64(time.Now().Add(-39 * time.Second).Unix())
genesisTime := time.Now().Add(-39 * time.Second)
waitTime, err := SecondsUntilNextEpochStart(genesisTime)
require.NoError(t, err)
require.Equal(t, secondsInEpoch-(params.BeaconConfig().SecondsPerSlot*3)-3, waitTime)
// try slot 34
genesisTime = uint64(time.Now().Add(time.Duration(-1*int(secondsInEpoch)-int(params.BeaconConfig().SecondsPerSlot*2)-5) * time.Second).Unix())
genesisTime = time.Now().Add(time.Duration(-1*int(secondsInEpoch)-int(params.BeaconConfig().SecondsPerSlot*2)-5) * time.Second)
waitTime, err = SecondsUntilNextEpochStart(genesisTime)
require.NoError(t, err)
require.Equal(t, secondsInEpoch-(params.BeaconConfig().SecondsPerSlot*2)-5, waitTime)
// check if waitTime is correctly EpochStart
n := time.Now().Add(-39 * time.Second)
genesisTime = uint64(n.Unix())
genesisTime = n
waitTime, err = SecondsUntilNextEpochStart(genesisTime)
require.NoError(t, err)
require.Equal(t, secondsInEpoch-39, waitTime)
newGenesisTime := uint64(n.Add(time.Duration(-1*int(waitTime)) * time.Second).Unix())
newGenesisTime := n.Add(time.Duration(-1*int(waitTime)) * time.Second)
currentSlot := CurrentSlot(newGenesisTime)
require.Equal(t, true, IsEpochStart(currentSlot))
}
func TestCurrentSlot(t *testing.T) {
for i := primitives.Slot(0); i < 1<<20; i++ {
testCurrentSlot(t, i)
}
}
func testCurrentSlot(t testing.TB, slot primitives.Slot) {
genesis := time.Now().Add(-1 * time.Duration(slot) * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
cs := CurrentSlot(genesis)
require.Equal(t, slot, cs)
}
func TestToForkVersion(t *testing.T) {

View File

@@ -326,7 +326,7 @@ func printStates(stateC <-chan *modifiedState, doneC chan<- bool) {
log.Infof("---- row = %04d, slot = %8d, epoch = %8d, key = %s ----", mst.rowCount, st.Slot(), st.Slot()/params.BeaconConfig().SlotsPerEpoch, hexutils.BytesToHex(mst.key))
log.Infof("key : %s", hexutils.BytesToHex(mst.key))
log.Infof("value : compressed size = %s", humanize.Bytes(mst.valueSize))
t := time.Unix(int64(st.GenesisTime()), 0) // lint:ignore uintcast -- Genesis time will not exceed int64 in your lifetime.
t := st.GenesisTime()
log.Infof("genesis_time : %s", t.Format(time.UnixDate))
log.Infof("genesis_validators_root : %s", hexutils.BytesToHex(st.GenesisValidatorsRoot()))
log.Infof("slot : %d", st.Slot())

View File

@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"testing"
"time"
fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams"
"github.com/OffchainLabs/prysm/v6/config/params"
@@ -14,7 +15,6 @@ import (
"github.com/OffchainLabs/prysm/v6/testing/assert"
"github.com/OffchainLabs/prysm/v6/testing/require"
"github.com/OffchainLabs/prysm/v6/testing/util"
"github.com/OffchainLabs/prysm/v6/time"
"github.com/OffchainLabs/prysm/v6/time/slots"
"github.com/OffchainLabs/prysm/v6/validator/client/iface"
"github.com/prysmaticlabs/go-bitfield"
@@ -256,7 +256,7 @@ func TestWaitForSlotTwoThird_WaitCorrectly(t *testing.T) {
defer finish()
currentTime := time.Now()
numOfSlots := primitives.Slot(4)
validator.genesisTime = uint64(currentTime.Unix()) - uint64(numOfSlots.Mul(params.BeaconConfig().SecondsPerSlot))
validator.genesisTime = currentTime.Add(-1 * time.Duration(numOfSlots.Mul(params.BeaconConfig().SecondsPerSlot)) * time.Second)
oneThird := slots.DivideSlotBy(3 /* one third of slot duration */)
timeToSleep := oneThird + oneThird
@@ -275,7 +275,7 @@ func TestWaitForSlotTwoThird_DoneContext_ReturnsImmediately(t *testing.T) {
defer finish()
currentTime := time.Now()
numOfSlots := primitives.Slot(4)
validator.genesisTime = uint64(currentTime.Unix()) - uint64(numOfSlots.Mul(params.BeaconConfig().SecondsPerSlot))
validator.genesisTime = currentTime.Add(-1 * time.Duration(numOfSlots.Mul(params.BeaconConfig().SecondsPerSlot)) * time.Second)
expectedTime := time.Now()
ctx, cancel := context.WithCancel(t.Context())

Some files were not shown because too many files have changed in this diff Show More