SlotToTime helper (#5710)

* SlotToTime helper
* gofmt
* gaz
* overflow
* Merge refs/heads/master into better-time
* Fix tests, move overflow
* Merge branch 'better-time' of github.com:prysmaticlabs/prysm into better-time
* smaller diff
This commit is contained in:
Preston Van Loon 2020-05-01 16:19:43 -07:00 committed by GitHub
parent 125d022518
commit 37f2a04e51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 127 additions and 8 deletions

View File

@ -92,10 +92,10 @@ func TestStore_OnBlock(t *testing.T) {
wantErrString: "provided block root does not have block saved in the db",
},
{
name: "block is from the feature",
name: "block is from the future",
blk: &ethpb.BeaconBlock{ParentRoot: randomParentRoot[:], Slot: params.BeaconConfig().FarFutureEpoch},
s: st.Copy(),
wantErrString: "could not process slot from the future",
wantErrString: "far distant future",
},
{
name: "could not get finalized block",

View File

@ -70,6 +70,7 @@ go_test(
"//shared/featureconfig:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library",
"//shared/roughtime:go_default_library",
"//shared/sliceutil:go_default_library",
"//shared/testutil:go_default_library",
"@com_github_google_gofuzz//:go_default_library",

View File

@ -2,6 +2,7 @@ package helpers
import (
"fmt"
"math"
"time"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
@ -94,16 +95,28 @@ const TimeShiftTolerance = 500 * time.Millisecond // ms
// VerifySlotTime validates the input slot is not from the future.
func VerifySlotTime(genesisTime uint64, slot uint64, timeTolerance time.Duration) error {
// denominate everything in milliseconds
slotTime := 1000 * (genesisTime + slot*params.BeaconConfig().SecondsPerSlot)
currentTime := 1000 * uint64(roughtime.Now().Unix())
tolerance := uint64(timeTolerance.Milliseconds())
if slotTime > currentTime+tolerance {
return fmt.Errorf("could not process slot from the future, slot time(ms) %d > current time(ms) %d", slotTime, currentTime)
slotTime, err := SlotToTime(genesisTime, slot)
if err != nil {
return err
}
currentTime := roughtime.Now()
diff := slotTime.Sub(currentTime)
if diff > timeTolerance {
return fmt.Errorf("could not process slot from the future, slot time %s > current time %s", slotTime, currentTime)
}
return nil
}
// SlotToTime takes the given slot and genesis time to determine the start time of the slot.
func SlotToTime(genesisTimeSec uint64, slot uint64) (time.Time, error) {
if slot >= math.MaxInt64 {
return time.Unix(0, 0), fmt.Errorf("slot (%d) is in the far distant future", slot)
}
timeSinceGenesis := slot * params.BeaconConfig().SecondsPerSlot
return time.Unix(int64(genesisTimeSec+timeSinceGenesis), 0), nil
}
// SlotsSince computes the number of time slots that have occurred since the given timestamp.
func SlotsSince(time time.Time) uint64 {
return uint64(roughtime.Since(time).Seconds()) / params.BeaconConfig().SecondsPerSlot

View File

@ -1,7 +1,11 @@
package helpers
import (
"github.com/prysmaticlabs/prysm/shared/roughtime"
"math"
"reflect"
"testing"
"time"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
@ -200,3 +204,104 @@ func TestRoundUpToNearestEpoch_OK(t *testing.T) {
}
}
}
func TestSlotToTime(t *testing.T) {
type args struct {
genesisTimeSec uint64
slot uint64
}
tests := []struct {
name string
args args
want time.Time
wantErr bool
}{
{
name: "slot_0",
args: args{
genesisTimeSec: 0,
slot: 0,
},
want: time.Unix(0, 0),
wantErr: false,
},
{
name: "slot_1",
args: args{
genesisTimeSec: 0,
slot: 1,
},
want: time.Unix(int64(1*params.BeaconConfig().SecondsPerSlot), 0),
wantErr: false,
},
{
name: "slot_12",
args: args{
genesisTimeSec: 500,
slot: 12,
},
want: time.Unix(500+int64(12*params.BeaconConfig().SecondsPerSlot), 0),
wantErr: false,
},
{
name: "overflow",
args: args{
genesisTimeSec: 500,
slot: math.MaxUint64,
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got, err := SlotToTime(tt.args.genesisTimeSec, tt.args.slot); (err != nil ) != tt.wantErr && !reflect.DeepEqual(got, tt.want) {
t.Errorf("SlotToTime() = %v, want %v", got, tt.want)
}
})
}
}
func TestVerifySlotTime(t *testing.T) {
type args struct {
genesisTime int64
slot uint64
timeTolerance time.Duration
}
tests := []struct {
name string
args args
wantErr bool
}{
{
name: "Past slot",
args: args{
genesisTime: roughtime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(),
slot: 3,
},
wantErr: false,
},
{
name: "within tolerance",
args: args{
genesisTime: roughtime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Add(20 * time.Millisecond).Unix(),
slot: 5,
},
wantErr: false,
},
{
name: "future slot",
args: args{
genesisTime: roughtime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(),
slot: 6,
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := VerifySlotTime(uint64(tt.args.genesisTime), tt.args.slot, tt.args.timeTolerance); (err != nil) != tt.wantErr {
t.Errorf("VerifySlotTime() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}