From 87ca73d60512ef488fe9551237bc9601c0f34809 Mon Sep 17 00:00:00 2001 From: Raul Jordan Date: Fri, 12 Jun 2020 13:47:18 -0500 Subject: [PATCH] Countdown Until Genesis (#6231) * added in logic * latest countdown * fixed up formatting and add tests * ready for review * Merge branch 'master' into countdown-genesis * no log if after genesis * Merge branch 'countdown-genesis' of github.com:prysmaticlabs/prysm into countdown-genesis * countdown * smarter logging * added buffer period for countdown * Merge refs/heads/master into countdown-genesis --- beacon-chain/blockchain/service.go | 10 ++++ beacon-chain/interop-cold-start/BUILD.bazel | 1 + beacon-chain/interop-cold-start/service.go | 3 ++ shared/params/config.go | 2 + shared/slotutil/BUILD.bazel | 13 +++++- shared/slotutil/countdown.go | 51 +++++++++++++++++++++ shared/slotutil/countdown_test.go | 30 ++++++++++++ 7 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 shared/slotutil/countdown.go create mode 100644 shared/slotutil/countdown_test.go diff --git a/beacon-chain/blockchain/service.go b/beacon-chain/blockchain/service.go index 5f1ec80189..80c6805e83 100644 --- a/beacon-chain/blockchain/service.go +++ b/beacon-chain/blockchain/service.go @@ -37,6 +37,7 @@ import ( "github.com/prysmaticlabs/prysm/shared/bytesutil" "github.com/prysmaticlabs/prysm/shared/featureconfig" "github.com/prysmaticlabs/prysm/shared/params" + "github.com/prysmaticlabs/prysm/shared/slotutil" "go.opencensus.io/trace" ) @@ -167,6 +168,10 @@ func (s *Service) Start() { if err := s.initializeChainInfo(ctx); err != nil { log.Fatalf("Could not set up chain info: %v", err) } + + // We start a counter to genesis, if needed. + go slotutil.CountdownToGenesis(ctx, s.genesisTime, uint64(beaconState.NumValidators())) + justifiedCheckpoint, err := s.beaconDB.JustifiedCheckpoint(ctx) if err != nil { log.Fatalf("Could not get justified checkpoint: %v", err) @@ -245,6 +250,11 @@ func (s *Service) processChainStartTime(ctx context.Context, genesisTime time.Ti if err != nil { log.Fatalf("Could not initialize beacon chain: %v", err) } + // We start a counter to genesis, if needed. + go slotutil.CountdownToGenesis(ctx, genesisTime, uint64(initializedState.NumValidators())) + + // We send out a state initialized event to the rest of the services + // running in the beacon node. s.stateNotifier.StateFeed().Send(&feed.Event{ Type: statefeed.Initialized, Data: &statefeed.InitializedData{ diff --git a/beacon-chain/interop-cold-start/BUILD.bazel b/beacon-chain/interop-cold-start/BUILD.bazel index 76f251bbd6..0721c5c6d0 100644 --- a/beacon-chain/interop-cold-start/BUILD.bazel +++ b/beacon-chain/interop-cold-start/BUILD.bazel @@ -18,6 +18,7 @@ go_library( "//proto/beacon/p2p/v1:go_default_library", "//shared:go_default_library", "//shared/interop:go_default_library", + "//shared/slotutil:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", diff --git a/beacon-chain/interop-cold-start/service.go b/beacon-chain/interop-cold-start/service.go index 58c2da7f08..a2af8663de 100644 --- a/beacon-chain/interop-cold-start/service.go +++ b/beacon-chain/interop-cold-start/service.go @@ -7,6 +7,7 @@ import ( "context" "io/ioutil" "math/big" + "time" "github.com/pkg/errors" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" @@ -19,6 +20,7 @@ import ( pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" "github.com/prysmaticlabs/prysm/shared" "github.com/prysmaticlabs/prysm/shared/interop" + "github.com/prysmaticlabs/prysm/shared/slotutil" ) var _ = shared.Service(&Service{}) @@ -97,6 +99,7 @@ func NewColdStartService(ctx context.Context, cfg *Config) *Service { // Generated genesis time; fetch it s.genesisTime = genesisTrie.GenesisTime() } + go slotutil.CountdownToGenesis(ctx, time.Unix(int64(s.genesisTime), 0), s.numValidators) if err := s.saveGenesisState(ctx, genesisTrie); err != nil { log.Fatalf("Could not save interop genesis state %v", err) diff --git a/shared/params/config.go b/shared/params/config.go index 362d9f0d37..5adf8b15a8 100644 --- a/shared/params/config.go +++ b/shared/params/config.go @@ -100,6 +100,7 @@ type BeaconChainConfig struct { DefaultPageSize int // DefaultPageSize defines the default page size for RPC server request. MaxPeersToSync int // MaxPeersToSync describes the limit for number of peers in round robin sync. SlotsPerArchivedPoint uint64 // SlotsPerArchivedPoint defines the number of slots per one archived point. + GenesisCountdownInterval time.Duration // How often to log the countdown until the genesis time is reached. // Slasher constants. WeakSubjectivityPeriod uint64 // WeakSubjectivityPeriod defines the time period expressed in number of epochs were proof of stake network should validate block headers and attestations for slashable events. @@ -200,6 +201,7 @@ var defaultBeaconConfig = &BeaconChainConfig{ DefaultPageSize: 250, MaxPeersToSync: 15, SlotsPerArchivedPoint: 2048, + GenesisCountdownInterval: time.Minute, // Slasher related values. WeakSubjectivityPeriod: 54000, diff --git a/shared/slotutil/BUILD.bazel b/shared/slotutil/BUILD.bazel index 50ca596017..be8b94b9d5 100644 --- a/shared/slotutil/BUILD.bazel +++ b/shared/slotutil/BUILD.bazel @@ -4,6 +4,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_test") go_library( name = "go_default_library", srcs = [ + "countdown.go", "slotticker.go", "slottime.go", ], @@ -12,12 +13,22 @@ go_library( deps = [ "//shared/params:go_default_library", "//shared/roughtime:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", ], ) go_test( name = "go_default_test", size = "small", - srcs = ["slotticker_test.go"], + srcs = [ + "countdown_test.go", + "slotticker_test.go", + ], embed = [":go_default_library"], + deps = [ + "//shared/params:go_default_library", + "//shared/roughtime:go_default_library", + "//shared/testutil:go_default_library", + "@com_github_sirupsen_logrus//hooks/test:go_default_library", + ], ) diff --git a/shared/slotutil/countdown.go b/shared/slotutil/countdown.go new file mode 100644 index 0000000000..18b11fed4d --- /dev/null +++ b/shared/slotutil/countdown.go @@ -0,0 +1,51 @@ +package slotutil + +import ( + "context" + "fmt" + "time" + + "github.com/prysmaticlabs/prysm/shared/params" + "github.com/prysmaticlabs/prysm/shared/roughtime" + "github.com/sirupsen/logrus" +) + +var log = logrus.WithField("prefix", "slotutil") + +// CountdownToGenesis starts a ticker at the specified duration +// logging the remaining minutes until the genesis chainstart event +// along with important genesis state metadata such as number +// of genesis validators. +func CountdownToGenesis(ctx context.Context, genesisTime time.Time, genesisValidatorCount uint64) { + ticker := time.NewTicker(params.BeaconConfig().GenesisCountdownInterval) + timeTillGenesis := genesisTime.Sub(roughtime.Now()) + logFields := logrus.Fields{ + "genesisValidators": fmt.Sprintf("%d", genesisValidatorCount), + "genesisTime": fmt.Sprintf("%v", genesisTime), + } + for { + select { + case <-time.After(timeTillGenesis): + log.WithFields(logFields).Info("Chain genesis time reached") + return + case <-ticker.C: + currentTime := roughtime.Now() + if currentTime.After(genesisTime) { + log.WithFields(logFields).Info("Chain genesis time reached") + return + } + timeRemaining := genesisTime.Sub(currentTime) + if timeRemaining <= 2*time.Minute { + ticker = time.NewTicker(time.Second) + } + if timeRemaining >= time.Second { + log.WithFields(logFields).Infof( + "%s until chain genesis", + timeRemaining.Truncate(time.Second), + ) + } + case <-ctx.Done(): + return + } + } +} diff --git a/shared/slotutil/countdown_test.go b/shared/slotutil/countdown_test.go new file mode 100644 index 0000000000..759aa483b6 --- /dev/null +++ b/shared/slotutil/countdown_test.go @@ -0,0 +1,30 @@ +package slotutil + +import ( + "context" + "testing" + "time" + + "github.com/prysmaticlabs/prysm/shared/params" + "github.com/prysmaticlabs/prysm/shared/roughtime" + "github.com/prysmaticlabs/prysm/shared/testutil" + logTest "github.com/sirupsen/logrus/hooks/test" +) + +func TestCountdownToGenesis(t *testing.T) { + hook := logTest.NewGlobal() + params.SetupTestConfigCleanup(t) + config := params.BeaconConfig() + config.GenesisCountdownInterval = time.Millisecond * 500 + params.OverrideBeaconConfig(config) + + firstStringResult := "1s until chain genesis" + genesisReached := "Chain genesis time reached" + CountdownToGenesis( + context.Background(), + roughtime.Now().Add(2*time.Second), + params.BeaconConfig().MinGenesisActiveValidatorCount, + ) + testutil.AssertLogsContain(t, hook, firstStringResult) + testutil.AssertLogsContain(t, hook, genesisReached) +}