From 6999b4024ee59d5bdf2c0c2ce4a0b7a6ca128a99 Mon Sep 17 00:00:00 2001 From: David Date: Mon, 6 Mar 2023 00:37:52 +0800 Subject: [PATCH] feat(prover): ensure L2 EE is fully synced when calling `initL1Current` --- pkg/rpc/methods.go | 37 +++++++++++++++++++++++++++++++++++++ proposer/proposer.go | 39 +-------------------------------------- prover/prover.go | 4 ++++ 3 files changed, 42 insertions(+), 38 deletions(-) diff --git a/pkg/rpc/methods.go b/pkg/rpc/methods.go index e428b0a72..a57037b1c 100644 --- a/pkg/rpc/methods.go +++ b/pkg/rpc/methods.go @@ -2,10 +2,12 @@ package rpc import ( "context" + "errors" "fmt" "math/big" "time" + "github.com/cenkalti/backoff/v4" ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -17,6 +19,14 @@ import ( "golang.org/x/sync/errgroup" ) +var ( + // errSyncing is returned when the L2 execution engine is syncing. + errSyncing = errors.New("syncing") + // syncProgressRecheckDelay is the time delay of rechecking the L2 execution engine's sync progress again, + // if the previous check failed. + syncProgressRecheckDelay = 12 * time.Second +) + // ensureGenesisMatched fetches the L2 genesis block from TaikoL1 contract, // and checks whether the fetched genesis is same to the node local genesis. func (c *Client) ensureGenesisMatched(ctx context.Context) error { @@ -60,6 +70,33 @@ func (c *Client) ensureGenesisMatched(ctx context.Context) error { return fmt.Errorf("genesis block not found in TaikoL1") } +// WaitTillL2Synced keeps waiting until the L2 execution engine is fully synced. +func (c *Client) WaitTillL2Synced(ctx context.Context) error { + return backoff.Retry( + func() error { + if ctx.Err() != nil { + return nil + } + progress, err := c.L2ExecutionEngineSyncProgress(ctx) + if err != nil { + log.Error("Fetch L2 execution engine sync progress error", "error", err) + return err + } + + if progress.SyncProgress != nil || + progress.CurrentBlockID == nil || + progress.HighestBlockID == nil || + progress.CurrentBlockID.Cmp(progress.HighestBlockID) < 0 { + log.Info("L2 execution engine is syncing", "progress", progress) + return errSyncing + } + + return nil + }, + backoff.NewConstantBackOff(syncProgressRecheckDelay), + ) +} + // LatestL2KnownL1Header fetches the L2 execution engine's latest known L1 header. func (c *Client) LatestL2KnownL1Header(ctx context.Context) (*types.Header, error) { headL1Origin, err := c.L2.HeadL1Origin(ctx) diff --git a/proposer/proposer.go b/proposer/proposer.go index a45963c2d..8406c3c17 100644 --- a/proposer/proposer.go +++ b/proposer/proposer.go @@ -3,14 +3,12 @@ package proposer import ( "context" "crypto/ecdsa" - "errors" "fmt" "math/big" "math/rand" "sync" "time" - "github.com/cenkalti/backoff/v4" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -25,14 +23,6 @@ import ( "github.com/urfave/cli/v2" ) -var ( - // errSyncing is returned when the L2 execution engine is syncing. - errSyncing = errors.New("syncing") - // syncProgressRecheckDelay is the time delay of rechecking the L2 execution engine's sync progress again, - // if the previous check failed. - syncProgressRecheckDelay = 12 * time.Second -) - // Proposer keep proposing new transactions from L2 execution engine's tx pool at a fixed interval. type Proposer struct { // RPC clients @@ -146,7 +136,7 @@ func (p *Proposer) ProposeOp(ctx context.Context) error { } // Wait until L2 execution engine is synced at first. - if err := p.waitTillSynced(ctx); err != nil { + if err := p.rpc.WaitTillL2Synced(ctx); err != nil { return fmt.Errorf("failed to wait until L2 execution engine synced: %w", err) } @@ -310,33 +300,6 @@ func (p *Proposer) ProposeTxList( return nil } -// waitTillSynced keeps waiting until the L2 execution engine is fully synced. -func (p *Proposer) waitTillSynced(ctx context.Context) error { - return backoff.Retry( - func() error { - if ctx.Err() != nil { - return nil - } - progress, err := p.rpc.L2ExecutionEngineSyncProgress(p.ctx) - if err != nil { - log.Error("Fetch L2 execution engine sync progress error", "error", err) - return err - } - - if progress.SyncProgress != nil || - progress.CurrentBlockID == nil || - progress.HighestBlockID == nil || - progress.CurrentBlockID.Cmp(progress.HighestBlockID) < 0 { - log.Info("L2 execution engine is syncing", "progress", progress) - return errSyncing - } - - return nil - }, - backoff.NewConstantBackOff(syncProgressRecheckDelay), - ) -} - // updateProposingTicker updates the internal proposing timer. func (p *Proposer) updateProposingTicker() { if p.proposingTimer != nil { diff --git a/prover/prover.go b/prover/prover.go index 686649278..594c9b8b9 100644 --- a/prover/prover.go +++ b/prover/prover.go @@ -354,6 +354,10 @@ func (p *Prover) Name() string { // initL1Current initializes prover's L1Current cursor. func (p *Prover) initL1Current(startingBlockID *big.Int) error { + if err := p.rpc.WaitTillL2Synced(p.ctx); err != nil { + return err + } + if startingBlockID == nil { stateVars, err := p.rpc.GetProtocolStateVariables(nil) if err != nil {