Skip to content

Commit

Permalink
enhance(l1-info-sync): sync l1 info table from l2 rpc id an rpc node
Browse files Browse the repository at this point in the history
enhance(l1-info-sync): l2 syncer wip

enhance(l1-info-sync): l2 syncer
  • Loading branch information
elliothllm committed Jan 30, 2025
1 parent 2a22c67 commit c068e1e
Show file tree
Hide file tree
Showing 12 changed files with 379 additions and 14 deletions.
10 changes: 10 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,16 @@ var (
Name: "zkevm.genesis-config-path",
Usage: "File path for the zk config containing allocs, chainspec, and other zk specific configurations.",
}
L2InfoTreeUpdatesBatchSize = cli.Uint64Flag{
Name: "zkevm.l2-info-tree-updates-batch-size",
Usage: "Size of the batch of L2 info tree updates to retrieve at a time. L2 info tree updates must be enabled to use this.",
Value: 500,
}
L2InfoTreeUpdatesEnabled = cli.BoolFlag{
Name: "zkevm.l2-info-tree-updates-enabled",
Usage: "When enabled a RPC node can use the L2 to build the InfoTree.",
Value: false,
}
ACLPrintHistory = cli.IntFlag{
Name: "acl.print-history",
Usage: "Number of entries to print from the ACL history on node start up",
Expand Down
2 changes: 1 addition & 1 deletion eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,7 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger
cfg.L1HighestBlockType,
)

l1InfoTreeUpdater := l1infotree.NewUpdater(cfg.Zk, l1InfoTreeSyncer)
l1InfoTreeUpdater := l1infotree.NewUpdater(cfg.Zk, l1InfoTreeSyncer, l1infotree.NewL2InfoTreeSyncer(ctx, cfg.Zk))

