mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-29 16:13:47 +00:00
129 lines
3.7 KiB
Go
129 lines
3.7 KiB
Go
package sync_service
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"math/big"
|
|
|
|
"github.com/scroll-tech/go-ethereum/accounts/abi/bind"
|
|
"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"
|
|
)
|
|
|
|
// BridgeClient is a wrapper around EthClient that adds
|
|
// methods for conveniently collecting L1 messages.
|
|
type BridgeClient struct {
|
|
client EthClient
|
|
confirmations rpc.BlockNumber
|
|
l1MessageQueueAddress common.Address
|
|
filterer *L1MessageQueueFilterer
|
|
}
|
|
|
|
func newBridgeClient(ctx context.Context, l1Client EthClient, l1ChainId uint64, confirmations rpc.BlockNumber, l1MessageQueueAddress common.Address) (*BridgeClient, error) {
|
|
if l1MessageQueueAddress == (common.Address{}) {
|
|
return nil, errors.New("must pass non-zero l1MessageQueueAddress to BridgeClient")
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
|
|
filterer, err := NewL1MessageQueueFilterer(l1MessageQueueAddress, l1Client)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to initialize L1MessageQueueFilterer, err = %w", err)
|
|
}
|
|
|
|
client := BridgeClient{
|
|
client: l1Client,
|
|
confirmations: confirmations,
|
|
l1MessageQueueAddress: l1MessageQueueAddress,
|
|
filterer: filterer,
|
|
}
|
|
|
|
return &client, nil
|
|
}
|
|
|
|
// fetchMessagesInRange retrieves and parses all L1 messages between the
|
|
// provided from and to L1 block numbers (inclusive).
|
|
func (c *BridgeClient) fetchMessagesInRange(ctx context.Context, from, to uint64) ([]types.L1MessageTx, error) {
|
|
log.Trace("BridgeClient fetchMessagesInRange", "fromBlock", from, "toBlock", to)
|
|
|
|
opts := bind.FilterOpts{
|
|
Start: from,
|
|
End: &to,
|
|
Context: ctx,
|
|
}
|
|
it, err := c.filterer.FilterQueueTransaction(&opts, nil, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var msgs []types.L1MessageTx
|
|
|
|
for it.Next() {
|
|
event := it.Event
|
|
log.Trace("Received new L1 QueueTransaction event", "event", event)
|
|
|
|
if !event.GasLimit.IsUint64() {
|
|
return nil, fmt.Errorf("invalid QueueTransaction event: QueueIndex = %v, GasLimit = %v", event.QueueIndex, event.GasLimit)
|
|
}
|
|
|
|
msgs = append(msgs, types.L1MessageTx{
|
|
QueueIndex: event.QueueIndex,
|
|
Gas: event.GasLimit.Uint64(),
|
|
To: &event.Target,
|
|
Value: event.Value,
|
|
Data: event.Data,
|
|
Sender: event.Sender,
|
|
})
|
|
}
|
|
|
|
return msgs, nil
|
|
}
|
|
|
|
func (c *BridgeClient) getLatestConfirmedBlockNumber(ctx context.Context) (uint64, error) {
|
|
// confirmation based on "safe" or "finalized" block tag
|
|
if c.confirmations == rpc.SafeBlockNumber || c.confirmations == rpc.FinalizedBlockNumber {
|
|
tag := big.NewInt(int64(c.confirmations))
|
|
header, err := c.client.HeaderByNumber(ctx, tag)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
if !header.Number.IsInt64() {
|
|
return 0, fmt.Errorf("received unexpected block number in BridgeClient: %v", header.Number)
|
|
}
|
|
return header.Number.Uint64(), nil
|
|
}
|
|
|
|
// confirmation based on latest block number
|
|
if c.confirmations == rpc.LatestBlockNumber {
|
|
number, err := c.client.BlockNumber(ctx)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return number, nil
|
|
}
|
|
|
|
// confirmation based on a certain number of blocks
|
|
if c.confirmations.Int64() >= 0 {
|
|
number, err := c.client.BlockNumber(ctx)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
confirmations := uint64(c.confirmations.Int64())
|
|
if number >= confirmations {
|
|
return number - confirmations, nil
|
|
}
|
|
return 0, nil
|
|
}
|
|
|
|
return 0, fmt.Errorf("unknown confirmation type: %v", c.confirmations)
|
|
}
|