From c7db7419a66ffa3cfd21b28a32ac3a1528e09b48 Mon Sep 17 00:00:00 2001 From: David Date: Thu, 18 Apr 2024 16:25:27 +0800 Subject: [PATCH] feat(prover): use `--guardian.submissionDelay` flag (#730) --- cmd/flags/prover.go | 23 ++++++------- prover/event_handler/block_proposed.go | 38 +++++++++++++++++++-- prover/event_handler/block_proposed_test.go | 37 ++++++++++++++++++-- prover/init.go | 1 + 4 files changed, 81 insertions(+), 18 deletions(-) diff --git a/cmd/flags/prover.go b/cmd/flags/prover.go index 1740db935..715f16538 100644 --- a/cmd/flags/prover.go +++ b/cmd/flags/prover.go @@ -96,18 +96,6 @@ var ( Usage: "Minimum accepted fee for generating a SGX + zkVM proof", Category: proverCategory, } - // Guardian prover related. - GuardianProver = &cli.StringFlag{ - Name: "guardianProver", - Usage: "GuardianProver contract `address`", - Category: proverCategory, - } - GuardianProofSubmissionDelay = &cli.DurationFlag{ - Name: "guardian.submissionDelay", - Usage: "Guardian proof submission delay", - Value: 0 * time.Second, - Category: proverCategory, - } // Running mode ContesterMode = &cli.BoolFlag{ Name: "mode.contester", @@ -160,6 +148,17 @@ var ( Category: proverCategory, } // Guardian prover specific flag + GuardianProver = &cli.StringFlag{ + Name: "guardianProver", + Usage: "GuardianProver contract `address`", + Category: proverCategory, + } + GuardianProofSubmissionDelay = &cli.DurationFlag{ + Name: "guardian.submissionDelay", + Usage: "Guardian proof submission delay", + Value: 1 * time.Hour, + Category: proverCategory, + } EnableLivenessBondProof = &cli.BoolFlag{ Name: "prover.enableLivenessBondProof", Usage: "Toggles whether the proof is a dummy proof or returns keccak256(RETURN_LIVENESS_BOND) as proof", diff --git a/prover/event_handler/block_proposed.go b/prover/event_handler/block_proposed.go index ec382a582..0ed6ae77a 100644 --- a/prover/event_handler/block_proposed.go +++ b/prover/event_handler/block_proposed.go @@ -2,6 +2,7 @@ package handler import ( "context" + "crypto/rand" "errors" "fmt" "math/big" @@ -22,8 +23,9 @@ import ( ) var ( - errL1Reorged = errors.New("L1 reorged") - proofExpirationDelay = 1 * time.Minute + errL1Reorged = errors.New("L1 reorged") + proofExpirationDelay = 1 * time.Minute + submissionDelayRandomBumpRange float64 = 20 ) // BlockProposedEventHandler is responsible for handling the BlockProposed event as a prover. @@ -41,6 +43,7 @@ type BlockProposedEventHandler struct { contesterMode bool proveUnassignedBlocks bool tierToOverride uint16 + submissionDelay time.Duration } // NewBlockProposedEventHandlerOps is the options for creating a new BlockProposedEventHandler. @@ -57,6 +60,7 @@ type NewBlockProposedEventHandlerOps struct { BackOffMaxRetrys uint64 ContesterMode bool ProveUnassignedBlocks bool + SubmissionDelay time.Duration } // NewBlockProposedEventHandler creates a new BlockProposedEventHandler instance. @@ -75,6 +79,7 @@ func NewBlockProposedEventHandler(opts *NewBlockProposedEventHandlerOps) *BlockP opts.ContesterMode, opts.ProveUnassignedBlocks, 0, + opts.SubmissionDelay, } } @@ -216,6 +221,23 @@ func (h *BlockProposedEventHandler) checkL1Reorg( return nil } +// getRandomBumpedSubmissionDelay returns a random bumped submission delay. +func (h *BlockProposedEventHandler) getRandomBumpedSubmissionDelay() (time.Duration, error) { + if h.submissionDelay == 0 { + return h.submissionDelay, nil + } + + randomBump, err := rand.Int( + rand.Reader, + new(big.Int).SetUint64(uint64(h.submissionDelay.Seconds()*submissionDelayRandomBumpRange/100)), + ) + if err != nil { + return 0, err + } + + return time.Duration(h.submissionDelay.Seconds()+float64(randomBump.Uint64())) * time.Second, nil +} + // checkExpirationAndSubmitProof checks whether the proposed block's proving window is expired, // and submits a new proof if necessary. func (h *BlockProposedEventHandler) checkExpirationAndSubmitProof( @@ -311,6 +333,13 @@ func (h *BlockProposedEventHandler) checkExpirationAndSubmitProof( // The current prover is the assigned prover, or the proving window is expired, // try to submit a proof for this proposed block. tier := e.Meta.MinTier + + // Get a random bumped submission delay, if necessary. + submissionDelay, err := h.getRandomBumpedSubmissionDelay() + if err != nil { + return err + } + if h.tierToOverride != 0 { tier = h.tierToOverride } @@ -320,12 +349,15 @@ func (h *BlockProposedEventHandler) checkExpirationAndSubmitProof( "blockID", e.BlockId, "assignProver", e.AssignedProver, "minTier", e.Meta.MinTier, + "submissionDelay", submissionDelay, "tier", tier, ) metrics.ProverProofsAssigned.Add(1) - h.proofSubmissionCh <- &proofProducer.ProofRequestBody{Tier: tier, Event: e} + time.AfterFunc(submissionDelay, func() { + h.proofSubmissionCh <- &proofProducer.ProofRequestBody{Tier: tier, Event: e} + }) return nil } diff --git a/prover/event_handler/block_proposed_test.go b/prover/event_handler/block_proposed_test.go index 267d4d97e..99cf68e3e 100644 --- a/prover/event_handler/block_proposed_test.go +++ b/prover/event_handler/block_proposed_test.go @@ -26,10 +26,41 @@ func (s *EventHandlerTestSuite) TestBlockProposedHandle() { ContesterMode: true, ProveUnassignedBlocks: true, } - handler := NewBlockProposedEventHandler( - opts, - ) + handler := NewBlockProposedEventHandler(opts) e := s.ProposeAndInsertValidBlock(s.proposer, s.calldataSyncer) err := handler.Handle(context.Background(), e, func() {}) s.Nil(err) } + +func (s *EventHandlerTestSuite) TestGetRandomBumpedSubmissionDelay() { + opts := &NewBlockProposedEventHandlerOps{ + SharedState: &state.SharedState{}, + ProverAddress: common.Address{}, + GenesisHeightL1: 0, + RPC: s.RPCClient, + ProofGenerationCh: make(chan *proofProducer.ProofWithHeader), + AssignmentExpiredCh: make(chan *bindings.TaikoL1ClientBlockProposed), + ProofSubmissionCh: make(chan *proofProducer.ProofRequestBody), + ProofContestCh: make(chan *proofProducer.ContestRequestBody), + BackOffRetryInterval: 1 * time.Minute, + BackOffMaxRetrys: 5, + ContesterMode: true, + ProveUnassignedBlocks: true, + } + handler1 := NewBlockProposedEventHandler(opts) + + delay, err := handler1.getRandomBumpedSubmissionDelay() + s.Nil(err) + s.Zero(delay) + + opts.SubmissionDelay = 1 * time.Hour + handler2 := NewBlockProposedEventHandler(opts) + delay, err = handler2.getRandomBumpedSubmissionDelay() + s.Nil(err) + s.NotZero(delay) + s.Greater(delay.Seconds(), opts.SubmissionDelay.Seconds()) + s.Less( + delay.Seconds(), + opts.SubmissionDelay.Seconds()*(1+(submissionDelayRandomBumpRange/100)), + ) +} diff --git a/prover/init.go b/prover/init.go index 389d0dc92..0fc7a2a2d 100644 --- a/prover/init.go +++ b/prover/init.go @@ -209,6 +209,7 @@ func (p *Prover) initEventHandlers() { ProveUnassignedBlocks: p.cfg.ProveUnassignedBlocks, } if p.IsGuardianProver() { + opts.SubmissionDelay = p.cfg.GuardianProofSubmissionDelay p.blockProposedHandler = handler.NewBlockProposedEventGuardianHandler( &handler.NewBlockProposedGuardianEventHandlerOps{ NewBlockProposedEventHandlerOps: opts,