diff --git a/beacon-chain/blockchain/forkchoice/BUILD.bazel b/beacon-chain/blockchain/forkchoice/BUILD.bazel index 2965c1b66d7a..2628fb7aa553 100644 --- a/beacon-chain/blockchain/forkchoice/BUILD.bazel +++ b/beacon-chain/blockchain/forkchoice/BUILD.bazel @@ -25,6 +25,7 @@ go_library( "//shared/featureconfig:go_default_library", "//shared/hashutil:go_default_library", "//shared/params:go_default_library", + "//shared/roughtime:go_default_library", "//shared/traceutil:go_default_library", "@com_github_gogo_protobuf//proto:go_default_library", "@com_github_pkg_errors//:go_default_library", diff --git a/beacon-chain/blockchain/forkchoice/process_attestation.go b/beacon-chain/blockchain/forkchoice/process_attestation.go index 4f54388d1da6..5174a5b878dc 100644 --- a/beacon-chain/blockchain/forkchoice/process_attestation.go +++ b/beacon-chain/blockchain/forkchoice/process_attestation.go @@ -50,7 +50,7 @@ var ErrTargetRootNotInDB = errors.New("target root does not exist in db") // assert target.root in store.blocks // # Attestations cannot be from future epochs. If they are, delay consideration until the epoch arrives // base_state = store.block_states[target.root].copy() -// assert store.time >= base_state.genesis_time + compute_start_slot_at_epoch(target.epoch) * SECONDS_PER_SLOT +// assert get_current_slot(store) >= compute_start_slot_at_epoch(target.epoch) // // # Attestations must be for a known block. If block is unknown, delay consideration until the block is found // assert attestation.data.beacon_block_root in store.blocks @@ -65,7 +65,7 @@ var ErrTargetRootNotInDB = errors.New("target root does not exist in db") // // # Attestations can only affect the fork choice of subsequent slots. // # Delay consideration in the fork choice until their slot is in the past. -// assert store.time >= (attestation.data.slot + 1) * SECONDS_PER_SLOT +// assert get_current_slot(store) >= attestation.data.slot + 1 // // # Get state at the `target` to validate attestation and calculate the committees // indexed_attestation = get_indexed_attestation(target_state, attestation) @@ -80,7 +80,6 @@ func (s *Store) OnAttestation(ctx context.Context, a *ethpb.Attestation) error { defer span.End() tgt := proto.Clone(a.Data.Target).(*ethpb.Checkpoint) - tgtSlot := helpers.StartSlot(tgt.Epoch) // Verify beacon node has seen the target block before. if !s.db.HasBlock(ctx, bytesutil.ToBytes32(tgt.Root)) { @@ -99,8 +98,8 @@ func (s *Store) OnAttestation(ctx context.Context, a *ethpb.Attestation) error { } // Verify Attestations cannot be from future epochs. - if err := helpers.VerifySlotTime(baseState.GenesisTime, tgtSlot); err != nil { - return errors.Wrap(err, "could not verify attestation target slot") + if helpers.StartSlot(tgt.Epoch) > s.currentSlot() { + return fmt.Errorf("could not process future attestation %d, current slot %d", helpers.StartSlot(tgt.Epoch), s.currentSlot()) } // Verify attestation beacon block is known and not from the future. @@ -115,8 +114,8 @@ func (s *Store) OnAttestation(ctx context.Context, a *ethpb.Attestation) error { } // Verify attestations can only affect the fork choice of subsequent slots. - if err := helpers.VerifySlotTime(baseState.GenesisTime, a.Data.Slot+1); err != nil { - return err + if a.Data.Slot+1 > s.currentSlot() { + return fmt.Errorf("could not process attesatin until subsequent slots %d, current slot %d", a.Data.Slot+1, s.currentSlot()) } // Use the target state to to validate attestation and calculate the committees. diff --git a/beacon-chain/blockchain/forkchoice/process_block.go b/beacon-chain/blockchain/forkchoice/process_block.go index 2d048732aa61..55fde5263663 100644 --- a/beacon-chain/blockchain/forkchoice/process_block.go +++ b/beacon-chain/blockchain/forkchoice/process_block.go @@ -5,7 +5,6 @@ import ( "context" "encoding/hex" "fmt" - "time" "github.com/gogo/protobuf/proto" "github.com/pkg/errors" @@ -21,6 +20,7 @@ import ( "github.com/prysmaticlabs/prysm/shared/featureconfig" "github.com/prysmaticlabs/prysm/shared/hashutil" "github.com/prysmaticlabs/prysm/shared/params" + "github.com/prysmaticlabs/prysm/shared/roughtime" "github.com/prysmaticlabs/prysm/shared/traceutil" "github.com/sirupsen/logrus" "go.opencensus.io/trace" @@ -35,7 +35,7 @@ import ( // assert block.parent_root in store.block_states // pre_state = store.block_states[block.parent_root].copy() // # Blocks cannot be in the future. If they are, their consideration must be delayed until the are in the past. -// assert store.time >= pre_state.genesis_time + block.slot * SECONDS_PER_SLOT +// assert get_current_slot(store) >= block.slot // # Add new block to the store // store.blocks[signing_root(block)] = block // # Check block is a descendant of the finalized block @@ -254,8 +254,8 @@ func (s *Store) getBlockPreState(ctx context.Context, b *ethpb.BeaconBlock) (*pb } // Verify block slot time is not from the feature. - if err := helpers.VerifySlotTime(preState.GenesisTime, b.Slot); err != nil { - return nil, err + if b.Slot > s.currentSlot() { + return nil, fmt.Errorf("could not process future block %d, current slot %d", b.Slot, s.currentSlot()) } // Verify block is a descendent of a finalized block. @@ -498,9 +498,14 @@ func (s *Store) shouldUpdateJustified(ctx context.Context, newJustifiedCheckpt * return true, nil } -// currentSlot returns the current slot based on time. +// currentSlot returns the current slot number. func (s *Store) currentSlot() uint64 { - return (uint64(time.Now().Unix()) - s.genesisTime) / params.BeaconConfig().SecondsPerSlot + return params.BeaconConfig().GenesisSlot + s.slotsSinceGenesis() +} + +// slotsSinceGenesis returns how many slots has passed since genesis time. +func (s *Store) slotsSinceGenesis() uint64 { + return (uint64(roughtime.Now().Unix()) - s.genesisTime) / params.BeaconConfig().SecondsPerSlot } // updates justified check point in store if a better check point is known diff --git a/beacon-chain/blockchain/forkchoice/process_block_test.go b/beacon-chain/blockchain/forkchoice/process_block_test.go index 5b51c42f8b43..4b8357c22f23 100644 --- a/beacon-chain/blockchain/forkchoice/process_block_test.go +++ b/beacon-chain/blockchain/forkchoice/process_block_test.go @@ -64,7 +64,7 @@ func TestStore_OnBlock(t *testing.T) { name: "block is from the feature", blk: ðpb.BeaconBlock{ParentRoot: randomParentRoot[:], Slot: params.BeaconConfig().FarFutureEpoch}, s: &pb.BeaconState{}, - wantErrString: "could not process slot from the future", + wantErrString: "could not process future block", }, { name: "could not get finalized block", diff --git a/shared/params/config.go b/shared/params/config.go index 80cf69598467..57f0ad4af3e2 100644 --- a/shared/params/config.go +++ b/shared/params/config.go @@ -27,6 +27,7 @@ type BeaconChainConfig struct { MinGenesisActiveValidatorCount uint64 `yaml:"MIN_GENESIS_ACTIVE_VALIDATOR_COUNT"` // MinGenesisActiveValidatorCount defines how many validator deposits needed to kick off beacon chain. MinGenesisTime uint64 `yaml:"MIN_GENESIS_TIME"` // MinGenesisTime is the time that needed to pass before kicking off beacon chain. Currently set to Jan/3/2020. TargetAggregatorsPerCommittee uint64 // TargetAggregatorsPerCommittee defines the number of aggregators inside one committee. + GenesisSlot uint64 // GenesisSlot is the slot number when beacon chain starts. // Gwei value constants. MinDepositAmount uint64 `yaml:"MIN_DEPOSIT_AMOUNT"` // MinDepositAmount is the maximal amount of Gwei a validator can send to the deposit contract at once. @@ -124,6 +125,7 @@ var defaultBeaconConfig = &BeaconChainConfig{ MinGenesisActiveValidatorCount: 16384, MinGenesisTime: 1578009600, TargetAggregatorsPerCommittee: 16, + GenesisSlot: 0, // Gwei value constants. MinDepositAmount: 1 * 1e9,