var dataStreamServer server.DataStreamServer
if backend.streamServer != nil {
Expand Down
2 changes: 2 additions & 0 deletions eth/ethconfig/config_zkevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ type Zk struct {
BadTxAllowance uint64
BadTxStoreValue uint64
BadTxPurge bool
L2InfoTreeUpdatesBatchSize uint64
L2InfoTreeUpdatesEnabled bool
}

var DefaultZkConfig = &Zk{}
Expand Down
2 changes: 2 additions & 0 deletions turbo/cli/default_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,8 @@ var DefaultFlags = []cli.Flag{
&utils.PanicOnReorg,
&utils.ShadowSequencer,
&utils.ZKGenesisConfigPathFlag,
&utils.L2InfoTreeUpdatesBatchSize,
&utils.L2InfoTreeUpdatesEnabled,

&utils.SilkwormExecutionFlag,
&utils.SilkwormRpcDaemonFlag,
Expand Down
2 changes: 2 additions & 0 deletions turbo/cli/flags_zkevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,8 @@ func ApplyFlagsForZkConfig(ctx *cli.Context, cfg *ethconfig.Config) {
BadTxAllowance: ctx.Uint64(utils.BadTxAllowance.Name),
BadTxStoreValue: ctx.Uint64(utils.BadTxStoreValue.Name),
BadTxPurge: ctx.Bool(utils.BadTxPurge.Name),
L2InfoTreeUpdatesBatchSize: ctx.Uint64(utils.L2InfoTreeUpdatesBatchSize.Name),
L2InfoTreeUpdatesEnabled: ctx.Bool(utils.L2InfoTreeUpdatesEnabled.Name),
}

utils2.EnableTimer(cfg.DebugTimers)
Expand Down
15 changes: 13 additions & 2 deletions turbo/jsonrpc/zkevm_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ type ZkEvmAPI interface {
GetL2BlockInfoTree(ctx context.Context, blockNum rpc.BlockNumberOrHash) (json.RawMessage, error)
EstimateCounters(ctx context.Context, argsOrNil *zkevmRPCTransaction) (json.RawMessage, error)
GetBatchCountersByNumber(ctx context.Context, batchNumRpc rpc.BlockNumber) (res json.RawMessage, err error)
GetExitRootTable(ctx context.Context) ([]l1InfoTreeData, error)
GetExitRootTable(ctx context.Context, argsOrNil *zkevmRPCExitRootTableArgs) ([]l1InfoTreeData, error)
GetVersionHistory(ctx context.Context) (json.RawMessage, error)
GetForkId(ctx context.Context) (hexutil.Uint64, error)
GetForkById(ctx context.Context, forkId hexutil.Uint64) (res json.RawMessage, err error)
Expand Down Expand Up @@ -1246,6 +1246,11 @@ func (api *ZkEvmAPIImpl) GetVersionHistory(ctx context.Context) (json.RawMessage
return versionsJson, nil
}

type zkevmRPCExitRootTableArgs struct {
From *uint64 `json:"from"`
To *uint64 `json:"to"`
}

type l1InfoTreeData struct {
Index uint64 `json:"index"`
Ger common.Hash `json:"ger"`
Expand All @@ -1257,7 +1262,7 @@ type l1InfoTreeData struct {
BlockNumber uint64 `json:"block_number"`
}

func (api *ZkEvmAPIImpl) GetExitRootTable(ctx context.Context) ([]l1InfoTreeData, error) {
func (api *ZkEvmAPIImpl) GetExitRootTable(ctx context.Context, argsOrNil *zkevmRPCExitRootTableArgs) ([]l1InfoTreeData, error) {
tx, err := api.db.BeginRo(ctx)
if err != nil {
return nil, err
Expand All @@ -1274,6 +1279,9 @@ func (api *ZkEvmAPIImpl) GetExitRootTable(ctx context.Context) ([]l1InfoTreeData
var result []l1InfoTreeData

var idx uint64 = 1
if argsOrNil != nil && argsOrNil.From != nil {
idx = *argsOrNil.From
}
for {
info, err := hermezDb.GetL1InfoTreeUpdate(idx)
if err != nil {
Expand All @@ -1294,6 +1302,9 @@ func (api *ZkEvmAPIImpl) GetExitRootTable(ctx context.Context) ([]l1InfoTreeData
}
result = append(result, data)
idx++
if argsOrNil != nil && argsOrNil.To != nil && idx > *argsOrNil.To {
break
}
}

return result, nil
Expand Down
122 changes: 122 additions & 0 deletions zk/l1infotree/l2_info_tree_syncer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package l1infotree

import (
"context"
"encoding/json"
"github.com/ledgerwatch/erigon/eth/ethconfig"
zkTypes "github.com/ledgerwatch/erigon/zk/types"
jsonClient "github.com/ledgerwatch/erigon/zkevm/jsonrpc/client"
"github.com/ledgerwatch/log/v3"
"sync/atomic"
"time"
)

const (
EXIT_ROOT_TABLE = "zkevm_getExitRootTable"
)

type L2InfoTreeSyncer struct {
ctx context.Context
zkCfg *ethconfig.Zk
isSyncStarted atomic.Bool
isSyncFinished atomic.Bool
infoTreeChan chan []zkTypes.L1InfoTreeUpdate
}

func NewL2InfoTreeSyncer(ctx context.Context, zkCfg *ethconfig.Zk) *L2InfoTreeSyncer {
return &L2InfoTreeSyncer{
ctx: ctx,
zkCfg: zkCfg,
infoTreeChan: make(chan []zkTypes.L1InfoTreeUpdate),
}
}

func (s *L2InfoTreeSyncer) IsSyncStarted() bool {
return s.isSyncStarted.Load()
}

func (s *L2InfoTreeSyncer) IsSyncFinished() bool {
return s.isSyncFinished.Load()
}

func (s *L2InfoTreeSyncer) GetInfoTreeChan() chan []zkTypes.L1InfoTreeUpdate {
return s.infoTreeChan
}

func (s *L2InfoTreeSyncer) ConsumeInfoTree() {
for {
select {
case <-s.ctx.Done():
return
case <-s.infoTreeChan:
default:
if !s.isSyncStarted.Load() {
return
}
time.Sleep(time.Second)
}
}
}

func (s *L2InfoTreeSyncer) RunSyncInfoTree() {
if s.isSyncStarted.Load() {
return
}
s.isSyncStarted.Store(true)
s.isSyncFinished.Store(false)

totalSynced := uint64(0)
batchSize := s.zkCfg.L2InfoTreeUpdatesBatchSize

go func() {
retry := 0
for {
select {
case <-s.ctx.Done():
s.isSyncFinished.Store(true)
break
default:
query := exitRootQuery{
From: totalSynced + 1,
To: totalSynced + batchSize,
}
infoTree, err := getExitRootTable(s.zkCfg.L2RpcUrl, query)
if err != nil {
log.Debug("getExitRootTable retry error", "err", err)
retry++
if retry > 5 {
return
}
time.Sleep(time.Duration(retry*2) * time.Second)
}

if len(infoTree) == 0 {
s.isSyncFinished.Store(true)
return
}

s.infoTreeChan <- infoTree
totalSynced = query.To
}
}
}()
}

type exitRootQuery struct {
From uint64 `json:"from"`
To uint64 `json:"to"`
}

func getExitRootTable(endpoint string, query exitRootQuery) ([]zkTypes.L1InfoTreeUpdate, error) {
res, err := jsonClient.JSONRPCCall(endpoint, EXIT_ROOT_TABLE, query)
if err != nil {
return nil, err
}

var updates []zkTypes.L1InfoTreeUpdate
if err = json.Unmarshal(res.Result, &updates); err != nil {
return nil, err
}

return updates, nil
}
Loading

0 comments on commit c068e1e

Please sign in to comment.