diff --git a/beacon-chain/main.go b/beacon-chain/main.go index c1ae1a92c..7a55ae2bb 100644 --- a/beacon-chain/main.go +++ b/beacon-chain/main.go @@ -71,6 +71,7 @@ VERSION: utils.GenesisJSON, utils.EnablePOWChain, utils.EnableDBCleanup, + utils.ChainStartDelay, cmd.BootstrapNode, cmd.RelayNode, cmd.P2PPort, diff --git a/beacon-chain/node/node.go b/beacon-chain/node/node.go index 0d65ae25e..158ad503b 100644 --- a/beacon-chain/node/node.go +++ b/beacon-chain/node/node.go @@ -207,6 +207,8 @@ func (b *BeaconNode) registerPOWChainService(ctx *cli.Context) error { } powClient := ethclient.NewClient(rpcClient) + delay := ctx.GlobalUint64(utils.ChainStartDelay.Name) + web3Service, err := powchain.NewWeb3Service(context.TODO(), &powchain.Web3ServiceConfig{ Endpoint: b.ctx.GlobalString(utils.Web3ProviderFlag.Name), DepositContract: common.HexToAddress(b.ctx.GlobalString(utils.DepositContractFlag.Name)), @@ -215,6 +217,7 @@ func (b *BeaconNode) registerPOWChainService(ctx *cli.Context) error { Logger: powClient, ContractBackend: powClient, BeaconDB: b.db, + ChainStartDelay: delay, }) if err != nil { return fmt.Errorf("could not register proof-of-work chain web3Service: %v", err) diff --git a/beacon-chain/powchain/service.go b/beacon-chain/powchain/service.go index c30171654..a422e3cfb 100644 --- a/beacon-chain/powchain/service.go +++ b/beacon-chain/powchain/service.go @@ -89,6 +89,7 @@ type Web3Service struct { chainStarted bool beaconDB *db.BeaconDB lastReceivedMerkleIndex int64 // Keeps track of the last received index to prevent log spam. + chainStartDelay uint64 } // Web3ServiceConfig defines a config struct for web3 service to use through its life cycle. @@ -100,6 +101,7 @@ type Web3ServiceConfig struct { Logger bind.ContractFilterer ContractBackend bind.ContractBackend BeaconDB *db.BeaconDB + ChainStartDelay uint64 } var ( @@ -140,6 +142,7 @@ func NewWeb3Service(ctx context.Context, config *Web3ServiceConfig) (*Web3Servic chainStartDeposits: []*pb.Deposit{}, beaconDB: config.BeaconDB, lastReceivedMerkleIndex: -1, + chainStartDelay: config.ChainStartDelay, }, nil } @@ -149,6 +152,10 @@ func (w *Web3Service) Start() { "endpoint": w.endpoint, }).Info("Starting service") go w.run(w.ctx.Done()) + + if w.chainStartDelay > 0 { + go w.runDelayTimer(w.ctx.Done()) + } } // Stop the web3 service's main event loop and associated goroutines. @@ -291,10 +298,32 @@ func (w *Web3Service) ProcessChainStartLog(depositLog gethTypes.Log) { chainStartTime := time.Unix(int64(timestamp), 0) log.WithFields(logrus.Fields{ "ChainStartTime": chainStartTime, - }).Info("Minimum Number of Validators Reached for beacon-chain to start") + }).Info("Minimum number of validators reached for beacon-chain to start") w.chainStartFeed.Send(chainStartTime) } +func (w *Web3Service) runDelayTimer(done <-chan struct{}) { + timer := time.NewTimer(time.Duration(w.chainStartDelay) * time.Second) + + for { + select { + case <-done: + log.Debug("ETH1.0 chain service context closed, exiting goroutine") + timer.Stop() + return + case currentTime := <-timer.C: + + w.chainStarted = true + log.WithFields(logrus.Fields{ + "ChainStartTime": currentTime.Unix(), + }).Info("Minimum number of validators reached for beacon-chain to start") + w.chainStartFeed.Send(currentTime) + timer.Stop() + return + } + } +} + // run subscribes to all the services for the ETH1.0 chain. func (w *Web3Service) run(done <-chan struct{}) { if err := w.initDataFromContract(); err != nil { @@ -323,9 +352,13 @@ func (w *Web3Service) run(done <-chan struct{}) { log.Errorf("Unable to query logs from deposit contract: %v", err) return } - if err := w.processPastLogs(query); err != nil { - log.Errorf("Unable to process past logs %v", err) - return + + // Only process logs if the chain start delay flag is not enabled. + if w.chainStartDelay == 0 { + if err := w.processPastLogs(query); err != nil { + log.Errorf("Unable to process past logs %v", err) + return + } } defer logSub.Unsubscribe() defer headSub.Unsubscribe() diff --git a/beacon-chain/powchain/service_test.go b/beacon-chain/powchain/service_test.go index fa0234a9d..abc2a4bff 100644 --- a/beacon-chain/powchain/service_test.go +++ b/beacon-chain/powchain/service_test.go @@ -777,7 +777,7 @@ func TestProcessChainStartLog(t *testing.T) { testutil.AssertLogsDoNotContain(t, hook, "Unable to unpack ChainStart log data") testutil.AssertLogsDoNotContain(t, hook, "Receipt root from log doesn't match the root saved in memory") testutil.AssertLogsDoNotContain(t, hook, "Invalid timestamp from log") - testutil.AssertLogsContain(t, hook, "Minimum Number of Validators Reached for beacon-chain to start") + testutil.AssertLogsContain(t, hook, "Minimum number of validators reached for beacon-chain to start") hook.Reset() diff --git a/beacon-chain/utils/flags.go b/beacon-chain/utils/flags.go index c592c56b7..93a73b3a1 100644 --- a/beacon-chain/utils/flags.go +++ b/beacon-chain/utils/flags.go @@ -54,4 +54,10 @@ var ( Name: "enable-db-cleanup", Usage: "Enable automatic DB cleanup routine", } + // ChainStartDelay tells the beacon node to wait for a period of time from the current time, before + // logging chainstart. + ChainStartDelay = cli.Uint64Flag{ + Name: "chain-start-delay", + Usage: "Delay the chain start so as to make local testing easier", + } )