diff --git a/packages/taiko-client/driver/chain_syncer/beaconsync/syncer.go b/packages/taiko-client/driver/chain_syncer/beaconsync/syncer.go index b9691cc165..cc2c65a515 100644 --- a/packages/taiko-client/driver/chain_syncer/beaconsync/syncer.go +++ b/packages/taiko-client/driver/chain_syncer/beaconsync/syncer.go @@ -5,13 +5,12 @@ import ( "fmt" "math/big" - "github.com/taikoxyz/taiko-mono/packages/taiko-client/bindings" - "github.com/ethereum/go-ethereum/beacon/engine" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/log" + "github.com/taikoxyz/taiko-mono/packages/taiko-client/bindings" "github.com/taikoxyz/taiko-mono/packages/taiko-client/bindings/encoding" "github.com/taikoxyz/taiko-mono/packages/taiko-client/driver/state" "github.com/taikoxyz/taiko-mono/packages/taiko-client/pkg/rpc" @@ -72,8 +71,15 @@ func (s *Syncer) TriggerBeaconSync(blockID uint64) error { return fmt.Errorf("unexpected NewPayload response status: %s", status.Status) } + lastVerifiedBlockHash, err := s.rpc.GetLastVerifiedBlockHash(s.ctx) + if err != nil { + return fmt.Errorf("failed to fetch the last verified block hash: %w", err) + } + fcRes, err := s.rpc.L2Engine.ForkchoiceUpdate(s.ctx, &engine.ForkchoiceStateV1{ - HeadBlockHash: headPayload.BlockHash, + HeadBlockHash: headPayload.BlockHash, + SafeBlockHash: lastVerifiedBlockHash, + FinalizedBlockHash: lastVerifiedBlockHash, }, nil) if err != nil { return err diff --git a/packages/taiko-client/driver/chain_syncer/blob/syncer.go b/packages/taiko-client/driver/chain_syncer/blob/syncer.go index 2314964a19..c850bb52ad 100644 --- a/packages/taiko-client/driver/chain_syncer/blob/syncer.go +++ b/packages/taiko-client/driver/chain_syncer/blob/syncer.go @@ -409,7 +409,16 @@ func (s *Syncer) insertNewHead( return nil, fmt.Errorf("failed to create execution payloads: %w", err) } - fc := &engine.ForkchoiceStateV1{HeadBlockHash: payload.BlockHash} + lastVerifiedBlockHash, err := s.rpc.GetLastVerifiedBlockHash(ctx) + if err != nil { + return nil, fmt.Errorf("failed to fetch the last verified block hash: %w", err) + } + + fc := &engine.ForkchoiceStateV1{ + HeadBlockHash: payload.BlockHash, + SafeBlockHash: lastVerifiedBlockHash, + FinalizedBlockHash: lastVerifiedBlockHash, + } // Update the fork choice fcRes, err := s.rpc.L2Engine.ForkchoiceUpdate(ctx, fc, nil) diff --git a/packages/taiko-client/pkg/rpc/methods.go b/packages/taiko-client/pkg/rpc/methods.go index d89b1457a7..7a747c419e 100644 --- a/packages/taiko-client/pkg/rpc/methods.go +++ b/packages/taiko-client/pkg/rpc/methods.go @@ -510,6 +510,19 @@ func (c *Client) GetProtocolStateVariables(opts *bind.CallOpts) (*struct { return GetProtocolStateVariables(c.TaikoL1, opts) } +// GetLastVerifiedBlockHash gets the last verified block hash from TaikoL1 contract. +func (c *Client) GetLastVerifiedBlockHash(ctx context.Context) (common.Hash, error) { + ctxWithTimeout, cancel := context.WithTimeout(ctx, defaultTimeout) + defer cancel() + + b, err := c.TaikoL1.GetLastVerifiedBlock(&bind.CallOpts{Context: ctxWithTimeout}) + if err != nil { + return common.Hash{}, err + } + + return b.BlockHash, nil +} + // GetL2BlockInfo fetches the L2 block information from the protocol. func (c *Client) GetL2BlockInfo(ctx context.Context, blockID *big.Int) (bindings.TaikoDataBlockV2, error) { ctxWithTimeout, cancel := CtxWithTimeoutOrDefault(ctx, defaultTimeout)