mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-04 02:53:45 +00:00
* port changes from #1013 * port changes from #1068 * go.mod tidy * fix compile error * fix goimports * fix log * address review comments * upgrade golang.org/x/net to 0.23.0 * bump version * remove unused flag * update da-codec commit --------- Co-authored-by: Péter Garamvölgyi <peter@scroll.io>
158 lines
5.8 KiB
Go
158 lines
5.8 KiB
Go
package rollup_sync_service
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"math/big"
|
|
|
|
"github.com/scroll-tech/go-ethereum"
|
|
"github.com/scroll-tech/go-ethereum/accounts/abi"
|
|
"github.com/scroll-tech/go-ethereum/common"
|
|
"github.com/scroll-tech/go-ethereum/core/types"
|
|
"github.com/scroll-tech/go-ethereum/log"
|
|
"github.com/scroll-tech/go-ethereum/rpc"
|
|
|
|
"github.com/scroll-tech/go-ethereum/rollup/sync_service"
|
|
)
|
|
|
|
// L1Client is a wrapper around EthClient that adds
|
|
// methods for conveniently collecting rollup events of ScrollChain contract.
|
|
type L1Client struct {
|
|
ctx context.Context
|
|
client sync_service.EthClient
|
|
scrollChainAddress common.Address
|
|
l1CommitBatchEventSignature common.Hash
|
|
l1RevertBatchEventSignature common.Hash
|
|
l1FinalizeBatchEventSignature common.Hash
|
|
}
|
|
|
|
// NewL1Client initializes a new L1Client instance with the provided configuration.
|
|
// It checks for a valid scrollChainAddress and verifies the chain ID.
|
|
func NewL1Client(ctx context.Context, l1Client sync_service.EthClient, l1ChainId uint64, scrollChainAddress common.Address, scrollChainABI *abi.ABI) (*L1Client, error) {
|
|
if scrollChainAddress == (common.Address{}) {
|
|
return nil, errors.New("must pass non-zero scrollChainAddress to L1Client")
|
|
}
|
|
|
|
// sanity check: compare chain IDs
|
|
got, err := l1Client.ChainID(ctx)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to query L1 chain ID, err: %w", err)
|
|
}
|
|
if got.Cmp(big.NewInt(0).SetUint64(l1ChainId)) != 0 {
|
|
return nil, fmt.Errorf("unexpected chain ID, expected: %v, got: %v", l1ChainId, got)
|
|
}
|
|
|
|
client := L1Client{
|
|
ctx: ctx,
|
|
client: l1Client,
|
|
scrollChainAddress: scrollChainAddress,
|
|
l1CommitBatchEventSignature: scrollChainABI.Events["CommitBatch"].ID,
|
|
l1RevertBatchEventSignature: scrollChainABI.Events["RevertBatch"].ID,
|
|
l1FinalizeBatchEventSignature: scrollChainABI.Events["FinalizeBatch"].ID,
|
|
}
|
|
|
|
return &client, nil
|
|
}
|
|
|
|
// FetchRollupEventsInRange retrieves and parses commit/revert/finalize rollup events between block numbers: [from, to].
|
|
func (c *L1Client) FetchRollupEventsInRange(from, to uint64) ([]types.Log, error) {
|
|
log.Trace("L1Client FetchRollupEventsInRange", "fromBlock", from, "toBlock", to)
|
|
|
|
query := ethereum.FilterQuery{
|
|
FromBlock: big.NewInt(int64(from)), // inclusive
|
|
ToBlock: big.NewInt(int64(to)), // inclusive
|
|
Addresses: []common.Address{
|
|
c.scrollChainAddress,
|
|
},
|
|
Topics: make([][]common.Hash, 1),
|
|
}
|
|
query.Topics[0] = make([]common.Hash, 3)
|
|
query.Topics[0][0] = c.l1CommitBatchEventSignature
|
|
query.Topics[0][1] = c.l1RevertBatchEventSignature
|
|
query.Topics[0][2] = c.l1FinalizeBatchEventSignature
|
|
|
|
logs, err := c.client.FilterLogs(c.ctx, query)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to filter logs, err: %w", err)
|
|
}
|
|
return logs, nil
|
|
}
|
|
|
|
// GetLatestFinalizedBlockNumber fetches the block number of the latest finalized block from the L1 chain.
|
|
func (c *L1Client) GetLatestFinalizedBlockNumber() (uint64, error) {
|
|
header, err := c.client.HeaderByNumber(c.ctx, big.NewInt(int64(rpc.FinalizedBlockNumber)))
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
if !header.Number.IsInt64() {
|
|
return 0, fmt.Errorf("received unexpected block number in L1Client: %v", header.Number)
|
|
}
|
|
return header.Number.Uint64(), nil
|
|
}
|
|
|
|
// FetchTxData fetches tx data corresponding to given event log
|
|
func (c *L1Client) FetchTxData(vLog *types.Log) ([]byte, error) {
|
|
tx, _, err := c.client.TransactionByHash(c.ctx, vLog.TxHash)
|
|
if err != nil {
|
|
log.Debug("failed to get transaction by hash, probably an unindexed transaction, fetching the whole block to get the transaction",
|
|
"tx hash", vLog.TxHash.Hex(), "block number", vLog.BlockNumber, "block hash", vLog.BlockHash.Hex(), "err", err)
|
|
block, err := c.client.BlockByHash(c.ctx, vLog.BlockHash)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get block by hash, block number: %v, block hash: %v, err: %w", vLog.BlockNumber, vLog.BlockHash.Hex(), err)
|
|
}
|
|
|
|
found := false
|
|
for _, txInBlock := range block.Transactions() {
|
|
if txInBlock.Hash() == vLog.TxHash {
|
|
tx = txInBlock
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
return nil, fmt.Errorf("transaction not found in the block, tx hash: %v, block number: %v, block hash: %v", vLog.TxHash.Hex(), vLog.BlockNumber, vLog.BlockHash.Hex())
|
|
}
|
|
}
|
|
|
|
return tx.Data(), nil
|
|
}
|
|
|
|
// FetchTxBlobHash fetches tx blob hash corresponding to given event log
|
|
func (c *L1Client) FetchTxBlobHash(vLog *types.Log) (common.Hash, error) {
|
|
tx, _, err := c.client.TransactionByHash(c.ctx, vLog.TxHash)
|
|
if err != nil {
|
|
log.Debug("failed to get transaction by hash, probably an unindexed transaction, fetching the whole block to get the transaction",
|
|
"tx hash", vLog.TxHash.Hex(), "block number", vLog.BlockNumber, "block hash", vLog.BlockHash.Hex(), "err", err)
|
|
block, err := c.client.BlockByHash(c.ctx, vLog.BlockHash)
|
|
if err != nil {
|
|
return common.Hash{}, fmt.Errorf("failed to get block by hash, block number: %v, block hash: %v, err: %w", vLog.BlockNumber, vLog.BlockHash.Hex(), err)
|
|
}
|
|
|
|
found := false
|
|
for _, txInBlock := range block.Transactions() {
|
|
if txInBlock.Hash() == vLog.TxHash {
|
|
tx = txInBlock
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
return common.Hash{}, fmt.Errorf("transaction not found in the block, tx hash: %v, block number: %v, block hash: %v", vLog.TxHash.Hex(), vLog.BlockNumber, vLog.BlockHash.Hex())
|
|
}
|
|
}
|
|
blobHashes := tx.BlobHashes()
|
|
if len(blobHashes) == 0 {
|
|
return common.Hash{}, fmt.Errorf("transaction does not contain any blobs, tx hash: %v", vLog.TxHash.Hex())
|
|
}
|
|
return blobHashes[0], nil
|
|
}
|
|
|
|
// GetHeaderByNumber fetches the block header by number
|
|
func (c *L1Client) GetHeaderByNumber(blockNumber uint64) (*types.Header, error) {
|
|
header, err := c.client.HeaderByNumber(c.ctx, big.NewInt(0).SetUint64(blockNumber))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return header, nil
|
|
}
|