@@ -4,9 +4,11 @@ import (
44 "context"
55 "errors"
66 "fmt"
7+ "slices"
78 "sync/atomic"
89
910 "github.com/ethereum/go-ethereum/common"
11+ "github.com/ethereum/go-ethereum/common/hexutil"
1012 "github.com/ethereum/go-ethereum/log"
1113
1214 "github.com/ethereum-optimism/optimism/op-service/client"
@@ -45,6 +47,7 @@ type SupervisorBackend struct {
4547 // crossProcessors are used to index cross-chain dependency validity data once the log events are indexed
4648 crossSafeProcessors locks.RWMap [types.ChainID , * cross.Worker ]
4749 crossUnsafeProcessors locks.RWMap [types.ChainID , * cross.Worker ]
50+ syncSources locks.RWMap [types.ChainID , syncnode.SyncSource ]
4851
4952 // syncNodesController controls the derivation or reset of the sync nodes
5053 syncNodesController * syncnode.SyncNodesController
@@ -151,6 +154,10 @@ func (su *SupervisorBackend) initResources(ctx context.Context, cfg *config.Conf
151154 chainProcessor := processors .NewChainProcessor (su .logger , chainID , logProcessor , su .chainDBs , su .onIndexedLocalUnsafeData )
152155 su .chainProcessors .Set (chainID , chainProcessor )
153156 }
157+ // initialize sync sources
158+ for _ , chainID := range chains {
159+ su .syncSources .Set (chainID , nil )
160+ }
154161
155162 if cfg .L1RPC != "" {
156163 if err := su .attachL1RPC (ctx , cfg .L1RPC ); err != nil {
@@ -251,6 +258,10 @@ func (su *SupervisorBackend) AttachSyncNode(ctx context.Context, src syncnode.Sy
251258 if err != nil {
252259 return nil , fmt .Errorf ("failed to attach sync source to processor: %w" , err )
253260 }
261+ err = su .AttachSyncSource (chainID , src )
262+ if err != nil {
263+ return nil , fmt .Errorf ("failed to attach sync source to node: %w" , err )
264+ }
254265 return su .syncNodesController .AttachNodeController (chainID , src , noSubscribe )
255266}
256267
@@ -263,6 +274,15 @@ func (su *SupervisorBackend) AttachProcessorSource(chainID types.ChainID, src pr
263274 return nil
264275}
265276
277+ func (su * SupervisorBackend ) AttachSyncSource (chainID types.ChainID , src syncnode.SyncSource ) error {
278+ _ , ok := su .syncSources .Get (chainID )
279+ if ! ok {
280+ return fmt .Errorf ("unknown chain %s, cannot attach RPC to sync source" , chainID )
281+ }
282+ su .syncSources .Set (chainID , src )
283+ return nil
284+ }
285+
266286func (su * SupervisorBackend ) attachL1RPC (ctx context.Context , l1RPCAddr string ) error {
267287 su .logger .Info ("attaching L1 RPC to L1 processor" , "rpc" , l1RPCAddr )
268288
@@ -497,6 +517,46 @@ func (su *SupervisorBackend) L1BlockRefByNumber(ctx context.Context, number uint
497517 return su .l1Accessor .L1BlockRefByNumber (ctx , number )
498518}
499519
520+ func (su * SupervisorBackend ) SuperRootAtTimestamp (ctx context.Context , timestamp hexutil.Uint64 ) (types.SuperRootResponse , error ) {
521+ chains := su .depSet .Chains ()
522+ slices .SortFunc (chains , func (a , b types.ChainID ) int {
523+ return a .Cmp (b )
524+ })
525+ chainInfos := make ([]types.ChainRootInfo , len (chains ))
526+ superRootChains := make ([]eth.ChainIDAndOutput , len (chains ))
527+ for i , chainID := range chains {
528+ src , ok := su .syncSources .Get (chainID )
529+ if ! ok {
530+ su .logger .Error ("bug: unknown chain %s, cannot get sync source" , chainID )
531+ return types.SuperRootResponse {}, fmt .Errorf ("unknown chain %s, cannot get sync source" , chainID )
532+ }
533+ output , err := src .OutputV0AtTimestamp (ctx , uint64 (timestamp ))
534+ if err != nil {
535+ return types.SuperRootResponse {}, err
536+ }
537+ pending , err := src .PendingOutputV0AtTimestamp (ctx , uint64 (timestamp ))
538+ if err != nil {
539+ return types.SuperRootResponse {}, err
540+ }
541+ canonicalRoot := eth .OutputRoot (output )
542+ chainInfos [i ] = types.ChainRootInfo {
543+ ChainID : chainID ,
544+ Canonical : canonicalRoot ,
545+ Pending : pending .Marshal (),
546+ }
547+ superRootChains [i ] = eth.ChainIDAndOutput {ChainID : chainID .ToBig ().Uint64 (), Output : canonicalRoot }
548+ }
549+ superRoot := eth .SuperRoot (& eth.SuperV1 {
550+ Timestamp : uint64 (timestamp ),
551+ Chains : superRootChains ,
552+ })
553+ return types.SuperRootResponse {
554+ Timestamp : uint64 (timestamp ),
555+ SuperRoot : superRoot ,
556+ Chains : chainInfos ,
557+ }, nil
558+ }
559+
500560// Update methods
501561// ----------------------------
502562
0 commit comments