Skip to content

Commit

Permalink
Eagerly compute witness when sequencing
Browse files Browse the repository at this point in the history
Before this change, the witness of a batch is computed only right before being sent to an executor. This mechanism can result in a longer time in chain unwinding if the witness to be computed is far away from the head. We can resolve this problem by alway eagerly computing the witness when a batch is closed, without delaying to the verification promise and therefore avoid chain unwinding overall.
  • Loading branch information
cffls committed Oct 15, 2024
1 parent 396cd19 commit 0d66b3f
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 14 deletions.
30 changes: 18 additions & 12 deletions zk/legacy_executor_verifier/legacy_executor_verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package legacy_executor_verifier

import (
"context"
"encoding/hex"
"sync"
"sync/atomic"
"time"

"encoding/hex"
"errors"
"fmt"
"strconv"
Expand Down Expand Up @@ -35,13 +35,14 @@ type VerifierRequest struct {
Counters map[string]int
creationTime time.Time
timeout time.Duration
witness []byte
}

func NewVerifierRequest(forkId, batchNumber uint64, blockNumbers []uint64, stateRoot common.Hash, counters map[string]int) *VerifierRequest {
return NewVerifierRequestWithTimeout(forkId, batchNumber, blockNumbers, stateRoot, counters, 0)
func NewVerifierRequest(forkId, batchNumber uint64, blockNumbers []uint64, stateRoot common.Hash, counters map[string]int, witness []byte) *VerifierRequest {
return NewVerifierRequestWithTimeout(forkId, batchNumber, blockNumbers, stateRoot, counters, 0, witness)
}

func NewVerifierRequestWithTimeout(forkId, batchNumber uint64, blockNumbers []uint64, stateRoot common.Hash, counters map[string]int, timeout time.Duration) *VerifierRequest {
func NewVerifierRequestWithTimeout(forkId, batchNumber uint64, blockNumbers []uint64, stateRoot common.Hash, counters map[string]int, timeout time.Duration, witness []byte) *VerifierRequest {
return &VerifierRequest{
BatchNumber: batchNumber,
BlockNumbers: blockNumbers,
Expand All @@ -50,6 +51,7 @@ func NewVerifierRequestWithTimeout(forkId, batchNumber uint64, blockNumbers []ui
Counters: counters,
creationTime: time.Now(),
timeout: timeout,
witness: witness,
}
}

Expand Down Expand Up @@ -138,10 +140,11 @@ func (v *LegacyExecutorVerifier) StartAsyncVerification(
blockNumbers []uint64,
useRemoteExecutor bool,
requestTimeout time.Duration,
witness []byte,
) {
var promise *Promise[*VerifierBundle]

request := NewVerifierRequestWithTimeout(forkId, batchNumber, blockNumbers, stateRoot, counters, requestTimeout)
request := NewVerifierRequestWithTimeout(forkId, batchNumber, blockNumbers, stateRoot, counters, requestTimeout, witness)
if useRemoteExecutor {
promise = v.VerifyAsync(request)
} else {
Expand Down Expand Up @@ -238,12 +241,15 @@ func (v *LegacyExecutorVerifier) VerifyAsync(request *VerifierRequest) *Promise[
return verifierBundle, err
}

witness, err := v.WitnessGenerator.GetWitnessByBlockRange(tx, innerCtx, blockNumbers[0], blockNumbers[len(blockNumbers)-1], false, v.cfg.WitnessFull)
if err != nil {
return verifierBundle, err
}
if request.witness == nil {
witness, err := v.WitnessGenerator.GetWitnessByBlockRange(tx, innerCtx, blockNumbers[0], blockNumbers[len(blockNumbers)-1], false, v.cfg.WitnessFull)
if err != nil {
return verifierBundle, err
}

log.Debug("witness generated", "data", hex.EncodeToString(witness))
log.Debug("witness generated", "data", hex.EncodeToString(witness))
request.witness = witness
}

// now we need to figure out the timestamp limit for this payload. It must be:
// timestampLimit >= currentTimestamp (from batch pre-state) + deltaTimestamp
Expand All @@ -258,7 +264,7 @@ func (v *LegacyExecutorVerifier) VerifyAsync(request *VerifierRequest) *Promise[
oldAccInputHash := common.HexToHash("0x0")
timestampLimit := lastBlock.Time()
payload := &Payload{
Witness: witness,
Witness: request.witness,
DataStream: streamBytes,
Coinbase: v.cfg.AddressSequencer.String(),
OldAccInputHash: oldAccInputHash.Bytes(),
Expand Down Expand Up @@ -291,7 +297,7 @@ func (v *LegacyExecutorVerifier) VerifyAsync(request *VerifierRequest) *Promise[

verifierBundle.Response = &VerifierResponse{
Valid: ok,
Witness: witness,
Witness: request.witness,
ExecutorResponse: executorResponse,
Error: executorErr,
}
Expand Down
8 changes: 7 additions & 1 deletion zk/stages/stage_sequence_execute.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,13 @@ func sequencingBatchStep(
if err != nil {
return err
}
cfg.legacyVerifier.StartAsyncVerification(batchContext.s.LogPrefix(), batchState.forkId, batchState.batchNumber, block.Root(), counters.UsedAsMap(), batchState.builtBlocks, useExecutorForVerification, batchContext.cfg.zk.SequencerBatchVerificationTimeout)

witness, err := cfg.legacyVerifier.WitnessGenerator.GetWitnessByBlockRange(sdb.tx, ctx, batchState.builtBlocks[0], batchState.builtBlocks[len(batchState.builtBlocks)-1], false, cfg.zk.WitnessFull)
if err != nil {
return err
}

cfg.legacyVerifier.StartAsyncVerification(batchContext.s.LogPrefix(), batchState.forkId, batchState.batchNumber, block.Root(), counters.UsedAsMap(), batchState.builtBlocks, useExecutorForVerification, batchContext.cfg.zk.SequencerBatchVerificationTimeout, witness)

// check for new responses from the verifier
needsUnwind, err := updateStreamAndCheckRollback(batchContext, batchState, streamWriter, u)
Expand Down
2 changes: 1 addition & 1 deletion zk/txpool/pool_zk_limbo_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func (_this *LimboSubPoolProcessor) run() {

for i, limboBlock := range limboBlocksDetails {
for _, limboTx := range limboBlock.Transactions {
request := legacy_executor_verifier.NewVerifierRequest(limboBlock.ForkId, limboBlock.BatchNumber, []uint64{limboBlock.BlockNumber}, limboTx.Root, unlimitedCounters)
request := legacy_executor_verifier.NewVerifierRequest(limboBlock.ForkId, limboBlock.BatchNumber, []uint64{limboBlock.BlockNumber}, limboTx.Root, unlimitedCounters, nil)
err := _this.verifier.VerifySync(tx, request, limboBlock.Witness, limboTx.StreamBytes, limboBlock.BlockTimestamp, limboBlock.L1InfoTreeMinTimestamps)
if err != nil {
idHash := hexutils.BytesToHex(limboTx.Hash[:])
Expand Down

0 comments on commit 0d66b3f

Please sign in to comment.