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
5a9928c0
Unverified
Commit
5a9928c0
authored
Oct 09, 2022
by
Matthew Slipper
Committed by
GitHub
Oct 09, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
indexer: Upgrade L2 services (#3668)
parent
475b2bfa
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
178 additions
and
267 deletions
+178
-267
indexer.go
indexer/indexer.go
+0
-2
bridge.go
indexer/services/l2/bridge/bridge.go
+30
-29
filter.go
indexer/services/l2/bridge/filter.go
+0
-45
standard_bridge.go
indexer/services/l2/bridge/standard_bridge.go
+82
-53
confirmed_headers.go
indexer/services/l2/confirmed_headers.go
+1
-2
query.go
indexer/services/l2/query.go
+0
-38
service.go
indexer/services/l2/service.go
+65
-98
No files found.
indexer/indexer.go
View file @
5a9928c0
...
@@ -183,7 +183,6 @@ func NewIndexer(cfg Config, gitVersion string) (*Indexer, error) {
...
@@ -183,7 +183,6 @@ func NewIndexer(cfg Config, gitVersion string) (*Indexer, error) {
ConfDepth
:
cfg
.
ConfDepth
,
ConfDepth
:
cfg
.
ConfDepth
,
MaxHeaderBatchSize
:
cfg
.
MaxHeaderBatchSize
,
MaxHeaderBatchSize
:
cfg
.
MaxHeaderBatchSize
,
StartBlockNumber
:
uint64
(
0
),
StartBlockNumber
:
uint64
(
0
),
StartBlockHash
:
cfg
.
L2GenesisBlockHash
,
})
})
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -211,7 +210,6 @@ func (b *Indexer) Serve() error {
...
@@ -211,7 +210,6 @@ func (b *Indexer) Serve() error {
b
.
router
.
HandleFunc
(
"/v1/l1/status"
,
b
.
l1IndexingService
.
GetIndexerStatus
)
.
Methods
(
"GET"
)
b
.
router
.
HandleFunc
(
"/v1/l1/status"
,
b
.
l1IndexingService
.
GetIndexerStatus
)
.
Methods
(
"GET"
)
b
.
router
.
HandleFunc
(
"/v1/l2/status"
,
b
.
l2IndexingService
.
GetIndexerStatus
)
.
Methods
(
"GET"
)
b
.
router
.
HandleFunc
(
"/v1/l2/status"
,
b
.
l2IndexingService
.
GetIndexerStatus
)
.
Methods
(
"GET"
)
b
.
router
.
HandleFunc
(
"/v1/deposits/0x{address:[a-fA-F0-9]{40}}"
,
b
.
l1IndexingService
.
GetDeposits
)
.
Methods
(
"GET"
)
b
.
router
.
HandleFunc
(
"/v1/deposits/0x{address:[a-fA-F0-9]{40}}"
,
b
.
l1IndexingService
.
GetDeposits
)
.
Methods
(
"GET"
)
b
.
router
.
HandleFunc
(
"/v1/withdrawal/0x{hash:[a-fA-F0-9]{64}}"
,
b
.
l2IndexingService
.
GetWithdrawalStatus
)
.
Methods
(
"GET"
)
b
.
router
.
HandleFunc
(
"/v1/withdrawals/0x{address:[a-fA-F0-9]{40}}"
,
b
.
l2IndexingService
.
GetWithdrawals
)
.
Methods
(
"GET"
)
b
.
router
.
HandleFunc
(
"/v1/withdrawals/0x{address:[a-fA-F0-9]{40}}"
,
b
.
l2IndexingService
.
GetWithdrawals
)
.
Methods
(
"GET"
)
b
.
router
.
HandleFunc
(
"/v1/airdrops/0x{address:[a-fA-F0-9]{40}}"
,
b
.
airdropService
.
GetAirdrop
)
b
.
router
.
HandleFunc
(
"/v1/airdrops/0x{address:[a-fA-F0-9]{40}}"
,
b
.
airdropService
.
GetAirdrop
)
b
.
router
.
HandleFunc
(
"/healthz"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
b
.
router
.
HandleFunc
(
"/healthz"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
...
...
indexer/services/l2/bridge/bridge.go
View file @
5a9928c0
...
@@ -7,75 +7,76 @@ import (
...
@@ -7,75 +7,76 @@ import (
"github.com/ethereum-optimism/optimism/indexer/db"
"github.com/ethereum-optimism/optimism/indexer/db"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
)
)
type
DepositsMap
map
[
common
.
Hash
][]
db
.
Deposit
// Finalizations
type
WithdrawalsMap
map
[
common
.
Hash
][]
db
.
Withdrawal
type
WithdrawalsMap
map
[
common
.
Hash
][]
db
.
Withdrawal
type
Bridge
interface
{
type
Bridge
interface
{
Address
()
common
.
Address
Address
()
common
.
Address
GetDepositsByBlockRange
(
uint64
,
uint64
)
(
DepositsMap
,
error
)
GetWithdrawalsByBlockRange
(
context
.
Context
,
uint64
,
uint64
)
(
WithdrawalsMap
,
error
)
GetWithdrawalsByBlockRange
(
uint64
,
uint64
)
(
WithdrawalsMap
,
error
)
String
()
string
String
()
string
}
}
type
implConfig
struct
{
type
implConfig
struct
{
name
string
name
string
impl
string
impl
string
addr
string
addr
common
.
Address
}
}
var
defaultBridgeCfgs
=
map
[
uint64
][]
*
implConfig
{
var
defaultBridgeCfgs
=
[]
*
implConfig
{
// Devnet
{
"Standard"
,
"StandardBridge"
,
predeploys
.
L2StandardBridgeAddr
},
901
:
{
{
"Standard"
,
"StandardBridge"
,
L2StandardBridgeAddr
},
},
// Goerli Alpha Testnet
28528
:
{
{
"Standard"
,
"StandardBridge"
,
L2StandardBridgeAddr
},
},
}
}
var
customBridgeCfgs
=
map
[
uint64
][]
*
implConfig
{
var
customBridgeCfgs
=
map
[
uint64
][]
*
implConfig
{
// Mainnet
// Mainnet
10
:
{
10
:
{
{
"BitBTC"
,
StandardBridgeImpl
,
"0x158F513096923fF2d3aab2BcF4478536de6725e2"
},
{
"BitBTC"
,
StandardBridgeImpl
,
common
.
HexToAddress
(
"0x158F513096923fF2d3aab2BcF4478536de6725e2"
)
},
//{"DAI", "DAIBridge", "0x467194771dAe2967Aef3ECbEDD3Bf9a310C76C65"},
//{"DAI", "DAIBridge", "0x467194771dAe2967Aef3ECbEDD3Bf9a310C76C65"},
{
"wstETH"
,
StandardBridgeImpl
,
common
.
HexToAddress
(
"0x8E01013243a96601a86eb3153F0d9Fa4fbFb6957"
)},
},
},
// Kovan
// Kovan
69
:
{
69
:
{
{
"BitBTC"
,
StandardBridgeImpl
,
"0x0CFb46528a7002a7D8877a5F7a69b9AaF1A9058e"
},
{
"BitBTC"
,
StandardBridgeImpl
,
common
.
HexToAddress
(
"0x0CFb46528a7002a7D8877a5F7a69b9AaF1A9058e"
)},
{
"USX"
,
StandardBridgeImpl
,
"0xB4d37826b14Cd3CB7257A2A5094507d701fe715f"
},
{
"USX"
,
StandardBridgeImpl
,
common
.
HexToAddress
(
"0xB4d37826b14Cd3CB7257A2A5094507d701fe715f"
)},
{
"wstETH"
,
StandardBridgeImpl
,
common
.
HexToAddress
(
"0x2E34e7d705AfaC3C4665b6feF31Aa394A1c81c92"
)},
//{"DAI", " DAIBridge", "0x467194771dAe2967Aef3ECbEDD3Bf9a310C76C65"},
//{"DAI", " DAIBridge", "0x467194771dAe2967Aef3ECbEDD3Bf9a310C76C65"},
},
},
}
}
func
BridgesByChainID
(
chainID
*
big
.
Int
,
client
bind
.
ContractFilterer
,
ctx
context
.
Context
)
(
map
[
string
]
Bridge
,
error
)
{
func
BridgesByChainID
(
chainID
*
big
.
Int
,
client
*
ethclient
.
Client
,
isBedrock
bool
)
(
map
[
string
]
Bridge
,
error
)
{
allCfgs
:=
make
([]
*
implConfig
,
0
)
allCfgs
:=
make
([]
*
implConfig
,
0
)
allCfgs
=
append
(
allCfgs
,
defaultBridgeCfgs
[
chainID
.
Uint64
()]
...
)
allCfgs
=
append
(
allCfgs
,
defaultBridgeCfgs
...
)
allCfgs
=
append
(
allCfgs
,
customBridgeCfgs
[
chainID
.
Uint64
()]
...
)
allCfgs
=
append
(
allCfgs
,
customBridgeCfgs
[
chainID
.
Uint64
()]
...
)
var
l2L1MP
*
bindings
.
L2ToL1MessagePasser
var
err
error
if
isBedrock
{
l2L1MP
,
err
=
bindings
.
NewL2ToL1MessagePasser
(
predeploys
.
L2ToL1MessagePasserAddr
,
client
)
if
err
!=
nil
{
return
nil
,
err
}
}
bridges
:=
make
(
map
[
string
]
Bridge
)
bridges
:=
make
(
map
[
string
]
Bridge
)
for
_
,
bridge
:=
range
allCfgs
{
for
_
,
bridge
:=
range
allCfgs
{
switch
bridge
.
impl
{
switch
bridge
.
impl
{
case
"StandardBridge"
:
case
"StandardBridge"
:
l2StandardBridgeAddress
:=
common
.
HexToAddress
(
bridge
.
addr
)
l2SB
,
err
:=
bindings
.
NewL2StandardBridge
(
bridge
.
addr
,
client
)
l2StandardBridgeFilter
,
err
:=
bindings
.
NewL2StandardBridgeFilterer
(
l2StandardBridgeAddress
,
client
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
bridges
[
bridge
.
name
]
=
&
StandardBridge
{
standardBridge
:=
&
StandardBridge
{
name
:
bridge
.
name
,
name
:
bridge
.
name
,
address
:
bridge
.
addr
,
c
tx
:
ctx
,
c
lient
:
client
,
address
:
l2StandardBridgeAddress
,
l2SB
:
l2SB
,
client
:
client
,
l2L1MP
:
l2L1MP
,
filterer
:
l2StandardBridgeFilter
,
isBedrock
:
isBedrock
,
}
}
bridges
[
bridge
.
name
]
=
standardBridge
default
:
default
:
return
nil
,
errors
.
New
(
"unsupported bridge"
)
return
nil
,
errors
.
New
(
"unsupported bridge"
)
}
}
...
...
indexer/services/l2/bridge/filter.go
deleted
100644 → 0
View file @
475b2bfa
package
bridge
import
(
"context"
"time"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
)
// clientRetryInterval is the interval to wait between retrying client API
// calls.
var
clientRetryInterval
=
5
*
time
.
Second
// FilterWithdrawalInitiatedWithRetry retries the given func until it succeeds,
// waiting for clientRetryInterval duration after every call.
func
FilterWithdrawalInitiatedWithRetry
(
ctx
context
.
Context
,
filterer
*
bindings
.
L2StandardBridgeFilterer
,
opts
*
bind
.
FilterOpts
)
(
*
bindings
.
L2StandardBridgeWithdrawalInitiatedIterator
,
error
)
{
for
{
ctxt
,
cancel
:=
context
.
WithTimeout
(
ctx
,
DefaultConnectionTimeout
)
opts
.
Context
=
ctxt
res
,
err
:=
filterer
.
FilterWithdrawalInitiated
(
opts
,
nil
,
nil
,
nil
)
cancel
()
if
err
==
nil
{
return
res
,
nil
}
logger
.
Error
(
"Error fetching filter"
,
"err"
,
err
)
time
.
Sleep
(
clientRetryInterval
)
}
}
// FilterDepositFinalizedWithRetry retries the given func until it succeeds,
// waiting for clientRetryInterval duration after every call.
func
FilterDepositFinalizedWithRetry
(
ctx
context
.
Context
,
filterer
*
bindings
.
L2StandardBridgeFilterer
,
opts
*
bind
.
FilterOpts
)
(
*
bindings
.
L2StandardBridgeDepositFinalizedIterator
,
error
)
{
for
{
ctxt
,
cancel
:=
context
.
WithTimeout
(
ctx
,
DefaultConnectionTimeout
)
opts
.
Context
=
ctxt
res
,
err
:=
filterer
.
FilterDepositFinalized
(
opts
,
nil
,
nil
,
nil
)
cancel
()
if
err
==
nil
{
return
res
,
nil
}
logger
.
Error
(
"Error fetching filter"
,
"err"
,
err
)
time
.
Sleep
(
clientRetryInterval
)
}
}
indexer/services/l2/bridge/standard_bridge.go
View file @
5a9928c0
...
@@ -5,83 +5,112 @@ import (
...
@@ -5,83 +5,112 @@ import (
"github.com/ethereum-optimism/optimism/indexer/db"
"github.com/ethereum-optimism/optimism/indexer/db"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-node/withdrawals"
"github.com/ethereum-optimism/optimism/op-service/backoff"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
)
)
type
StandardBridge
struct
{
type
StandardBridge
struct
{
name
string
name
string
ctx
context
.
Context
address
common
.
Address
address
common
.
Address
client
*
ethclient
.
Client
client
bind
.
ContractFilterer
l2SB
*
bindings
.
L2StandardBridge
filterer
*
bindings
.
L2StandardBridgeFilterer
l2L1MP
*
bindings
.
L2ToL1MessagePasser
isBedrock
bool
}
}
func
(
s
*
StandardBridge
)
Address
()
common
.
Address
{
func
(
s
*
StandardBridge
)
Address
()
common
.
Address
{
return
s
.
address
return
s
.
address
}
}
func
(
s
*
StandardBridge
)
GetDepositsByBlockRange
(
start
,
end
uint64
)
(
DepositsMap
,
error
)
{
func
(
s
*
StandardBridge
)
GetWithdrawalsByBlockRange
(
ctx
context
.
Context
,
start
,
end
uint64
)
(
WithdrawalsMap
,
error
)
{
depositsByBlockhash
:=
make
(
DepositsMap
)
withdrawalsByBlockhash
:=
make
(
map
[
common
.
Hash
][]
db
.
Withdrawal
)
opts
:=
&
bind
.
FilterOpts
{
Context
:
ctx
,
Start
:
start
,
End
:
&
end
,
}
iter
,
err
:=
FilterDepositFinalizedWithRetry
(
s
.
ctx
,
s
.
filterer
,
&
bind
.
FilterOpts
{
var
iter
*
bindings
.
L2StandardBridgeWithdrawalInitiatedIterator
Start
:
start
,
err
:=
backoff
.
Do
(
3
,
backoff
.
Exponential
(),
func
()
error
{
End
:
&
end
,
var
err
error
iter
,
err
=
s
.
l2SB
.
FilterWithdrawalInitiated
(
opts
,
nil
,
nil
,
nil
)
return
err
})
})
if
err
!=
nil
{
if
err
!=
nil
{
logger
.
Error
(
"Error fetching filter"
,
"err"
,
err
)
return
nil
,
err
}
}
receipts
:=
make
(
map
[
common
.
Hash
]
*
types
.
Receipt
)
defer
iter
.
Close
()
for
iter
.
Next
()
{
for
iter
.
Next
()
{
depositsByBlockhash
[
iter
.
Event
.
Raw
.
BlockHash
]
=
append
(
ev
:=
iter
.
Event
depositsByBlockhash
[
iter
.
Event
.
Raw
.
BlockHash
],
db
.
Deposit
{
if
s
.
isBedrock
{
TxHash
:
iter
.
Event
.
Raw
.
TxHash
,
receipt
:=
receipts
[
ev
.
Raw
.
TxHash
]
L1Token
:
iter
.
Event
.
L1Token
,
if
receipt
==
nil
{
L2Token
:
iter
.
Event
.
L2Token
,
receipt
,
err
=
s
.
client
.
TransactionReceipt
(
ctx
,
ev
.
Raw
.
TxHash
)
FromAddress
:
iter
.
Event
.
From
,
if
err
!=
nil
{
ToAddress
:
iter
.
Event
.
To
,
return
nil
,
err
Amount
:
iter
.
Event
.
Amount
,
}
Data
:
iter
.
Event
.
ExtraData
,
receipts
[
ev
.
Raw
.
TxHash
]
=
receipt
LogIndex
:
iter
.
Event
.
Raw
.
Index
,
}
})
}
if
err
:=
iter
.
Error
();
err
!=
nil
{
return
nil
,
err
}
return
depositsByBlockhash
,
nil
var
withdrawalInitiated
*
bindings
.
L2ToL1MessagePasserMessagePassed
}
for
_
,
eLog
:=
range
receipt
.
Logs
{
if
len
(
eLog
.
Topics
)
==
0
||
eLog
.
Topics
[
0
]
!=
withdrawals
.
MessagePassedTopic
{
continue
}
func
(
s
*
StandardBridge
)
GetWithdrawalsByBlockRange
(
start
,
end
uint64
)
(
WithdrawalsMap
,
error
)
{
if
withdrawalInitiated
!=
nil
{
withdrawalsByBlockhash
:=
make
(
map
[
common
.
Hash
][]
db
.
Withdrawal
)
logger
.
Warn
(
"detected multiple withdrawal initiated events! ignoring"
,
"tx_hash"
,
ev
.
Raw
.
TxHash
)
continue
}
iter
,
err
:=
FilterWithdrawalInitiatedWithRetry
(
s
.
ctx
,
s
.
filterer
,
&
bind
.
FilterOpts
{
withdrawalInitiated
,
err
=
s
.
l2L1MP
.
ParseMessagePassed
(
*
eLog
)
Start
:
start
,
if
err
!=
nil
{
End
:
&
end
,
return
nil
,
err
})
}
if
err
!=
nil
{
}
logger
.
Error
(
"Error fetching filter"
,
"err"
,
err
)
}
for
iter
.
Next
()
{
hash
,
err
:=
withdrawals
.
WithdrawalHash
(
withdrawalInitiated
)
withdrawalsByBlockhash
[
iter
.
Event
.
Raw
.
BlockHash
]
=
append
(
if
err
!=
nil
{
withdrawalsByBlockhash
[
iter
.
Event
.
Raw
.
BlockHash
],
db
.
Withdrawal
{
return
nil
,
err
TxHash
:
iter
.
Event
.
Raw
.
TxHash
,
}
L1Token
:
iter
.
Event
.
L1Token
,
L2Token
:
iter
.
Event
.
L2Token
,
withdrawalsByBlockhash
[
ev
.
Raw
.
BlockHash
]
=
append
(
FromAddress
:
iter
.
Event
.
From
,
withdrawalsByBlockhash
[
ev
.
Raw
.
BlockHash
],
db
.
Withdrawal
{
ToAddress
:
iter
.
Event
.
To
,
TxHash
:
ev
.
Raw
.
TxHash
,
Amount
:
iter
.
Event
.
Amount
,
L1Token
:
ev
.
L1Token
,
Data
:
iter
.
Event
.
ExtraData
,
L2Token
:
ev
.
L2Token
,
LogIndex
:
iter
.
Event
.
Raw
.
Index
,
FromAddress
:
ev
.
From
,
})
ToAddress
:
ev
.
To
,
}
Amount
:
ev
.
Amount
,
if
err
:=
iter
.
Error
();
err
!=
nil
{
Data
:
ev
.
ExtraData
,
return
nil
,
err
LogIndex
:
ev
.
Raw
.
Index
,
BedrockHash
:
&
hash
,
},
)
}
else
{
withdrawalsByBlockhash
[
ev
.
Raw
.
BlockHash
]
=
append
(
withdrawalsByBlockhash
[
ev
.
Raw
.
BlockHash
],
db
.
Withdrawal
{
TxHash
:
ev
.
Raw
.
TxHash
,
L1Token
:
ev
.
L1Token
,
L2Token
:
ev
.
L2Token
,
FromAddress
:
ev
.
From
,
ToAddress
:
ev
.
To
,
Amount
:
ev
.
Amount
,
Data
:
ev
.
ExtraData
,
LogIndex
:
ev
.
Raw
.
Index
,
},
)
}
}
}
return
withdrawalsByBlockhash
,
nil
return
withdrawalsByBlockhash
,
iter
.
Error
()
}
}
func
(
s
*
StandardBridge
)
String
()
string
{
func
(
s
*
StandardBridge
)
String
()
string
{
...
...
indexer/services/l2/confirmed_headers.go
View file @
5a9928c0
...
@@ -147,8 +147,7 @@ func (f *ConfirmedHeaderSelector) NewHead(
...
@@ -147,8 +147,7 @@ func (f *ConfirmedHeaderSelector) NewHead(
return
headers
,
nil
return
headers
,
nil
}
}
func
NewConfirmedHeaderSelector
(
cfg
HeaderSelectorConfig
)
(
*
ConfirmedHeaderSelector
,
func
NewConfirmedHeaderSelector
(
cfg
HeaderSelectorConfig
)
(
*
ConfirmedHeaderSelector
,
error
)
{
error
)
{
if
cfg
.
ConfDepth
==
0
{
if
cfg
.
ConfDepth
==
0
{
return
nil
,
errors
.
New
(
"ConfDepth must be greater than zero"
)
return
nil
,
errors
.
New
(
"ConfDepth must be greater than zero"
)
}
}
...
...
indexer/services/l2/query.go
deleted
100644 → 0
View file @
475b2bfa
package
l2
import
(
"github.com/ethereum-optimism/optimism/indexer/db"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)
func
QueryERC20
(
address
common
.
Address
,
client
*
ethclient
.
Client
)
(
*
db
.
Token
,
error
)
{
contract
,
err
:=
bindings
.
NewERC20
(
address
,
client
)
if
err
!=
nil
{
return
nil
,
err
}
name
,
err
:=
contract
.
Name
(
&
bind
.
CallOpts
{})
if
err
!=
nil
{
return
nil
,
err
}
symbol
,
err
:=
contract
.
Symbol
(
&
bind
.
CallOpts
{})
if
err
!=
nil
{
return
nil
,
err
}
decimals
,
err
:=
contract
.
Decimals
(
&
bind
.
CallOpts
{})
if
err
!=
nil
{
return
nil
,
err
}
return
&
db
.
Token
{
Name
:
name
,
Symbol
:
symbol
,
Decimals
:
decimals
,
},
nil
}
indexer/services/l2/service.go
View file @
5a9928c0
...
@@ -12,6 +12,7 @@ import (
...
@@ -12,6 +12,7 @@ import (
"github.com/ethereum-optimism/optimism/indexer/metrics"
"github.com/ethereum-optimism/optimism/indexer/metrics"
"github.com/ethereum-optimism/optimism/indexer/server"
"github.com/ethereum-optimism/optimism/indexer/server"
"github.com/ethereum-optimism/optimism/indexer/services/query"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus"
"github.com/ethereum-optimism/optimism/indexer/db"
"github.com/ethereum-optimism/optimism/indexer/db"
...
@@ -38,37 +39,18 @@ var errWrongChainID = errors.New("wrong chain id provided")
...
@@ -38,37 +39,18 @@ var errWrongChainID = errors.New("wrong chain id provided")
var
errNoNewBlocks
=
errors
.
New
(
"no new blocks"
)
var
errNoNewBlocks
=
errors
.
New
(
"no new blocks"
)
// clientRetryInterval is the interval to wait between retrying client API
// calls.
var
clientRetryInterval
=
5
*
time
.
Second
// HeaderByNumberWithRetry retries the given func until it succeeds, waiting
// for clientRetryInterval duration after every call.
func
HeaderByNumberWithRetry
(
ctx
context
.
Context
,
client
*
ethclient
.
Client
)
(
*
types
.
Header
,
error
)
{
for
{
res
,
err
:=
client
.
HeaderByNumber
(
ctx
,
nil
)
switch
err
{
case
nil
:
return
res
,
err
default
:
log
.
Error
(
"Error fetching header"
,
"err"
,
err
)
}
time
.
Sleep
(
clientRetryInterval
)
}
}
type
ServiceConfig
struct
{
type
ServiceConfig
struct
{
Context
context
.
Context
Context
context
.
Context
Metrics
*
metrics
.
Metrics
Metrics
*
metrics
.
Metrics
L2RPC
*
rpc
.
Client
L2RPC
*
rpc
.
Client
L2Client
*
ethclient
.
Client
L2Client
*
ethclient
.
Client
ChainID
*
big
.
Int
ChainID
*
big
.
Int
ConfDepth
uint64
ConfDepth
uint64
MaxHeaderBatchSize
uint64
MaxHeaderBatchSize
uint64
StartBlockNumber
uint64
StartBlockNumber
uint64
StartBlockHash
string
DB
*
db
.
Database
DB
*
db
.
Database
Bedrock
bool
}
}
type
Service
struct
{
type
Service
struct
{
...
@@ -113,7 +95,7 @@ func NewService(cfg ServiceConfig) (*Service, error) {
...
@@ -113,7 +95,7 @@ func NewService(cfg ServiceConfig) (*Service, error) {
cfg
.
ChainID
=
chainID
cfg
.
ChainID
=
chainID
}
}
bridges
,
err
:=
bridge
.
BridgesByChainID
(
cfg
.
ChainID
,
cfg
.
L2Client
,
c
tx
)
bridges
,
err
:=
bridge
.
BridgesByChainID
(
cfg
.
ChainID
,
cfg
.
L2Client
,
c
fg
.
Bedrock
)
if
err
!=
nil
{
if
err
!=
nil
{
cancel
()
cancel
()
return
nil
,
err
return
nil
,
err
...
@@ -131,7 +113,7 @@ func NewService(cfg ServiceConfig) (*Service, error) {
...
@@ -131,7 +113,7 @@ func NewService(cfg ServiceConfig) (*Service, error) {
return
nil
,
err
return
nil
,
err
}
}
return
&
Service
{
service
:=
&
Service
{
cfg
:
cfg
,
cfg
:
cfg
,
ctx
:
ctx
,
ctx
:
ctx
,
cancel
:
cancel
,
cancel
:
cancel
,
...
@@ -141,12 +123,16 @@ func NewService(cfg ServiceConfig) (*Service, error) {
...
@@ -141,12 +123,16 @@ func NewService(cfg ServiceConfig) (*Service, error) {
tokenCache
:
map
[
common
.
Address
]
*
db
.
Token
{
tokenCache
:
map
[
common
.
Address
]
*
db
.
Token
{
db
.
ETHL2Address
:
db
.
ETHL1Token
,
db
.
ETHL2Address
:
db
.
ETHL1Token
,
},
},
},
nil
}
service
.
wg
.
Add
(
1
)
return
service
,
nil
}
}
func
(
s
*
Service
)
Loop
(
ctx
context
.
Context
)
{
func
(
s
*
Service
)
loop
()
{
defer
s
.
wg
.
Done
()
for
{
for
{
err
:=
s
.
catchUp
(
ctx
)
err
:=
s
.
catchUp
()
if
err
==
nil
{
if
err
==
nil
{
break
break
}
}
...
@@ -160,10 +146,18 @@ func (s *Service) Loop(ctx context.Context) {
...
@@ -160,10 +146,18 @@ func (s *Service) Loop(ctx context.Context) {
}
}
newHeads
:=
make
(
chan
*
types
.
Header
,
1000
)
newHeads
:=
make
(
chan
*
types
.
Header
,
1000
)
go
s
.
subscribeNewHeads
(
ctx
,
newHeads
)
tick
:=
time
.
NewTicker
(
5
*
time
.
Second
)
defer
tick
.
Stop
()
for
{
for
{
select
{
select
{
case
<-
tick
.
C
:
header
,
err
:=
query
.
HeaderByNumberWithRetry
(
s
.
ctx
,
s
.
cfg
.
L2Client
)
if
err
!=
nil
{
logger
.
Error
(
"error fetching header by number"
,
"err"
,
err
)
continue
}
newHeads
<-
header
case
header
:=
<-
newHeads
:
case
header
:=
<-
newHeads
:
logger
.
Info
(
"Received new header"
,
"header"
,
header
.
Hash
)
logger
.
Info
(
"Received new header"
,
"header"
,
header
.
Hash
)
for
{
for
{
...
@@ -176,6 +170,7 @@ func (s *Service) Loop(ctx context.Context) {
...
@@ -176,6 +170,7 @@ func (s *Service) Loop(ctx context.Context) {
}
}
}
}
case
<-
s
.
ctx
.
Done
()
:
case
<-
s
.
ctx
.
Done
()
:
logger
.
Info
(
"service stopped"
)
return
return
}
}
}
}
...
@@ -184,7 +179,6 @@ func (s *Service) Loop(ctx context.Context) {
...
@@ -184,7 +179,6 @@ func (s *Service) Loop(ctx context.Context) {
func
(
s
*
Service
)
Update
(
newHeader
*
types
.
Header
)
error
{
func
(
s
*
Service
)
Update
(
newHeader
*
types
.
Header
)
error
{
var
lowest
=
db
.
BlockLocator
{
var
lowest
=
db
.
BlockLocator
{
Number
:
s
.
cfg
.
StartBlockNumber
,
Number
:
s
.
cfg
.
StartBlockNumber
,
Hash
:
common
.
HexToHash
(
s
.
cfg
.
StartBlockHash
),
}
}
highestConfirmed
,
err
:=
s
.
cfg
.
DB
.
GetHighestL2Block
()
highestConfirmed
,
err
:=
s
.
cfg
.
DB
.
GetHighestL2Block
()
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -209,7 +203,7 @@ func (s *Service) Update(newHeader *types.Header) error {
...
@@ -209,7 +203,7 @@ func (s *Service) Update(newHeader *types.Header) error {
return
nil
return
nil
}
}
if
lowest
.
Hash
!=
headers
[
0
]
.
ParentHash
{
if
lowest
.
Number
>
0
&&
lowest
.
Hash
!=
headers
[
0
]
.
ParentHash
{
logger
.
Error
(
"Parent hash does not connect to "
,
logger
.
Error
(
"Parent hash does not connect to "
,
"block"
,
headers
[
0
]
.
Number
.
Uint64
(),
"hash"
,
headers
[
0
]
.
Hash
(),
"block"
,
headers
[
0
]
.
Number
.
Uint64
(),
"hash"
,
headers
[
0
]
.
Hash
(),
"lowest_block"
,
lowest
.
Number
,
"hash"
,
lowest
.
Hash
)
"lowest_block"
,
lowest
.
Number
,
"hash"
,
lowest
.
Hash
)
...
@@ -218,7 +212,6 @@ func (s *Service) Update(newHeader *types.Header) error {
...
@@ -218,7 +212,6 @@ func (s *Service) Update(newHeader *types.Header) error {
startHeight
:=
headers
[
0
]
.
Number
.
Uint64
()
startHeight
:=
headers
[
0
]
.
Number
.
Uint64
()
endHeight
:=
headers
[
len
(
headers
)
-
1
]
.
Number
.
Uint64
()
endHeight
:=
headers
[
len
(
headers
)
-
1
]
.
Number
.
Uint64
()
depositsByBlockHash
:=
make
(
map
[
common
.
Hash
][]
db
.
Deposit
)
withdrawalsByBlockHash
:=
make
(
map
[
common
.
Hash
][]
db
.
Withdrawal
)
withdrawalsByBlockHash
:=
make
(
map
[
common
.
Hash
][]
db
.
Withdrawal
)
start
:=
prometheus
.
NewTimer
(
s
.
metrics
.
UpdateDuration
.
WithLabelValues
(
"l2"
))
start
:=
prometheus
.
NewTimer
(
s
.
metrics
.
UpdateDuration
.
WithLabelValues
(
"l2"
))
...
@@ -227,21 +220,12 @@ func (s *Service) Update(newHeader *types.Header) error {
...
@@ -227,21 +220,12 @@ func (s *Service) Update(newHeader *types.Header) error {
logger
.
Info
(
"updated index"
,
"start_height"
,
startHeight
,
"end_height"
,
endHeight
,
"duration"
,
dur
)
logger
.
Info
(
"updated index"
,
"start_height"
,
startHeight
,
"end_height"
,
endHeight
,
"duration"
,
dur
)
}()
}()
bridgeDepositsCh
:=
make
(
chan
bridge
.
DepositsMap
,
len
(
s
.
bridges
))
bridgeWdsCh
:=
make
(
chan
bridge
.
WithdrawalsMap
)
bridgeWdsCh
:=
make
(
chan
bridge
.
WithdrawalsMap
)
errCh
:=
make
(
chan
error
,
len
(
s
.
bridges
))
errCh
:=
make
(
chan
error
,
len
(
s
.
bridges
))
for
_
,
bridgeImpl
:=
range
s
.
bridges
{
for
_
,
bridgeImpl
:=
range
s
.
bridges
{
go
func
(
b
bridge
.
Bridge
)
{
go
func
(
b
bridge
.
Bridge
)
{
deposits
,
err
:=
b
.
GetDepositsByBlockRange
(
startHeight
,
endHeight
)
wds
,
err
:=
b
.
GetWithdrawalsByBlockRange
(
s
.
ctx
,
startHeight
,
endHeight
)
if
err
!=
nil
{
errCh
<-
err
return
}
bridgeDepositsCh
<-
deposits
}(
bridgeImpl
)
go
func
(
b
bridge
.
Bridge
)
{
wds
,
err
:=
b
.
GetWithdrawalsByBlockRange
(
startHeight
,
endHeight
)
if
err
!=
nil
{
if
err
!=
nil
{
errCh
<-
err
errCh
<-
err
return
return
...
@@ -256,29 +240,19 @@ func (s *Service) Update(newHeader *types.Header) error {
...
@@ -256,29 +240,19 @@ func (s *Service) Update(newHeader *types.Header) error {
case
bridgeWds
:=
<-
bridgeWdsCh
:
case
bridgeWds
:=
<-
bridgeWdsCh
:
for
blockHash
,
withdrawals
:=
range
bridgeWds
{
for
blockHash
,
withdrawals
:=
range
bridgeWds
{
for
_
,
wd
:=
range
withdrawals
{
for
_
,
wd
:=
range
withdrawals
{
if
err
:=
s
.
cacheToken
(
wd
.
L2Token
);
err
!=
nil
{
if
err
:=
s
.
cacheToken
(
wd
);
err
!=
nil
{
logger
.
Warn
(
"error caching token"
,
"err"
,
err
)
logger
.
Warn
(
"error caching token"
,
"err"
,
err
)
}
}
}
}
withdrawalsByBlockHash
[
blockHash
]
=
append
(
withdrawalsByBlockHash
[
blockHash
],
withdrawals
...
)
withdrawalsByBlockHash
[
blockHash
]
=
append
(
withdrawalsByBlockHash
[
blockHash
],
withdrawals
...
)
}
}
case
bridgeDeposits
:=
<-
bridgeDepositsCh
:
for
blockHash
,
deposits
:=
range
bridgeDeposits
{
for
_
,
deposit
:=
range
deposits
{
if
err
:=
s
.
cacheToken
(
deposit
.
L2Token
);
err
!=
nil
{
logger
.
Warn
(
"error caching token"
,
"err"
,
err
)
}
}
depositsByBlockHash
[
blockHash
]
=
append
(
depositsByBlockHash
[
blockHash
],
deposits
...
)
}
case
err
:=
<-
errCh
:
case
err
:=
<-
errCh
:
return
err
return
err
}
}
receives
++
receives
++
if
receives
==
2
*
len
(
s
.
bridges
)
{
if
receives
==
len
(
s
.
bridges
)
{
break
break
}
}
}
}
...
@@ -356,8 +330,21 @@ func (s *Service) GetIndexerStatus(w http.ResponseWriter, r *http.Request) {
...
@@ -356,8 +330,21 @@ func (s *Service) GetIndexerStatus(w http.ResponseWriter, r *http.Request) {
server
.
RespondWithJSON
(
w
,
http
.
StatusOK
,
status
)
server
.
RespondWithJSON
(
w
,
http
.
StatusOK
,
status
)
}
}
func
(
s
*
Service
)
GetWithdrawalStatus
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
func
(
s
*
Service
)
GetWithdrawalBatch
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
// Temporary stub until rest of indexer is landed
vars
:=
mux
.
Vars
(
r
)
hash
:=
vars
[
"hash"
]
if
hash
==
""
{
server
.
RespondWithError
(
w
,
http
.
StatusBadRequest
,
"must specify a hash"
)
return
}
batch
,
err
:=
s
.
cfg
.
DB
.
GetWithdrawalBatch
(
common
.
HexToHash
(
vars
[
"hash"
]))
if
err
!=
nil
{
server
.
RespondWithError
(
w
,
http
.
StatusInternalServerError
,
err
.
Error
())
return
}
server
.
RespondWithJSON
(
w
,
http
.
StatusOK
,
batch
)
}
}
func
(
s
*
Service
)
GetWithdrawals
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
func
(
s
*
Service
)
GetWithdrawals
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
...
@@ -380,12 +367,14 @@ func (s *Service) GetWithdrawals(w http.ResponseWriter, r *http.Request) {
...
@@ -380,12 +367,14 @@ func (s *Service) GetWithdrawals(w http.ResponseWriter, r *http.Request) {
return
return
}
}
finalizationState
:=
db
.
ParseFinalizationState
(
r
.
URL
.
Query
()
.
Get
(
"finalized"
))
page
:=
db
.
PaginationParam
{
page
:=
db
.
PaginationParam
{
Limit
:
uint64
(
limit
)
,
Limit
:
limit
,
Offset
:
uint64
(
offset
)
,
Offset
:
offset
,
}
}
withdrawals
,
err
:=
s
.
cfg
.
DB
.
GetWithdrawalsByAddress
(
common
.
HexToAddress
(
vars
[
"address"
]),
page
,
db
.
FinalizationStateAny
)
withdrawals
,
err
:=
s
.
cfg
.
DB
.
GetWithdrawalsByAddress
(
common
.
HexToAddress
(
vars
[
"address"
]),
page
,
finalizationState
)
if
err
!=
nil
{
if
err
!=
nil
{
server
.
RespondWithError
(
w
,
http
.
StatusInternalServerError
,
err
.
Error
())
server
.
RespondWithError
(
w
,
http
.
StatusInternalServerError
,
err
.
Error
())
return
return
...
@@ -394,25 +383,8 @@ func (s *Service) GetWithdrawals(w http.ResponseWriter, r *http.Request) {
...
@@ -394,25 +383,8 @@ func (s *Service) GetWithdrawals(w http.ResponseWriter, r *http.Request) {
server
.
RespondWithJSON
(
w
,
http
.
StatusOK
,
withdrawals
)
server
.
RespondWithJSON
(
w
,
http
.
StatusOK
,
withdrawals
)
}
}
func
(
s
*
Service
)
subscribeNewHeads
(
ctx
context
.
Context
,
heads
chan
*
types
.
Header
)
{
func
(
s
*
Service
)
catchUp
()
error
{
tick
:=
time
.
NewTicker
(
5
*
time
.
Second
)
realHead
,
err
:=
query
.
HeaderByNumberWithRetry
(
s
.
ctx
,
s
.
cfg
.
L2Client
)
for
{
select
{
case
<-
tick
.
C
:
header
,
err
:=
HeaderByNumberWithRetry
(
ctx
,
s
.
cfg
.
L2Client
)
if
err
!=
nil
{
logger
.
Error
(
"error fetching header by number"
,
"err"
,
err
)
}
heads
<-
header
case
<-
ctx
.
Done
()
:
return
}
}
}
func
(
s
*
Service
)
catchUp
(
ctx
context
.
Context
)
error
{
realHead
,
err
:=
HeaderByNumberWithRetry
(
ctx
,
s
.
cfg
.
L2Client
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -436,8 +408,8 @@ func (s *Service) catchUp(ctx context.Context) error {
...
@@ -436,8 +408,8 @@ func (s *Service) catchUp(ctx context.Context) error {
for
realHeadNum
-
s
.
cfg
.
ConfDepth
>
currHeadNum
+
s
.
cfg
.
MaxHeaderBatchSize
{
for
realHeadNum
-
s
.
cfg
.
ConfDepth
>
currHeadNum
+
s
.
cfg
.
MaxHeaderBatchSize
{
select
{
select
{
case
<-
ctx
.
Done
()
:
case
<-
s
.
ctx
.
Done
()
:
return
context
.
Canceled
return
s
.
ctx
.
Err
()
default
:
default
:
if
err
:=
s
.
Update
(
realHead
);
err
!=
nil
&&
err
!=
errNoNewBlocks
{
if
err
:=
s
.
Update
(
realHead
);
err
!=
nil
&&
err
!=
errNoNewBlocks
{
return
err
return
err
...
@@ -455,32 +427,32 @@ func (s *Service) catchUp(ctx context.Context) error {
...
@@ -455,32 +427,32 @@ func (s *Service) catchUp(ctx context.Context) error {
return
nil
return
nil
}
}
func
(
s
*
Service
)
cacheToken
(
address
common
.
Address
)
error
{
func
(
s
*
Service
)
cacheToken
(
withdrawal
db
.
Withdrawal
)
error
{
if
s
.
tokenCache
[
address
]
!=
nil
{
if
s
.
tokenCache
[
withdrawal
.
L2Token
]
!=
nil
{
return
nil
return
nil
}
}
token
,
err
:=
s
.
cfg
.
DB
.
GetL2TokenByAddress
(
address
.
String
())
token
,
err
:=
s
.
cfg
.
DB
.
GetL2TokenByAddress
(
withdrawal
.
L2Token
.
String
())
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
if
token
!=
nil
{
if
token
!=
nil
{
s
.
metrics
.
IncL2CachedTokensCount
()
s
.
metrics
.
IncL2CachedTokensCount
()
s
.
tokenCache
[
address
]
=
token
s
.
tokenCache
[
withdrawal
.
L2Token
]
=
token
return
nil
return
nil
}
}
token
,
err
=
QueryERC20
(
address
,
s
.
cfg
.
L2Client
)
token
,
err
=
query
.
NewERC20
(
withdrawal
.
L2Token
,
s
.
cfg
.
L2Client
)
if
err
!=
nil
{
if
err
!=
nil
{
logger
.
Error
(
"Error querying ERC20 token details"
,
logger
.
Error
(
"Error querying ERC20 token details"
,
"l2_token"
,
address
.
String
(),
"err"
,
err
)
"l2_token"
,
withdrawal
.
L2Token
.
String
(),
"err"
,
err
)
token
=
&
db
.
Token
{
token
=
&
db
.
Token
{
Address
:
address
.
String
(),
Address
:
withdrawal
.
L2Token
.
String
(),
}
}
}
}
if
err
:=
s
.
cfg
.
DB
.
AddL2Token
(
address
.
String
(),
token
);
err
!=
nil
{
if
err
:=
s
.
cfg
.
DB
.
AddL2Token
(
withdrawal
.
L2Token
.
String
(),
token
);
err
!=
nil
{
return
err
return
err
}
}
s
.
tokenCache
[
address
]
=
token
s
.
tokenCache
[
withdrawal
.
L2Token
]
=
token
s
.
metrics
.
IncL2CachedTokensCount
()
s
.
metrics
.
IncL2CachedTokensCount
()
return
nil
return
nil
}
}
...
@@ -489,16 +461,11 @@ func (s *Service) Start() error {
...
@@ -489,16 +461,11 @@ func (s *Service) Start() error {
if
s
.
cfg
.
ChainID
==
nil
{
if
s
.
cfg
.
ChainID
==
nil
{
return
errNoChainID
return
errNoChainID
}
}
s
.
wg
.
Add
(
1
)
go
s
.
loop
()
go
s
.
Loop
(
s
.
ctx
)
return
nil
return
nil
}
}
func
(
s
*
Service
)
Stop
()
{
func
(
s
*
Service
)
Stop
()
{
s
.
cancel
()
s
.
cancel
()
s
.
wg
.
Wait
()
s
.
wg
.
Wait
()
err
:=
s
.
cfg
.
DB
.
Close
()
if
err
!=
nil
{
logger
.
Error
(
"Error closing db"
,
"err"
,
err
)
}
}
}
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