Skip to content
This repository has been archived by the owner on May 11, 2024. It is now read-only.

Commit

Permalink
feat(prover): add getProvingWindow
Browse files Browse the repository at this point in the history
  • Loading branch information
davidtaikocha committed Oct 6, 2023
1 parent e3dd1bf commit 4dd63c3
Showing 1 changed file with 67 additions and 60 deletions.
127 changes: 67 additions & 60 deletions prover/prover.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ import (
)

var (
errNoCapacity = errors.New("no prover capacity available")
errNoCapacity = errors.New("no prover capacity available")
errTierNotFound = errors.New("tier not found")
)

// Prover keep trying to prove new proposed blocks valid/invalid.
Expand Down Expand Up @@ -60,13 +61,14 @@ type Prover struct {
validProofSubmitter proofSubmitter.ProofSubmitter

// Subscriptions
blockProposedCh chan *bindings.TaikoL1ClientBlockProposed
blockProposedSub event.Subscription
transitionProvedCh chan *bindings.TaikoL1ClientTransitionProved
transitionProvedSub event.Subscription
blockVerifiedCh chan *bindings.TaikoL1ClientBlockVerified
blockVerifiedSub event.Subscription
proveNotify chan struct{}
blockProposedCh chan *bindings.TaikoL1ClientBlockProposed
blockProposedSub event.Subscription
transitionProvedCh chan *bindings.TaikoL1ClientTransitionProved
transitionProvedSub event.Subscription
blockVerifiedCh chan *bindings.TaikoL1ClientBlockVerified
blockVerifiedSub event.Subscription
proofWindowExpiredCh chan *bindings.TaikoL1ClientBlockProposed
proveNotify chan struct{}

// Proof related
proofGenerationCh chan *proofProducer.ProofWithHeader
Expand Down Expand Up @@ -130,6 +132,7 @@ func InitFromConfig(ctx context.Context, p *Prover, cfg *Config) (err error) {
p.blockVerifiedCh = make(chan *bindings.TaikoL1ClientBlockVerified, chBufferSize)
p.transitionProvedCh = make(chan *bindings.TaikoL1ClientTransitionProved, chBufferSize)
p.proofGenerationCh = make(chan *proofProducer.ProofWithHeader, chBufferSize)
p.proofWindowExpiredCh = make(chan *bindings.TaikoL1ClientBlockProposed, chBufferSize)
p.proveNotify = make(chan struct{}, 1)
if err := p.initL1Current(cfg.StartingBlockID); err != nil {
return fmt.Errorf("initialize L1 current cursor error: %w", err)
Expand Down Expand Up @@ -442,55 +445,49 @@ func (p *Prover) onBlockProposed(
"minTier", event.MinTier,
)

// TODO: add this back
// if p.cfg.GuardianProver {
// shouldSkipProofWindowExpiredCheck := func() (bool, error) {
// parent, err := p.rpc.L2ParentByBlockId(ctx, event.BlockId)
// if err != nil {
// return false, err
// }

// // check if an invalid proof has been submitted, if so, we can skip proofWindowExpired check below
// // and always submit proof. otherwise, guardianProver follows same proof logic as regular.
// transition, err := p.rpc.TaikoL1.GetTransition(
// &bind.CallOpts{Context: ctx},
// event.BlockId.Uint64(),
// parent.Hash(),
// )
// if err != nil {
// if strings.Contains(encoding.TryParsingCustomError(err).Error(), "L1_TRANSITION_NOT_FOUND") {
// // proof hasnt been submitted
// return false, nil
// } else {
// return false, err
// }
// }

// block, err := p.rpc.L2.BlockByNumber(ctx, event.BlockId)
// if err != nil {
// return false, err
// }

// // proof is invalid but has correct parents, guardian prover should skip
// // checking proofWindow expired, and simply force prove.
// if transition.BlockHash != block.Hash() {
// log.Info(
// "Guardian prover forcing prove block due to invalid proof",
// "blockID", event.BlockId,
// "transitionBlockHash", common.BytesToHash(transition.BlockHash[:]).Hex(),
// "expectedBlockHash", block.Hash().Hex(),
// )

// return true, nil
// }

// return false, nil
// }

// if skipProofWindowExpiredCheck, err = shouldSkipProofWindowExpiredCheck(); err != nil {
// return err
// }
// }
provingWindow, err := p.getProvingWindow(event)
if err != nil {
return fmt.Errorf("failed to get proving window: %w", err)
}

var (
now = uint64(time.Now().Unix())
provingWindowExpiresAt = currentL1OriginHeader.Time + uint64(provingWindow.Seconds())
provingWindowExpired = now > provingWindowExpiresAt
timeToExpire = time.Duration(provingWindowExpiresAt-now) * time.Second
)
if event.AssignedProver != p.proverAddress && !provingWindowExpired {
log.Info(
"Proposed block is not provable",
"blockID", event.BlockId,
"prover", event.AssignedProver,
"expiresAt", provingWindowExpiresAt,
"timeToExpire", timeToExpire,
)

if p.cfg.ProveUnassignedBlocks {
log.Info("Add proposed block to wait for proof window expiration", "blockID", event.BlockId)
time.AfterFunc(timeToExpire, func() { p.proofWindowExpiredCh <- event })
}

return nil
}

// If set not to prove unassigned blocks, this block is still not provable
// by us even though its open proving.
if provingWindowExpired && !p.cfg.ProveUnassignedBlocks {
log.Info("Skip proving expired blocks", "blockID", event.BlockId)
return nil
}

log.Info(
"Proposed block is provable",
"blockID", event.BlockId,
"prover", event.AssignedProver,
"expiresAt", provingWindowExpiresAt,
)

metrics.ProverProofsAssigned.Inc(1)

if !p.cfg.GuardianProver {
if _, ok := p.capacityManager.TakeOneCapacity(event.BlockId.Uint64()); !ok {
Expand Down Expand Up @@ -649,8 +646,7 @@ func (p *Prover) closeSubscription() {
p.blockProposedSub.Unsubscribe()
}

// isValidProof cancels proof only if the parentGasUsed and parentHash in the proof match what
// is expected
// isValidProof checks if the given proof is a valid one.
func (p *Prover) isValidProof(
ctx context.Context,
blockID uint64,
Expand Down Expand Up @@ -726,7 +722,7 @@ func (p *Prover) requestProofByBlockID(blockId *big.Int, l1Height *big.Int) erro
return nil
}

// make sure to takea capacity before requesting proof
// Make sure to take a capacity before requesting proof
if !p.cfg.GuardianProver {
if _, ok := p.capacityManager.TakeOneCapacity(event.BlockId.Uint64()); !ok {
return errNoCapacity
Expand Down Expand Up @@ -767,3 +763,14 @@ func (p *Prover) requestProofByBlockID(blockId *big.Int, l1Height *big.Int) erro

return nil
}

// getProvingWindow returns the provingWindow of the given proposed block.
func (p *Prover) getProvingWindow(e *bindings.TaikoL1ClientBlockProposed) (time.Duration, error) {
for _, t := range p.tiers {
if e.MinTier == t.ID {
return time.Duration(t.ProvingWindow) * time.Second, nil
}
}

return 0, errTierNotFound
}

0 comments on commit 4dd63c3

Please sign in to comment.