From 1fcb244b29467fcdb7972a724a1ace8b94a67eb8 Mon Sep 17 00:00:00 2001 From: David Date: Thu, 8 Jun 2023 14:30:53 +0800 Subject: [PATCH] feat(prover): check if a system proof has already been submitted by another system prover (#274) --- driver/state/state.go | 6 ----- metrics/metrics.go | 2 +- pkg/rpc/utils.go | 57 +++++++++++++++++++++++++++++++++++++++++++ prover/prover.go | 18 ++++++++++++++ 4 files changed, 76 insertions(+), 7 deletions(-) diff --git a/driver/state/state.go b/driver/state/state.go index 4ae0aaae3..81fd67f75 100644 --- a/driver/state/state.go +++ b/driver/state/state.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "fmt" - "math" "math/big" "sync/atomic" @@ -174,11 +173,6 @@ func (s *State) startSubscriptions(ctx context.Context) { } case e := <-s.blockVerifiedCh: log.Info("📈 Block verified", "blockID", e.Id, "hash", common.Hash(e.BlockHash), "reward", e.Reward) - if e.Reward > math.MaxInt64 { - metrics.DriverProofRewardGauge.Update(math.MaxInt64) - } else { - metrics.DriverProofRewardGauge.Update(int64(e.Reward)) - } case e := <-s.crossChainSynced: // Verify the protocol synced block, check if it exists in // L2 execution engine. diff --git a/metrics/metrics.go b/metrics/metrics.go index 025837d94..a534a36e7 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -21,7 +21,6 @@ var ( DriverL1CurrentHeightGauge = metrics.NewRegisteredGauge("driver/l1Current/height", nil) DriverL2HeadIDGauge = metrics.NewRegisteredGauge("driver/l2Head/id", nil) DriverL2VerifiedHeightGauge = metrics.NewRegisteredGauge("driver/l2Verified/id", nil) - DriverProofRewardGauge = metrics.NewRegisteredGauge("driver/proofReward", nil) // Proposer ProposerProposeEpochCounter = metrics.NewRegisteredCounter("proposer/epoch", nil) @@ -43,6 +42,7 @@ var ( ProverSentInvalidProofCounter = metrics.NewRegisteredCounter("prover/proof/invalid/sent", nil) ProverReceivedProposedBlockGauge = metrics.NewRegisteredGauge("prover/proposed/received", nil) ProverReceivedProvenBlockGauge = metrics.NewRegisteredGauge("prover/proven/received", nil) + ProverProofRewardGauge = metrics.NewRegisteredGauge("prover/proofReward", nil) ) // Serve starts the metrics server on the given address, will be closed when the given diff --git a/pkg/rpc/utils.go b/pkg/rpc/utils.go index 6fe9e5337..39b8e0e4c 100644 --- a/pkg/rpc/utils.go +++ b/pkg/rpc/utils.go @@ -111,6 +111,63 @@ func GetReceiptsByBlock(ctx context.Context, cli *rpc.Client, block *types.Block return receipts, nil } +// NeedNewSystemProof checks whether the L2 block still needs a new system proof. +func NeedNewSystemProof(ctx context.Context, cli *Client, id *big.Int, realProofSkipSize *big.Int) (bool, error) { + if realProofSkipSize == nil || realProofSkipSize.Uint64() <= 1 { + return false, nil + } + if id.Uint64()%realProofSkipSize.Uint64() == 0 { + log.Info( + "Skipping system block proof", + "blockID", id.Uint64(), + "skipSize", realProofSkipSize.Uint64(), + ) + + return false, nil + } + + var parent *types.Header + if id.Cmp(common.Big1) == 0 { + header, err := cli.L2.HeaderByNumber(ctx, common.Big0) + if err != nil { + return false, err + } + + parent = header + } else { + parentL1Origin, err := cli.WaitL1Origin(ctx, new(big.Int).Sub(id, common.Big1)) + if err != nil { + return false, err + } + + if parent, err = cli.L2.HeaderByHash(ctx, parentL1Origin.L2BlockHash); err != nil { + return false, err + } + } + + fc, err := cli.TaikoL1.GetForkChoice(nil, id, parent.Hash(), uint32(parent.GasUsed)) + if err != nil { + if !strings.Contains(encoding.TryParsingCustomError(err).Error(), "L1_FORK_CHOICE_NOT_FOUND") { + return false, encoding.TryParsingCustomError(err) + } + + return true, nil + } + + if fc.Prover == encoding.SystemProverAddress { + log.Info( + "📬 Block's system proof has already been submitted by another system prover", + "blockID", id, + "prover", fc.Prover, + "provenAt", fc.ProvenAt, + ) + + return false, nil + } + + return true, nil +} + // NeedNewProof checks whether the L2 block still needs a new proof. func NeedNewProof( ctx context.Context, diff --git a/prover/prover.go b/prover/prover.go index 0b2c5c585..2717b2c22 100644 --- a/prover/prover.go +++ b/prover/prover.go @@ -4,6 +4,7 @@ import ( "context" "crypto/ecdsa" "fmt" + "math" "math/big" "sync" "time" @@ -386,6 +387,17 @@ func (p *Prover) onBlockProposed( } } + if p.cfg.SystemProver { + needNewSystemProof, err := rpc.NeedNewSystemProof(ctx, p.rpc, event.Id, p.protocolConfigs.RealProofSkipSize) + if err != nil { + return fmt.Errorf("failed to check whether the L2 block needs a new system proof: %w", err) + } + + if !needNewSystemProof { + return nil + } + } + // Check if the current prover has seen this block ID before, there was probably // a L1 reorg, we need to cancel that reorged block's proof generation task at first. if p.currentBlocksBeingProven[event.Meta.Id] != nil { @@ -443,6 +455,12 @@ func (p *Prover) submitProofOp(ctx context.Context, proofWithHeader *proofProduc // the block being proven if it's verified. func (p *Prover) onBlockVerified(ctx context.Context, event *bindings.TaikoL1ClientBlockVerified) error { metrics.ProverLatestVerifiedIDGauge.Update(event.Id.Int64()) + if event.Reward > math.MaxInt64 { + metrics.ProverProofRewardGauge.Update(math.MaxInt64) + } else { + metrics.ProverProofRewardGauge.Update(int64(event.Reward)) + } + p.latestVerifiedL1Height = event.Raw.BlockNumber log.Info(