Commit 19eb157f authored by Hamdi Allam's avatar Hamdi Allam

Legacy block processor

parent 7662a3b3
...@@ -37,7 +37,6 @@ func Grouped(start, end *big.Int, size uint64) []Range { ...@@ -37,7 +37,6 @@ func Grouped(start, end *big.Int, size uint64) []Range {
if end.Cmp(start) < 0 || size == 0 { if end.Cmp(start) < 0 || size == 0 {
return nil return nil
} }
bigMaxDiff := big.NewInt(int64(size - 1)) bigMaxDiff := big.NewInt(int64(size - 1))
groups := []Range{} groups := []Range{}
......
...@@ -7,7 +7,7 @@ import ( ...@@ -7,7 +7,7 @@ import (
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
geth_log "github.com/ethereum/go-ethereum/log" log "github.com/ethereum/go-ethereum/log"
) )
const ( const (
...@@ -34,6 +34,9 @@ type L1Contracts struct { ...@@ -34,6 +34,9 @@ type L1Contracts struct {
L1CrossDomainMessengerProxy common.Address `toml:"l1-cross-domain-messenger"` L1CrossDomainMessengerProxy common.Address `toml:"l1-cross-domain-messenger"`
L1StandardBridgeProxy common.Address `toml:"l1-standard-bridge"` L1StandardBridgeProxy common.Address `toml:"l1-standard-bridge"`
// Pre-Bedrock Legacy Contracts
LegacyCanonicalTransactionChain common.Address `toml:"l1-canonical-transaction-chain"`
// Some more contracts -- L1ERC721Bridge, ProxyAdmin, SystemConfig, etc // Some more contracts -- L1ERC721Bridge, ProxyAdmin, SystemConfig, etc
// Ignore the auxiliary contracts? // Ignore the auxiliary contracts?
...@@ -69,6 +72,10 @@ type ChainConfig struct { ...@@ -69,6 +72,10 @@ type ChainConfig struct {
L1Contracts L1Contracts `toml:"l1-contracts"` L1Contracts L1Contracts `toml:"l1-contracts"`
L1StartingHeight uint `toml:"l1-starting-height"` L1StartingHeight uint `toml:"l1-starting-height"`
// Bedrock starting heights only applicable for OP-Mainnet & OP-Goerli
L1BedrockStartingHeight uint `toml:"-"`
L2BedrockStartingHeight uint `toml:"-"`
// These configuration options will be removed once // These configuration options will be removed once
// native reorg handling is implemented // native reorg handling is implemented
L1ConfirmationDepth uint `toml:"l1-confirmation-depth"` L1ConfirmationDepth uint `toml:"l1-confirmation-depth"`
...@@ -103,8 +110,8 @@ type ServerConfig struct { ...@@ -103,8 +110,8 @@ type ServerConfig struct {
} }
// LoadConfig loads the `indexer.toml` config file from a given path // LoadConfig loads the `indexer.toml` config file from a given path
func LoadConfig(logger geth_log.Logger, path string) (Config, error) { func LoadConfig(log log.Logger, path string) (Config, error) {
logger.Debug("loading config", "path", path) log.Debug("loading config", "path", path)
var conf Config var conf Config
data, err := os.ReadFile(path) data, err := os.ReadFile(path)
...@@ -113,9 +120,9 @@ func LoadConfig(logger geth_log.Logger, path string) (Config, error) { ...@@ -113,9 +120,9 @@ func LoadConfig(logger geth_log.Logger, path string) (Config, error) {
} }
data = []byte(os.ExpandEnv(string(data))) data = []byte(os.ExpandEnv(string(data)))
logger.Debug("parsed config file", "data", string(data)) log.Debug("parsed config file", "data", string(data))
if _, err := toml.Decode(string(data), &conf); err != nil { if _, err := toml.Decode(string(data), &conf); err != nil {
logger.Info("failed to decode config file", "err", err) log.Info("failed to decode config file", "err", err)
return conf, err return conf, err
} }
...@@ -124,31 +131,34 @@ func LoadConfig(logger geth_log.Logger, path string) (Config, error) { ...@@ -124,31 +131,34 @@ func LoadConfig(logger geth_log.Logger, path string) (Config, error) {
if !ok { if !ok {
return conf, fmt.Errorf("unknown preset: %d", conf.Chain.Preset) return conf, fmt.Errorf("unknown preset: %d", conf.Chain.Preset)
} }
conf.Chain.L1Contracts = knownPreset.L1Contracts conf.Chain.L1Contracts = knownPreset.L1Contracts
conf.Chain.L1StartingHeight = knownPreset.L1StartingHeight conf.Chain.L1StartingHeight = knownPreset.L1StartingHeight
conf.Chain.L1BedrockStartingHeight = knownPreset.L1BedrockStartingHeight
conf.Chain.L2BedrockStartingHeight = knownPreset.L1BedrockStartingHeight
} }
// Set polling defaults if not set // Set polling defaults if not set
if conf.Chain.L1PollingInterval == 0 { if conf.Chain.L1PollingInterval == 0 {
logger.Info("setting default L1 polling interval", "interval", defaultLoopInterval) log.Info("setting default L1 polling interval", "interval", defaultLoopInterval)
conf.Chain.L1PollingInterval = defaultLoopInterval conf.Chain.L1PollingInterval = defaultLoopInterval
} }
if conf.Chain.L2PollingInterval == 0 { if conf.Chain.L2PollingInterval == 0 {
logger.Info("setting default L2 polling interval", "interval", defaultLoopInterval) log.Info("setting default L2 polling interval", "interval", defaultLoopInterval)
conf.Chain.L2PollingInterval = defaultLoopInterval conf.Chain.L2PollingInterval = defaultLoopInterval
} }
if conf.Chain.L1HeaderBufferSize == 0 { if conf.Chain.L1HeaderBufferSize == 0 {
logger.Info("setting default L1 header buffer", "size", defaultHeaderBufferSize) log.Info("setting default L1 header buffer", "size", defaultHeaderBufferSize)
conf.Chain.L1HeaderBufferSize = defaultHeaderBufferSize conf.Chain.L1HeaderBufferSize = defaultHeaderBufferSize
} }
if conf.Chain.L2HeaderBufferSize == 0 { if conf.Chain.L2HeaderBufferSize == 0 {
logger.Info("setting default L2 header buffer", "size", defaultHeaderBufferSize) log.Info("setting default L2 header buffer", "size", defaultHeaderBufferSize)
conf.Chain.L2HeaderBufferSize = defaultHeaderBufferSize conf.Chain.L2HeaderBufferSize = defaultHeaderBufferSize
} }
logger.Info("loaded config") log.Info("loaded config")
return conf, nil return conf, nil
} }
...@@ -10,23 +10,28 @@ var presetConfigs = map[int]ChainConfig{ ...@@ -10,23 +10,28 @@ var presetConfigs = map[int]ChainConfig{
// OP Mainnet // OP Mainnet
10: { 10: {
L1Contracts: L1Contracts{ L1Contracts: L1Contracts{
OptimismPortalProxy: common.HexToAddress("0xbEb5Fc579115071764c7423A4f12eDde41f106Ed"), OptimismPortalProxy: common.HexToAddress("0xbEb5Fc579115071764c7423A4f12eDde41f106Ed"),
L2OutputOracleProxy: common.HexToAddress("0xdfe97868233d1aa22e815a266982f2cf17685a27"), L2OutputOracleProxy: common.HexToAddress("0xdfe97868233d1aa22e815a266982f2cf17685a27"),
L1CrossDomainMessengerProxy: common.HexToAddress("0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1"), L1CrossDomainMessengerProxy: common.HexToAddress("0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1"),
L1StandardBridgeProxy: common.HexToAddress("0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1"), L1StandardBridgeProxy: common.HexToAddress("0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1"),
// LegacyCanonicalTransactionChain: common.HexToAddress("0x5e4e65926ba27467555eb562121fac00d24e9dd2"), LegacyCanonicalTransactionChain: common.HexToAddress("0x5e4e65926ba27467555eb562121fac00d24e9dd2"),
}, },
L1StartingHeight: 13596466, L1StartingHeight: 13596466,
L1BedrockStartingHeight: 17422590,
L2BedrockStartingHeight: 105235063,
}, },
// OP Goerli // OP Goerli
420: { 420: {
L1Contracts: L1Contracts{ L1Contracts: L1Contracts{
OptimismPortalProxy: common.HexToAddress("0x5b47E1A08Ea6d985D6649300584e6722Ec4B1383"), OptimismPortalProxy: common.HexToAddress("0x5b47E1A08Ea6d985D6649300584e6722Ec4B1383"),
L2OutputOracleProxy: common.HexToAddress("0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0"), L2OutputOracleProxy: common.HexToAddress("0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0"),
L1CrossDomainMessengerProxy: common.HexToAddress("0x5086d1eEF304eb5284A0f6720f79403b4e9bE294"), L1CrossDomainMessengerProxy: common.HexToAddress("0x5086d1eEF304eb5284A0f6720f79403b4e9bE294"),
L1StandardBridgeProxy: common.HexToAddress("0x636Af16bf2f682dD3109e60102b8E1A089FedAa8"), L1StandardBridgeProxy: common.HexToAddress("0x636Af16bf2f682dD3109e60102b8E1A089FedAa8"),
LegacyCanonicalTransactionChain: common.HexToAddress("0x2ebA8c4EfDB39A8Cd8f9eD65c50ec079f7CEBD81"),
}, },
L1StartingHeight: 7017096, L1StartingHeight: 7017096,
L1BedrockStartingHeight: 8300214,
L2BedrockStartingHeight: 4061224,
}, },
// Base Mainnet // Base Mainnet
8453: { 8453: {
......
...@@ -29,9 +29,10 @@ type ETL struct { ...@@ -29,9 +29,10 @@ type ETL struct {
headerBufferSize uint64 headerBufferSize uint64
headerTraversal *node.HeaderTraversal headerTraversal *node.HeaderTraversal
ethClient node.EthClient
contracts []common.Address contracts []common.Address
etlBatches chan ETLBatch etlBatches chan ETLBatch
EthClient node.EthClient
} }
type ETLBatch struct { type ETLBatch struct {
...@@ -104,7 +105,7 @@ func (etl *ETL) processBatch(headers []types.Header) error { ...@@ -104,7 +105,7 @@ func (etl *ETL) processBatch(headers []types.Header) error {
} }
headersWithLog := make(map[common.Hash]bool, len(headers)) headersWithLog := make(map[common.Hash]bool, len(headers))
logs, err := etl.ethClient.FilterLogs(ethereum.FilterQuery{FromBlock: firstHeader.Number, ToBlock: lastHeader.Number, Addresses: etl.contracts}) logs, err := etl.EthClient.FilterLogs(ethereum.FilterQuery{FromBlock: firstHeader.Number, ToBlock: lastHeader.Number, Addresses: etl.contracts})
if err != nil { if err != nil {
batchLog.Info("unable to extract logs", "err", err) batchLog.Info("unable to extract logs", "err", err)
return err return err
......
...@@ -66,9 +66,10 @@ func NewL1ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli ...@@ -66,9 +66,10 @@ func NewL1ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli
log: log, log: log,
metrics: metrics, metrics: metrics,
headerTraversal: node.NewHeaderTraversal(client, fromHeader, cfg.ConfirmationDepth), headerTraversal: node.NewHeaderTraversal(client, fromHeader, cfg.ConfirmationDepth),
ethClient: client,
contracts: cSlice, contracts: cSlice,
etlBatches: etlBatches, etlBatches: etlBatches,
EthClient: client,
} }
return &L1ETL{ETL: etl, db: db, mu: new(sync.Mutex)}, nil return &L1ETL{ETL: etl, db: db, mu: new(sync.Mutex)}, nil
......
...@@ -50,9 +50,10 @@ func NewL2ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli ...@@ -50,9 +50,10 @@ func NewL2ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli
log: log, log: log,
metrics: metrics, metrics: metrics,
headerTraversal: node.NewHeaderTraversal(client, fromHeader, cfg.ConfirmationDepth), headerTraversal: node.NewHeaderTraversal(client, fromHeader, cfg.ConfirmationDepth),
ethClient: client,
contracts: l2Contracts, contracts: l2Contracts,
etlBatches: etlBatches, etlBatches: etlBatches,
EthClient: client,
} }
return &L2ETL{ETL: etl, db: db}, nil return &L2ETL{ETL: etl, db: db}, nil
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
# Can configure them manually or use a preset l2 ChainId for known chains including OP Mainnet, OP Goerli, Base, Base Goerli, Zora, and Zora goerli # Can configure them manually or use a preset l2 ChainId for known chains including OP Mainnet, OP Goerli, Base, Base Goerli, Zora, and Zora goerli
[chain] [chain]
# OP Goerli
preset = $INDEXER_CHAIN_PRESET preset = $INDEXER_CHAIN_PRESET
# L1 Config # L1 Config
......
...@@ -29,7 +29,7 @@ CREATE TABLE IF NOT EXISTS l2_block_headers ( ...@@ -29,7 +29,7 @@ CREATE TABLE IF NOT EXISTS l2_block_headers (
hash VARCHAR PRIMARY KEY, hash VARCHAR PRIMARY KEY,
parent_hash VARCHAR NOT NULL UNIQUE, parent_hash VARCHAR NOT NULL UNIQUE,
number UINT256 NOT NULL UNIQUE, number UINT256 NOT NULL UNIQUE,
timestamp INTEGER NOT NULL UNIQUE CHECK (timestamp > 0), timestamp INTEGER NOT NULL,
-- Raw Data -- Raw Data
rlp_bytes VARCHAR NOT NULL rlp_bytes VARCHAR NOT NULL
......
...@@ -29,6 +29,8 @@ type EthClient interface { ...@@ -29,6 +29,8 @@ type EthClient interface {
BlockHeaderByHash(common.Hash) (*types.Header, error) BlockHeaderByHash(common.Hash) (*types.Header, error)
BlockHeadersByRange(*big.Int, *big.Int) ([]types.Header, error) BlockHeadersByRange(*big.Int, *big.Int) ([]types.Header, error)
TxByHash(common.Hash) (*types.Transaction, error)
StorageHash(common.Address, *big.Int) (common.Hash, error) StorageHash(common.Address, *big.Int) (common.Hash, error)
FilterLogs(ethereum.FilterQuery) ([]types.Log, error) FilterLogs(ethereum.FilterQuery) ([]types.Log, error)
} }
...@@ -147,6 +149,23 @@ func (c *client) BlockHeadersByRange(startHeight, endHeight *big.Int) ([]types.H ...@@ -147,6 +149,23 @@ func (c *client) BlockHeadersByRange(startHeight, endHeight *big.Int) ([]types.H
return headers, nil return headers, nil
} }
func (c *client) TxByHash(hash common.Hash) (*types.Transaction, error) {
ctxwt, cancel := context.WithTimeout(context.Background(), defaultRequestTimeout)
defer cancel()
var tx *types.Transaction
err := c.rpc.CallContext(ctxwt, &tx, "eth_getTransactionByHash", hash)
if err != nil {
return nil, err
} else if tx == nil {
return nil, ethereum.NotFound
}
// NOTE: why does ethclient do something different here
return tx, nil
}
// StorageHash returns the sha3 of the storage root for the specified account // StorageHash returns the sha3 of the storage root for the specified account
func (c *client) StorageHash(address common.Address, blockNumber *big.Int) (common.Hash, error) { func (c *client) StorageHash(address common.Address, blockNumber *big.Int) (common.Hash, error) {
ctxwt, cancel := context.WithTimeout(context.Background(), defaultRequestTimeout) ctxwt, cancel := context.WithTimeout(context.Background(), defaultRequestTimeout)
......
...@@ -124,15 +124,77 @@ func (b *BridgeProcessor) Start(ctx context.Context) error { ...@@ -124,15 +124,77 @@ func (b *BridgeProcessor) Start(ctx context.Context) error {
fromL2Height = new(big.Int).Add(b.LatestL2Header.Number, bigint.One) fromL2Height = new(big.Int).Add(b.LatestL2Header.Number, bigint.One)
} }
l1BedrockStartingHeight := big.NewInt(int64(b.chainConfig.L1BedrockStartingHeight))
l2BedrockStartingHeight := big.NewInt(int64(b.chainConfig.L2BedrockStartingHeight))
batchLog := b.log.New("epoch_start_number", fromL1Height, "epoch_end_number", toL1Height) batchLog := b.log.New("epoch_start_number", fromL1Height, "epoch_end_number", toL1Height)
batchLog.Info("unobserved epochs") batchLog.Info("unobserved epochs")
err = b.db.Transaction(func(tx *database.DB) error { err = b.db.Transaction(func(tx *database.DB) error {
l1BridgeLog := b.log.New("bridge", "l1")
l2BridgeLog := b.log.New("bridge", "l2")
// In the event where we have a large number of un-observed blocks, group the block range // In the event where we have a large number of un-observed blocks, group the block range
// on the order of 10k blocks at a time. If this turns out to be a bottleneck, we can // on the order of 10k blocks at a time. If this turns out to be a bottleneck, we can
// parallelize these operations for significant improvements as well // parallelize these operations for significant improvements as well
l1BridgeLog := b.log.New("bridge", "l1")
l2BridgeLog := b.log.New("bridge", "l2")
// FOR OP-MAINNET, OP-GOERLI ONLY! Specially handle the existence of pre-bedrock blocks
// - Since this processor indexes bridge events on available epochs between L1 & L2, we
// can detect when we've switched into bedrock state by comparing the l1 bedrock starting
// height to the range of L1 blocks we are indexing.
if l1BedrockStartingHeight.Cmp(fromL1Height) > 0 {
legacyFromL1Height, legacyToL1Height := fromL1Height, toL1Height
legacyFromL2Height, legacyToL2Height := fromL2Height, toL2Height
if l1BedrockStartingHeight.Cmp(toL1Height) <= 0 {
legacyToL1Height = new(big.Int).Sub(l1BedrockStartingHeight, big.NewInt(1))
legacyToL1Height = new(big.Int).Sub(l2BedrockStartingHeight, big.NewInt(1))
}
l1BridgeLog := l1BridgeLog.New("mode", "legacy")
l2BridgeLog := l2BridgeLog.New("mode", "legacy")
l1BlockGroups := bigint.Grouped(legacyFromL1Height, legacyToL1Height, 10_000)
l2BlockGroups := bigint.Grouped(legacyFromL2Height, legacyToL2Height, 10_000)
// Now that all initiated events have been indexed, it is ensured that all finalization can find their counterpart.
for _, group := range l1BlockGroups {
log := l1BridgeLog.New("from_l1_block_number", group.Start, "to_l1_block_number", group.End)
log.Info("scanning for initiated bridge events")
if err := bridge.LegacyL1ProcessInitiatedBridgeEvents(log, tx, b.chainConfig, group.Start, group.End); err != nil {
return err
}
}
for _, group := range l2BlockGroups {
log := l2BridgeLog.New("from_l2_block_number", group.Start, "to_l2_block_number", group.End)
log.Info("scanning for initiated bridge events")
if err := bridge.LegacyL2ProcessInitiatedBridgeEvents(log, tx, group.Start, group.End); err != nil {
return err
}
}
// Now that all initiated events have been indexed, it is ensured that all finalization can find their counterpart.
for _, group := range l1BlockGroups {
log := l1BridgeLog.New("from_l1_block_number", group.Start, "to_l1_block_number", group.End)
log.Info("scanning for finalized bridge events")
if err := bridge.LegacyL1ProcessFinalizedBridgeEvents(log, tx, b.l1Etl.EthClient, b.chainConfig, group.Start, group.End); err != nil {
return err
}
}
for _, group := range l2BlockGroups {
log := l2BridgeLog.New("from_l2_block_number", group.Start, "to_l2_block_number", group.End)
log.Info("scanning for finalized bridge events")
if err := bridge.LegacyL2ProcessFinalizedBridgeEvents(log, tx, group.Start, group.End); err != nil {
return err
}
}
if legacyToL1Height.Cmp(toL1Height) == 0 {
// a-ok! entire batch was legacy blocks
return nil
}
batchLog.Info("detected switch to bedrock", "l1_bedrock_starting_height", l1BedrockStartingHeight, "l2_bedrock_starting_height", l2BedrockStartingHeight)
fromL1Height = l1BedrockStartingHeight
fromL2Height = l2BedrockStartingHeight
}
l1BlockGroups := bigint.Grouped(fromL1Height, toL1Height, 10_000) l1BlockGroups := bigint.Grouped(fromL1Height, toL1Height, 10_000)
l2BlockGroups := bigint.Grouped(fromL2Height, toL2Height, 10_000) l2BlockGroups := bigint.Grouped(fromL2Height, toL2Height, 10_000)
...@@ -181,4 +243,5 @@ func (b *BridgeProcessor) Start(ctx context.Context) error { ...@@ -181,4 +243,5 @@ func (b *BridgeProcessor) Start(ctx context.Context) error {
b.LatestL2Header = latestEpoch.L2BlockHeader.RLPHeader.Header() b.LatestL2Header = latestEpoch.L2BlockHeader.RLPHeader.Header()
} }
} }
} }
This diff is collapsed.
...@@ -18,7 +18,7 @@ var ( ...@@ -18,7 +18,7 @@ var (
bytesType, _ = abi.NewType("bytes", "", nil) bytesType, _ = abi.NewType("bytes", "", nil)
addressType, _ = abi.NewType("address", "", nil) addressType, _ = abi.NewType("address", "", nil)
legacyCrossDomainMessengerRelayMessageMethod = abi.NewMethod( CrossDomainMessengerLegacyRelayMessageEncoding = abi.NewMethod(
"relayMessage", "relayMessage",
"relayMessage", "relayMessage",
abi.Function, abi.Function,
...@@ -26,10 +26,13 @@ var ( ...@@ -26,10 +26,13 @@ var (
false, // isConst false, // isConst
true, // payable true, // payable
abi.Arguments{ // inputs abi.Arguments{ // inputs
{Name: "sender", Type: addressType},
{Name: "target", Type: addressType}, {Name: "target", Type: addressType},
{Name: "sender", Type: addressType},
{Name: "data", Type: bytesType}, {Name: "data", Type: bytesType},
{Name: "nonce", Type: uint256Type}, {Name: "nonce", Type: uint256Type},
// The actual transaction on the legacy L1CrossDomainMessenger
// actually has a trailing proof argument but is ignored for the
// `XDomainCallData` encoding
}, },
abi.Arguments{}, // outputs abi.Arguments{}, // outputs
) )
...@@ -58,7 +61,6 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress ...@@ -58,7 +61,6 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress
return nil, err return nil, err
} }
if len(sentMessageEvents) == 0 { if len(sentMessageEvents) == 0 {
// prevent the following db queries if we dont need them
return nil, nil return nil, nil
} }
...@@ -68,10 +70,13 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress ...@@ -68,10 +70,13 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress
if err != nil { if err != nil {
return nil, err return nil, err
} }
if len(sentMessageEvents) != len(sentMessageExtensionEvents) { if len(sentMessageExtensionEvents) > len(sentMessageEvents) {
return nil, fmt.Errorf("mismatch in SentMessage events. %d sent messages & %d sent message extensions", len(sentMessageEvents), len(sentMessageExtensionEvents)) return nil, fmt.Errorf("mismatch. %d sent messages & %d sent message extensions", len(sentMessageEvents), len(sentMessageExtensionEvents))
} }
// We handle version zero messages uniquely since the first version of cross domain messages
// do not have the SentMessageExtension1 event emitted, introduced in version 1.
numVersionZeroMessages := len(sentMessageEvents) - len(sentMessageExtensionEvents)
crossDomainSentMessages := make([]CrossDomainMessengerSentMessageEvent, len(sentMessageEvents)) crossDomainSentMessages := make([]CrossDomainMessengerSentMessageEvent, len(sentMessageEvents))
for i := range sentMessageEvents { for i := range sentMessageEvents {
sentMessage := bindings.CrossDomainMessengerSentMessage{Raw: *sentMessageEvents[i].RLPLog} sentMessage := bindings.CrossDomainMessengerSentMessage{Raw: *sentMessageEvents[i].RLPLog}
...@@ -79,13 +84,24 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress ...@@ -79,13 +84,24 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress
if err != nil { if err != nil {
return nil, err return nil, err
} }
sentMessageExtension := bindings.CrossDomainMessengerSentMessageExtension1{Raw: *sentMessageExtensionEvents[i].RLPLog}
err = UnpackLog(&sentMessageExtension, sentMessageExtensionEvents[i].RLPLog, sentMessageExtensionEventAbi.Name, crossDomainMessengerAbi) version, _ := DecodeVersionedNonce(sentMessage.MessageNonce)
if err != nil { if i < numVersionZeroMessages && version != 0 {
return nil, err return nil, fmt.Errorf("expected version zero nonce. nonce %d tx_hash %s", sentMessage.MessageNonce, sentMessage.Raw.TxHash)
}
// In version zero, to value is bridged through the cross domain messenger.
value := big.NewInt(0)
if version > 0 {
sentMessageExtension := bindings.CrossDomainMessengerSentMessageExtension1{Raw: *sentMessageExtensionEvents[i].RLPLog}
err = UnpackLog(&sentMessageExtension, sentMessageExtensionEvents[i].RLPLog, sentMessageExtensionEventAbi.Name, crossDomainMessengerAbi)
if err != nil {
return nil, err
}
value = sentMessageExtension.Value
} }
messageHash, err := CrossDomainMessageHash(crossDomainMessengerAbi, &sentMessage, sentMessageExtension.Value) messageHash, err := CrossDomainMessageHash(crossDomainMessengerAbi, &sentMessage, value)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -100,13 +116,12 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress ...@@ -100,13 +116,12 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress
Tx: database.Transaction{ Tx: database.Transaction{
FromAddress: sentMessage.Sender, FromAddress: sentMessage.Sender,
ToAddress: sentMessage.Target, ToAddress: sentMessage.Target,
Amount: sentMessageExtension.Value, Amount: value,
Data: sentMessage.Message, Data: sentMessage.Message,
Timestamp: sentMessageEvents[i].Timestamp, Timestamp: sentMessageEvents[i].Timestamp,
}, },
}, },
} }
} }
return crossDomainSentMessages, nil return crossDomainSentMessages, nil
...@@ -148,11 +163,11 @@ func CrossDomainMessageHash(abi *abi.ABI, sentMsg *bindings.CrossDomainMessenger ...@@ -148,11 +163,11 @@ func CrossDomainMessageHash(abi *abi.ABI, sentMsg *bindings.CrossDomainMessenger
switch version { switch version {
case 0: case 0:
// Legacy Message // Legacy Message
inputBytes, err := legacyCrossDomainMessengerRelayMessageMethod.Inputs.Pack(sentMsg.Sender, sentMsg.Target, sentMsg.Message, sentMsg.MessageNonce) inputBytes, err := CrossDomainMessengerLegacyRelayMessageEncoding.Inputs.Pack(sentMsg.Target, sentMsg.Sender, sentMsg.Message, sentMsg.MessageNonce)
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
msgBytes := append(legacyCrossDomainMessengerRelayMessageMethod.ID, inputBytes...) msgBytes := append(CrossDomainMessengerLegacyRelayMessageEncoding.ID, inputBytes...)
return crypto.Keccak256Hash(msgBytes), nil return crypto.Keccak256Hash(msgBytes), nil
case 1: case 1:
// Current Message // Current Message
......
package contracts
import (
"math/big"
"github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum/go-ethereum/common"
)
type LegacyBridgeEvent struct {
Event *database.ContractEvent
BridgeTransfer database.BridgeTransfer
}
func L1StandardBridgeLegacyDepositInitiatedEvents(contractAddress common.Address, db *database.DB, fromHeight, toHeight *big.Int) ([]LegacyBridgeEvent, error) {
l1StandardBridgeAbi, err := bindings.L1StandardBridgeMetaData.GetAbi()
if err != nil {
return nil, err
}
// The L1StandardBridge contains the legacy events
ethDepositEventAbi := l1StandardBridgeAbi.Events["ETHDepositInitiated"]
erc20DepositEventAbi := l1StandardBridgeAbi.Events["ERC20DepositInitiated"]
// Grab both ETH & ERC20 Events
ethDepositEvents, err := db.ContractEvents.L1ContractEventsWithFilter(database.ContractEvent{ContractAddress: contractAddress, EventSignature: ethDepositEventAbi.ID}, fromHeight, toHeight)
if err != nil {
return nil, err
}
erc20DepositEvents, err := db.ContractEvents.L1ContractEventsWithFilter(database.ContractEvent{ContractAddress: contractAddress, EventSignature: erc20DepositEventAbi.ID}, fromHeight, toHeight)
if err != nil {
return nil, err
}
// Represent the ETH deposits via the ETH ERC20 predeploy address
deposits := make([]LegacyBridgeEvent, len(ethDepositEvents)+len(erc20DepositEvents))
for i := range ethDepositEvents {
bridgeEvent := bindings.L1StandardBridgeETHDepositInitiated{Raw: *ethDepositEvents[i].RLPLog}
err := UnpackLog(&bridgeEvent, &bridgeEvent.Raw, ethDepositEventAbi.Name, l1StandardBridgeAbi)
if err != nil {
return nil, err
}
deposits[i] = LegacyBridgeEvent{
Event: &ethDepositEvents[i].ContractEvent,
BridgeTransfer: database.BridgeTransfer{
TokenPair: database.ETHTokenPair,
Tx: database.Transaction{
FromAddress: bridgeEvent.From,
ToAddress: bridgeEvent.To,
Amount: bridgeEvent.Amount,
Data: bridgeEvent.ExtraData,
Timestamp: ethDepositEvents[i].Timestamp,
},
},
}
}
for i := range erc20DepositEvents {
bridgeEvent := bindings.L1StandardBridgeERC20DepositInitiated{Raw: *erc20DepositEvents[i].RLPLog}
err := UnpackLog(&bridgeEvent, &bridgeEvent.Raw, erc20DepositEventAbi.Name, l1StandardBridgeAbi)
if err != nil {
return nil, err
}
deposits[len(ethDepositEvents)+i] = LegacyBridgeEvent{
Event: &erc20DepositEvents[i].ContractEvent,
BridgeTransfer: database.BridgeTransfer{
TokenPair: database.TokenPair{LocalTokenAddress: bridgeEvent.L1Token, RemoteTokenAddress: bridgeEvent.L2Token},
Tx: database.Transaction{
FromAddress: bridgeEvent.From,
ToAddress: bridgeEvent.To,
Amount: bridgeEvent.Amount,
Data: bridgeEvent.ExtraData,
Timestamp: erc20DepositEvents[i].Timestamp,
},
},
}
}
return deposits, nil
}
func L2StandardBridgeLegacyWithdrawalInitiatedEvents(contractAddress common.Address, db *database.DB, fromHeight, toHeight *big.Int) ([]LegacyBridgeEvent, error) {
l2StandardBridgeAbi, err := bindings.L2StandardBridgeMetaData.GetAbi()
if err != nil {
return nil, err
}
withdrawalInitiatedEventAbi := l2StandardBridgeAbi.Events["WithdrawalInitiated"]
withdrawalEvents, err := db.ContractEvents.L2ContractEventsWithFilter(database.ContractEvent{ContractAddress: contractAddress, EventSignature: withdrawalInitiatedEventAbi.ID}, fromHeight, toHeight)
withdrawals := make([]LegacyBridgeEvent, len(withdrawalEvents))
for i := range withdrawalEvents {
bridgeEvent := bindings.L2StandardBridgeWithdrawalInitiated{Raw: *withdrawalEvents[i].RLPLog}
err := UnpackLog(&bridgeEvent, &bridgeEvent.Raw, withdrawalInitiatedEventAbi.Name, l2StandardBridgeAbi)
if err != nil {
return nil, err
}
withdrawals[i] = LegacyBridgeEvent{
Event: &withdrawalEvents[i].ContractEvent,
BridgeTransfer: database.BridgeTransfer{
TokenPair: database.ETHTokenPair,
Tx: database.Transaction{
FromAddress: bridgeEvent.From,
ToAddress: bridgeEvent.To,
Amount: bridgeEvent.Amount,
Data: bridgeEvent.ExtraData,
Timestamp: withdrawalEvents[i].Timestamp,
},
},
}
}
return withdrawals, nil
}
package contracts
import (
"math/big"
"github.com/ethereum-optimism/optimism/indexer/database"
legacy_bindings "github.com/ethereum-optimism/optimism/op-bindings/legacy-bindings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
type LegacyCTCDepositEvent struct {
Event *database.ContractEvent
Tx database.Transaction
TxHash common.Hash
GasLimit *big.Int
}
func LegacyCTCDepositEvents(contractAddress common.Address, db *database.DB, fromHeight, toHeight *big.Int) ([]LegacyCTCDepositEvent, error) {
ctcAbi, err := legacy_bindings.CanonicalTransactionChainMetaData.GetAbi()
if err != nil {
return nil, err
}
transactionEnqueuedEventAbi := ctcAbi.Events["TransactionEnqueued"]
contractEventFilter := database.ContractEvent{ContractAddress: contractAddress, EventSignature: transactionEnqueuedEventAbi.ID}
events, err := db.ContractEvents.L1ContractEventsWithFilter(contractEventFilter, fromHeight, toHeight)
if err != nil {
return nil, err
}
ctcTxDeposits := make([]LegacyCTCDepositEvent, len(events))
for i := range events {
txEnqueued := legacy_bindings.CanonicalTransactionChainTransactionEnqueued{Raw: *events[i].RLPLog}
err = UnpackLog(&txEnqueued, events[i].RLPLog, transactionEnqueuedEventAbi.Name, ctcAbi)
if err != nil {
return nil, err
}
zeroAmt := big.NewInt(0)
ctcTxDeposits[i] = LegacyCTCDepositEvent{
Event: &events[i].ContractEvent,
GasLimit: txEnqueued.GasLimit,
TxHash: types.NewTransaction(0, txEnqueued.Target, zeroAmt, txEnqueued.GasLimit.Uint64(), nil, txEnqueued.Data).Hash(),
Tx: database.Transaction{
FromAddress: txEnqueued.L1TxOrigin,
ToAddress: txEnqueued.Target,
Amount: zeroAmt,
Data: txEnqueued.Data,
Timestamp: events[i].Timestamp,
},
}
}
return ctcTxDeposits, nil
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment