Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix deposit block slot before genesis state #4495

Merged
10 changes: 8 additions & 2 deletions beacon-chain/rpc/validator/status.go
Expand Up @@ -178,6 +178,7 @@ func (vs *Server) assignmentStatus(validatorIdx uint64, beaconState *pbp2p.Beaco
}

func (vs *Server) depositBlockSlot(ctx context.Context, eth1BlockNumBigInt *big.Int, beaconState *pbp2p.BeaconState) (uint64, error) {
var depositBlockSlot uint64
blockTimeStamp, err := vs.BlockFetcher.BlockTimeByHeight(ctx, eth1BlockNumBigInt)
if err != nil {
return 0, err
Expand All @@ -190,8 +191,13 @@ func (vs *Server) depositBlockSlot(ctx context.Context, eth1BlockNumBigInt *big.
timeToInclusion := eth1UnixTime.Add(votingPeriodSeconds)

eth2Genesis := time.Unix(int64(beaconState.GenesisTime), 0)
eth2TimeDifference := timeToInclusion.Sub(eth2Genesis).Seconds()
depositBlockSlot := uint64(eth2TimeDifference) / params.BeaconConfig().SecondsPerSlot

if eth2Genesis.After(timeToInclusion) {
princesinha19 marked this conversation as resolved.
Show resolved Hide resolved
depositBlockSlot = 0
} else {
eth2TimeDifference := timeToInclusion.Sub(eth2Genesis).Seconds()
depositBlockSlot = uint64(eth2TimeDifference) / params.BeaconConfig().SecondsPerSlot
}

return depositBlockSlot, nil
}
153 changes: 153 additions & 0 deletions beacon-chain/rpc/validator/status_test.go
@@ -1,6 +1,7 @@
package validator

import (
"math/big"
"context"
"testing"
"time"
Expand Down Expand Up @@ -744,3 +745,155 @@ func TestValidatorStatus_CorrectActivationQueue(t *testing.T) {
t.Errorf("Expected Position in activation queue of %d but instead got %d", 2, resp.PositionInActivationQueue)
}
}

func TestDepositBlockSlotAfterGenesisTime(t *testing.T) {
db := dbutil.SetupDB(t)
defer dbutil.TeardownDB(t, db)
ctx := context.Background()

pubKey := pubKey(1)
if err := db.SaveValidatorIndex(ctx, pubKey, 0); err != nil {
t.Fatalf("Could not save validator index: %v", err)
}

depData := &ethpb.Deposit_Data{
PublicKey: pubKey,
Signature: []byte("hi"),
WithdrawalCredentials: []byte("hey"),
}

deposit := &ethpb.Deposit{
Data: depData,
}
depositTrie, err := trieutil.NewTrie(int(params.BeaconConfig().DepositContractTreeDepth))
if err != nil {
t.Fatalf("Could not setup deposit trie: %v", err)
}
depositCache := depositcache.NewDepositCache()
depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.Root())

timestamp := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
p := &mockPOW.POWChain{
TimesByHeight: map[int]uint64{
int(params.BeaconConfig().Eth1FollowDistance): uint64(timestamp),
},
}

block := blk.NewGenesisBlock([]byte{})
if err := db.SaveBlock(ctx, block); err != nil {
t.Fatalf("Could not save genesis block: %v", err)
}
genesisRoot, err := ssz.HashTreeRoot(block.Block)
if err != nil {
t.Fatalf("Could not get signing root %v", err)
}

activeEpoch := helpers.DelayedActivationExitEpoch(0)

state := &pbp2p.BeaconState{
GenesisTime: uint64(time.Unix(0, 0).Unix()),
Slot: 10000,
Validators: []*ethpb.Validator{{
ActivationEpoch: activeEpoch,
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
PublicKey: pubKey},
}}

vs := &Server{
BeaconDB: db,
ChainStartFetcher: p,
BlockFetcher: p,
Eth1InfoFetcher: p,
DepositFetcher: depositCache,
HeadFetcher: &mockChain.ChainService{State: state, Root: genesisRoot[:]},
}

eth1BlockNumBigInt := big.NewInt(1000000)

resp, err := vs.depositBlockSlot(context.Background(), eth1BlockNumBigInt, state)
if err != nil {
t.Fatalf("Could not get the deposit block slot %v", err)
}

expected := uint64(2405)

if resp != expected {
t.Errorf("Wanted %v, got %v", expected, resp)
}
}

func TestDepositBlockSlotBeforeGenesisTime(t *testing.T) {
db := dbutil.SetupDB(t)
defer dbutil.TeardownDB(t, db)
ctx := context.Background()

pubKey := pubKey(1)
if err := db.SaveValidatorIndex(ctx, pubKey, 0); err != nil {
t.Fatalf("Could not save validator index: %v", err)
}

depData := &ethpb.Deposit_Data{
PublicKey: pubKey,
Signature: []byte("hi"),
WithdrawalCredentials: []byte("hey"),
}

deposit := &ethpb.Deposit{
Data: depData,
}
depositTrie, err := trieutil.NewTrie(int(params.BeaconConfig().DepositContractTreeDepth))
if err != nil {
t.Fatalf("Could not setup deposit trie: %v", err)
}
depositCache := depositcache.NewDepositCache()
depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.Root())

timestamp := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
p := &mockPOW.POWChain{
TimesByHeight: map[int]uint64{
int(params.BeaconConfig().Eth1FollowDistance): uint64(timestamp),
},
}

block := blk.NewGenesisBlock([]byte{})
if err := db.SaveBlock(ctx, block); err != nil {
t.Fatalf("Could not save genesis block: %v", err)
}
genesisRoot, err := ssz.HashTreeRoot(block.Block)
if err != nil {
t.Fatalf("Could not get signing root %v", err)
}

activeEpoch := helpers.DelayedActivationExitEpoch(0)

state := &pbp2p.BeaconState{
GenesisTime: uint64(time.Unix(25000, 0).Unix()),
Slot: 10000,
Validators: []*ethpb.Validator{{
ActivationEpoch: activeEpoch,
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
PublicKey: pubKey},
}}

vs := &Server{
BeaconDB: db,
ChainStartFetcher: p,
BlockFetcher: p,
Eth1InfoFetcher: p,
DepositFetcher: depositCache,
HeadFetcher: &mockChain.ChainService{State: state, Root: genesisRoot[:]},
}

eth1BlockNumBigInt := big.NewInt(1000000)

resp, err := vs.depositBlockSlot(context.Background(), eth1BlockNumBigInt, state)
if err != nil {
t.Fatalf("Could not get the deposit block slot %v", err)
}

expected := uint64(0)

if resp != expected {
t.Errorf("Wanted %v, got %v", expected, resp)
}
}