From e9427f7870be6d168bcfc52d657fd1d0d4739c04 Mon Sep 17 00:00:00 2001 From: Michael de Hoog Date: Wed, 6 Nov 2024 10:12:25 -1000 Subject: [PATCH] Proof aggregation improvements (#14) * Only clear pending proofs if the enclave returns an error * Only generate batchSize proofs before aggregating * Tiny logging improvement * Fix count off-by-1 --- op-proposer/proposer/driver.go | 49 +++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/op-proposer/proposer/driver.go b/op-proposer/proposer/driver.go index 83108fd..1bf1a2a 100644 --- a/op-proposer/proposer/driver.go +++ b/op-proposer/proposer/driver.go @@ -18,6 +18,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" ) const aggregateBatchSize = 1000 @@ -257,18 +258,20 @@ func (l *L2OutputSubmitter) generateOutputs(ctx context.Context, latestOutput bi } } - for i := latestOutputNumber + 1; ; i++ { - block, err := l.L2Client.BlockByNumber(ctx, new(big.Int).SetUint64(i)) + // calculate `aggregateBatchSize` proofs at once, which are then aggregated in `nextOutput` + for i := uint64(0); i < aggregateBatchSize; i++ { + number := i + latestOutputNumber + 1 + block, err := l.L2Client.BlockByNumber(ctx, new(big.Int).SetUint64(number)) if errors.Is(err, ethereum.NotFound) { - return nil + break } if err != nil { - return fmt.Errorf("failed to get block %d: %w", i, err) + return fmt.Errorf("failed to get block %d: %w", number, err) } proposal, err := l.prover.Generate(ctx, block) if err != nil { - return fmt.Errorf("failed to generate proof for block %d: %w", i, err) + return fmt.Errorf("failed to generate proof for block %d: %w", number, err) } l.Log.Info("Generated proof for block", @@ -276,6 +279,8 @@ func (l *L2OutputSubmitter) generateOutputs(ctx context.Context, latestOutput bi "withdrawals", proposal.Withdrawals, "output", proposal.Output.OutputRoot.String()) l.pending = append(l.pending, proposal) } + + return nil } func (l *L2OutputSubmitter) nextOutput(ctx context.Context, latestOutput bindings.TypesOutputProposal) (*Proposal, bool, error) { @@ -285,32 +290,34 @@ func (l *L2OutputSubmitter) nextOutput(ctx context.Context, latestOutput binding return nil, false, err } - var proposals []*Proposal - for _, proposal := range l.pending { - if proposal.To.Number > latestSafe.Number { - break - } - proposals = append(proposals, proposal) + count := 0 + for count < len(l.pending) && l.pending[count].To.Number < latestSafe.Number { + count++ } - if len(proposals) == 0 { + if count <= 0 { return nil, false, nil } - l.pending = l.pending[len(proposals):] - for len(proposals) > 1 { - batchLength := min(len(proposals), aggregateBatchSize) - batch := proposals[:batchLength] + for count > 1 { + batchLength := min(count, aggregateBatchSize) + batch := l.pending[:batchLength] aggregated, err := l.prover.Aggregate(ctx, latestOutput.OutputRoot, batch) if err != nil { - return nil, false, fmt.Errorf("failed to aggregate proofs: %w", err) + var rpcError rpc.Error + if errors.As(err, &rpcError) { + // if we received an explicit error from the enclave (like "invalid signer"), clear the pending proofs + l.Log.Warn("Non-recoverable error aggregating proofs", "err", err) + l.pending = nil + } + return nil, false, err } + l.pending = append([]*Proposal{aggregated}, l.pending[batchLength:]...) + count -= batchLength - 1 l.Log.Info("Aggregated proofs", - "output", aggregated.Output.OutputRoot.String(), "blocks", batchLength, "remaining", len(proposals), + "output", aggregated.Output.OutputRoot.String(), "blocks", batchLength, "remaining", count-1, "withdrawals", aggregated.Withdrawals, "from", aggregated.From.Number, "to", aggregated.To.Number) - proposals = append([]*Proposal{aggregated}, proposals[batchLength:]...) } - proposal := proposals[0] - l.pending = append([]*Proposal{proposal}, l.pending...) + proposal := l.pending[0] if proposal.To.Hash != latestSafe.Hash { l.Log.Warn("Aggregated output does not match the latest batched block, possible reorg",