Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
32780542
Commit
32780542
authored
Jun 09, 2023
by
Hamdi Allam
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
index specified contract events
parent
2fdcbd5a
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
226 additions
and
23 deletions
+226
-23
bridge.go
indexer/database/bridge.go
+6
-3
contract_events.go
indexer/database/contract_events.go
+6
-4
indexer.go
indexer/indexer.go
+12
-3
l1_processor.go
indexer/processor/l1_processor.go
+98
-7
l2_processor.go
indexer/processor/l2_processor.go
+104
-6
No files found.
indexer/database/bridge.go
View file @
32780542
...
...
@@ -3,9 +3,12 @@ package database
import
(
"errors"
"gorm.io/gorm"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"gorm.io/gorm"
"github.com/google/uuid"
)
/**
...
...
@@ -26,7 +29,7 @@ type TokenPair struct {
}
type
Deposit
struct
{
GUID
string
`gorm:"primaryKey"`
GUID
uuid
.
UUID
`gorm:"primaryKey"`
InitiatedL1EventGUID
string
Tx
Transaction
`gorm:"embedded"`
...
...
@@ -39,7 +42,7 @@ type DepositWithTransactionHash struct {
}
type
Withdrawal
struct
{
GUID
string
`gorm:"primaryKey"`
GUID
uuid
.
UUID
`gorm:"primaryKey"`
InitiatedL2EventGUID
string
WithdrawalHash
common
.
Hash
`gorm:"serializer:json"`
...
...
indexer/database/contract_events.go
View file @
32780542
package
database
import
(
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"gorm.io/gorm"
"github.com/ethereum/go-ethereum/common"
"github.com/google/uuid"
)
/**
...
...
@@ -11,11 +13,11 @@ import (
*/
type
ContractEvent
struct
{
GUID
string
`gorm:"primaryKey"`
GUID
uuid
.
UUID
`gorm:"primaryKey"`
BlockHash
common
.
Hash
`gorm:"serializer:json"`
TransactionHash
common
.
Hash
`gorm:"serializer:json"`
EventSignature
hexutil
.
Bytes
`gorm:"serializer:json"`
EventSignature
common
.
Hash
`gorm:"serializer:json"`
LogIndex
uint64
Timestamp
uint64
}
...
...
indexer/indexer.go
View file @
32780542
...
...
@@ -9,6 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/indexer/node"
"github.com/ethereum-optimism/optimism/indexer/processor"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/urfave/cli"
...
...
@@ -72,22 +73,30 @@ func NewIndexer(ctx *cli.Context) (*Indexer, error) {
return
nil
,
err
}
// L1 Processor
// L1 Processor (hardhat devnet contracts). Make this configurable
l1Contracts
:=
processor
.
L1Contracts
{
OptimismPortal
:
common
.
HexToAddress
(
"0x6900000000000000000000000000000000000000"
),
L2OutputOracle
:
common
.
HexToAddress
(
"0x6900000000000000000000000000000000000001"
),
L1CrossDomainMessenger
:
common
.
HexToAddress
(
"0x6900000000000000000000000000000000000002"
),
L1StandardBridge
:
common
.
HexToAddress
(
"0x6900000000000000000000000000000000000003"
),
L1ERC721Bridge
:
common
.
HexToAddress
(
"0x6900000000000000000000000000000000000004"
),
}
l1EthClient
,
err
:=
node
.
NewEthClient
(
ctx
.
GlobalString
(
flags
.
L1EthRPCFlag
.
Name
))
if
err
!=
nil
{
return
nil
,
err
}
l1Processor
,
err
:=
processor
.
NewL1Processor
(
l1EthClient
,
db
)
l1Processor
,
err
:=
processor
.
NewL1Processor
(
l1EthClient
,
db
,
l1Contracts
)
if
err
!=
nil
{
return
nil
,
err
}
// L2Processor
l2Contracts
:=
processor
.
L2ContractPredeploys
()
// Make this configurable
l2EthClient
,
err
:=
node
.
NewEthClient
(
ctx
.
GlobalString
(
flags
.
L2EthRPCFlag
.
Name
))
if
err
!=
nil
{
return
nil
,
err
}
l2Processor
,
err
:=
processor
.
NewL2Processor
(
l2EthClient
,
db
)
l2Processor
,
err
:=
processor
.
NewL2Processor
(
l2EthClient
,
db
,
l2Contracts
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
indexer/processor/l1_processor.go
View file @
32780542
package
processor
import
(
"context"
"errors"
"reflect"
"github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/indexer/node"
"github.com/google/uuid"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
)
type
L1Contracts
struct
{
OptimismPortal
common
.
Address
L2OutputOracle
common
.
Address
L1CrossDomainMessenger
common
.
Address
L1StandardBridge
common
.
Address
L1ERC721Bridge
common
.
Address
// Some more contracts -- ProxyAdmin, SystemConfig, etcc
// Ignore the auxilliary contracts?
// Legacy contracts? We'll add this in to index the legacy chain.
// Remove afterwards?
}
func
(
c
L1Contracts
)
toArray
()
[]
common
.
Address
{
fields
:=
reflect
.
VisibleFields
(
reflect
.
TypeOf
(
c
))
v
:=
reflect
.
ValueOf
(
c
)
contracts
:=
make
([]
common
.
Address
,
len
(
fields
))
for
i
,
field
:=
range
fields
{
contracts
[
i
]
=
(
v
.
FieldByName
(
field
.
Name
)
.
Interface
())
.
(
common
.
Address
)
}
return
contracts
}
type
L1Processor
struct
{
processor
}
func
NewL1Processor
(
ethClient
node
.
EthClient
,
db
*
database
.
DB
)
(
*
L1Processor
,
error
)
{
func
NewL1Processor
(
ethClient
node
.
EthClient
,
db
*
database
.
DB
,
l1Contracts
L1Contracts
)
(
*
L1Processor
,
error
)
{
l1ProcessLog
:=
log
.
New
(
"processor"
,
"l1"
)
l1ProcessLog
.
Info
(
"initializing processor"
)
...
...
@@ -41,7 +75,7 @@ func NewL1Processor(ethClient node.EthClient, db *database.DB) (*L1Processor, er
processor
:
processor
{
fetcher
:
node
.
NewFetcher
(
ethClient
,
fromL1Header
),
db
:
db
,
processFn
:
l1ProcessFn
(
ethClient
),
processFn
:
l1ProcessFn
(
l1ProcessLog
,
ethClient
,
l1Contracts
),
processLog
:
l1ProcessLog
,
},
}
...
...
@@ -49,22 +83,79 @@ func NewL1Processor(ethClient node.EthClient, db *database.DB) (*L1Processor, er
return
l1Processor
,
nil
}
func
l1ProcessFn
(
ethClient
node
.
EthClient
)
func
(
db
*
database
.
DB
,
headers
[]
*
types
.
Header
)
error
{
func
l1ProcessFn
(
processLog
log
.
Logger
,
ethClient
node
.
EthClient
,
l1Contracts
L1Contracts
)
func
(
db
*
database
.
DB
,
headers
[]
*
types
.
Header
)
error
{
rawEthClient
:=
ethclient
.
NewClient
(
ethClient
.
RawRpcClient
())
contractAddrs
:=
l1Contracts
.
toArray
()
processLog
.
Info
(
"processor configured with contracts"
,
"contracts"
,
l1Contracts
)
return
func
(
db
*
database
.
DB
,
headers
[]
*
types
.
Header
)
error
{
numHeaders
:=
len
(
headers
)
// index all l2 blocks for now
l1Headers
:=
make
([]
*
database
.
L1BlockHeader
,
len
(
headers
))
/** Index Blocks **/
l1Headers
:=
make
([]
*
database
.
L1BlockHeader
,
numHeaders
)
l1HeaderMap
:=
make
(
map
[
common
.
Hash
]
*
types
.
Header
)
for
i
,
header
:=
range
headers
{
blockHash
:=
header
.
Hash
()
l1Headers
[
i
]
=
&
database
.
L1BlockHeader
{
BlockHeader
:
database
.
BlockHeader
{
Hash
:
header
.
Hash
()
,
Hash
:
blockHash
,
ParentHash
:
header
.
ParentHash
,
Number
:
database
.
U256
{
Int
:
header
.
Number
},
Timestamp
:
header
.
Time
,
},
}
l1HeaderMap
[
blockHash
]
=
header
}
/** Index Contract Events **/
logFilter
:=
ethereum
.
FilterQuery
{
FromBlock
:
headers
[
0
]
.
Number
,
ToBlock
:
headers
[
numHeaders
-
1
]
.
Number
,
Addresses
:
contractAddrs
}
logs
,
err
:=
rawEthClient
.
FilterLogs
(
context
.
Background
(),
logFilter
)
if
err
!=
nil
{
return
err
}
numLogs
:=
len
(
logs
)
l1ContractEvents
:=
make
([]
*
database
.
L1ContractEvent
,
numLogs
)
for
i
,
log
:=
range
logs
{
header
,
ok
:=
l1HeaderMap
[
log
.
BlockHash
]
if
!
ok
{
// Log the individual headers in the batch?
processLog
.
Crit
(
"contract event found with associated header not in the batch"
,
"header"
,
header
,
"log_index"
,
log
.
Index
)
return
errors
.
New
(
"parsed log with a block hash not in this batch"
)
}
l1ContractEvents
[
i
]
=
&
database
.
L1ContractEvent
{
ContractEvent
:
database
.
ContractEvent
{
GUID
:
uuid
.
New
(),
BlockHash
:
log
.
BlockHash
,
TransactionHash
:
log
.
TxHash
,
EventSignature
:
log
.
Topics
[
0
],
LogIndex
:
uint64
(
log
.
Index
),
Timestamp
:
header
.
Time
,
},
}
}
/** Update Database **/
err
=
db
.
Blocks
.
StoreL1BlockHeaders
(
l1Headers
)
if
err
!=
nil
{
return
err
}
if
numLogs
>
0
{
processLog
.
Info
(
"detected new contract logs"
,
"size"
,
numLogs
)
err
=
db
.
ContractEvents
.
StoreL1ContractEvents
(
l1ContractEvents
)
if
err
!=
nil
{
return
err
}
}
return
db
.
Blocks
.
StoreL1BlockHeaders
(
l1Headers
)
// a-ok!
return
nil
}
}
indexer/processor/l2_processor.go
View file @
32780542
package
processor
import
(
"context"
"errors"
"reflect"
"github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/indexer/node"
"github.com/google/uuid"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
)
type
L2Contracts
struct
{
L2CrossDomainMessenger
common
.
Address
L2StandardBridge
common
.
Address
L2ERC721Bridge
common
.
Address
L2ToL1MessagePasser
common
.
Address
// Some more contracts -- ProxyAdmin, SystemConfig, etcc
// Ignore the auxilliary contracts?
// Legacy Contracts? We'll add this in to index the legacy chain.
// Remove afterwards?
}
func
L2ContractPredeploys
()
L2Contracts
{
return
L2Contracts
{
L2CrossDomainMessenger
:
common
.
HexToAddress
(
"0x4200000000000000000000000000000000000007"
),
L2StandardBridge
:
common
.
HexToAddress
(
"0x4200000000000000000000000000000000000010"
),
L2ERC721Bridge
:
common
.
HexToAddress
(
"0x4200000000000000000000000000000000000014"
),
L2ToL1MessagePasser
:
common
.
HexToAddress
(
"0x4200000000000000000000000000000000000016"
),
}
}
func
(
c
L2Contracts
)
toArray
()
[]
common
.
Address
{
fields
:=
reflect
.
VisibleFields
(
reflect
.
TypeOf
(
c
))
v
:=
reflect
.
ValueOf
(
c
)
contracts
:=
make
([]
common
.
Address
,
len
(
fields
))
for
i
,
field
:=
range
fields
{
contracts
[
i
]
=
(
v
.
FieldByName
(
field
.
Name
)
.
Interface
())
.
(
common
.
Address
)
}
return
contracts
}
type
L2Processor
struct
{
processor
}
func
NewL2Processor
(
ethClient
node
.
EthClient
,
db
*
database
.
DB
)
(
*
L2Processor
,
error
)
{
func
NewL2Processor
(
ethClient
node
.
EthClient
,
db
*
database
.
DB
,
l2Contracts
L2Contracts
)
(
*
L2Processor
,
error
)
{
l2ProcessLog
:=
log
.
New
(
"processor"
,
"l2"
)
l2ProcessLog
.
Info
(
"initializing processor"
)
...
...
@@ -40,7 +82,7 @@ func NewL2Processor(ethClient node.EthClient, db *database.DB) (*L2Processor, er
processor
:
processor
{
fetcher
:
node
.
NewFetcher
(
ethClient
,
fromL2Header
),
db
:
db
,
processFn
:
l2ProcessFn
(
ethClient
),
processFn
:
l2ProcessFn
(
l2ProcessLog
,
ethClient
,
l2Contracts
),
processLog
:
l2ProcessLog
,
},
}
...
...
@@ -48,22 +90,78 @@ func NewL2Processor(ethClient node.EthClient, db *database.DB) (*L2Processor, er
return
l2Processor
,
nil
}
func
l2ProcessFn
(
ethClient
node
.
EthClient
)
func
(
db
*
database
.
DB
,
headers
[]
*
types
.
Header
)
error
{
func
l2ProcessFn
(
processLog
log
.
Logger
,
ethClient
node
.
EthClient
,
l2Contracts
L2Contracts
)
func
(
db
*
database
.
DB
,
headers
[]
*
types
.
Header
)
error
{
rawEthClient
:=
ethclient
.
NewClient
(
ethClient
.
RawRpcClient
())
contractAddrs
:=
l2Contracts
.
toArray
()
processLog
.
Info
(
"processor configured with contracts"
,
"contracts"
,
l2Contracts
)
return
func
(
db
*
database
.
DB
,
headers
[]
*
types
.
Header
)
error
{
numHeaders
:=
len
(
headers
)
/** Index Blocks **/
// index all l2 blocks for now
l2Headers
:=
make
([]
*
database
.
L2BlockHeader
,
len
(
headers
))
l2HeaderMap
:=
make
(
map
[
common
.
Hash
]
*
types
.
Header
)
for
i
,
header
:=
range
headers
{
blockHash
:=
header
.
Hash
()
l2Headers
[
i
]
=
&
database
.
L2BlockHeader
{
BlockHeader
:
database
.
BlockHeader
{
Hash
:
header
.
Hash
()
,
Hash
:
blockHash
,
ParentHash
:
header
.
ParentHash
,
Number
:
database
.
U256
{
Int
:
header
.
Number
},
Timestamp
:
header
.
Time
,
},
}
l2HeaderMap
[
blockHash
]
=
header
}
/** Index Contract Events **/
logFilter
:=
ethereum
.
FilterQuery
{
FromBlock
:
headers
[
0
]
.
Number
,
ToBlock
:
headers
[
numHeaders
-
1
]
.
Number
,
Addresses
:
contractAddrs
}
logs
,
err
:=
rawEthClient
.
FilterLogs
(
context
.
Background
(),
logFilter
)
if
err
!=
nil
{
return
err
}
numLogs
:=
len
(
logs
)
l2ContractEvents
:=
make
([]
*
database
.
L2ContractEvent
,
numLogs
)
for
i
,
log
:=
range
logs
{
header
,
ok
:=
l2HeaderMap
[
log
.
BlockHash
]
if
!
ok
{
// Log the individual headers in the batch?
processLog
.
Crit
(
"contract event found with associated header not in the batch"
,
"header"
,
header
,
"log_index"
,
log
.
Index
)
return
errors
.
New
(
"parsed log with a block hash not in this batch"
)
}
l2ContractEvents
[
i
]
=
&
database
.
L2ContractEvent
{
ContractEvent
:
database
.
ContractEvent
{
GUID
:
uuid
.
New
(),
BlockHash
:
log
.
BlockHash
,
TransactionHash
:
log
.
TxHash
,
EventSignature
:
log
.
Topics
[
0
],
LogIndex
:
uint64
(
log
.
Index
),
Timestamp
:
header
.
Time
,
},
}
}
/** Update Database **/
err
=
db
.
Blocks
.
StoreL2BlockHeaders
(
l2Headers
)
if
err
!=
nil
{
return
err
}
if
numLogs
>
0
{
processLog
.
Info
(
"detected new contract logs"
,
"size"
,
numLogs
)
err
=
db
.
ContractEvents
.
StoreL2ContractEvents
(
l2ContractEvents
)
if
err
!=
nil
{
return
err
}
}
return
db
.
Blocks
.
StoreL2BlockHeaders
(
l2Headers
)
// a-ok!
return
nil
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment