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
fc64f875
Commit
fc64f875
authored
Jun 21, 2023
by
Kevin Chen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fault-detector: Remove pre-bedrock support.
parent
52eb1a26
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
141 additions
and
258 deletions
+141
-258
helpers.ts
packages/fault-detector/src/helpers.ts
+9
-9
service.ts
packages/fault-detector/src/service.ts
+131
-248
helpers.spec.ts
packages/fault-detector/test/helpers.spec.ts
+1
-1
No files found.
packages/fault-detector/src/helpers.ts
View file @
fc64f875
import
{
Contract
,
BigNumber
}
from
'
ethers
'
import
{
Contract
,
BigNumber
}
from
'
ethers
'
import
{
Logger
}
from
'
@eth-optimism/common-ts
'
import
{
Logger
}
from
'
@eth-optimism/common-ts
'
export
interface
OutputOracle
<
TSubmissionEventArgs
>
{
export
interface
OutputOracle
{
contract
:
Contract
contract
:
Contract
filter
:
any
filter
:
any
getTotalElements
:
()
=>
Promise
<
BigNumber
>
getTotalElements
:
()
=>
Promise
<
BigNumber
>
getEventIndex
:
(
args
:
TSubmissionEventArgs
)
=>
BigNumber
getEventIndex
:
(
args
:
any
)
=>
BigNumber
}
}
/**
/**
...
@@ -54,8 +54,8 @@ const getCache = (
...
@@ -54,8 +54,8 @@ const getCache = (
* @param contract Contract to update cache for.
* @param contract Contract to update cache for.
* @param filter Event filter to use.
* @param filter Event filter to use.
*/
*/
export
const
updateOracleCache
=
async
<
TSubmissionEventArgs
>
(
export
const
updateOracleCache
=
async
(
oracle
:
OutputOracle
<
TSubmissionEventArgs
>
,
oracle
:
OutputOracle
,
logger
?:
Logger
logger
?:
Logger
):
Promise
<
void
>
=>
{
):
Promise
<
void
>
=>
{
const
cache
=
getCache
(
oracle
.
contract
.
address
)
const
cache
=
getCache
(
oracle
.
contract
.
address
)
...
@@ -86,7 +86,7 @@ export const updateOracleCache = async <TSubmissionEventArgs>(
...
@@ -86,7 +86,7 @@ export const updateOracleCache = async <TSubmissionEventArgs>(
// Throw the events into the cache.
// Throw the events into the cache.
for
(
const
event
of
events
)
{
for
(
const
event
of
events
)
{
cache
.
eventCache
[
cache
.
eventCache
[
oracle
.
getEventIndex
(
event
.
args
as
TSubmissionEventArgs
).
toNumber
()
oracle
.
getEventIndex
(
event
.
args
).
toNumber
()
]
=
{
]
=
{
blockNumber
:
event
.
blockNumber
,
blockNumber
:
event
.
blockNumber
,
transactionHash
:
event
.
transactionHash
,
transactionHash
:
event
.
transactionHash
,
...
@@ -135,8 +135,8 @@ export const updateOracleCache = async <TSubmissionEventArgs>(
...
@@ -135,8 +135,8 @@ export const updateOracleCache = async <TSubmissionEventArgs>(
* @param index State batch index to search for.
* @param index State batch index to search for.
* @returns Event corresponding to the batch.
* @returns Event corresponding to the batch.
*/
*/
export
const
findEventForStateBatch
=
async
<
TSubmissionEventArgs
>
(
export
const
findEventForStateBatch
=
async
(
oracle
:
OutputOracle
<
TSubmissionEventArgs
>
,
oracle
:
OutputOracle
,
index
:
number
,
index
:
number
,
logger
?:
Logger
logger
?:
Logger
):
Promise
<
PartialEvent
>
=>
{
):
Promise
<
PartialEvent
>
=>
{
...
@@ -166,8 +166,8 @@ export const findEventForStateBatch = async <TSubmissionEventArgs>(
...
@@ -166,8 +166,8 @@ export const findEventForStateBatch = async <TSubmissionEventArgs>(
* @param oracle Output oracle contract.
* @param oracle Output oracle contract.
* @returns Starting state root batch index.
* @returns Starting state root batch index.
*/
*/
export
const
findFirstUnfinalizedStateBatchIndex
=
async
<
TSubmissionEventArgs
>
(
export
const
findFirstUnfinalizedStateBatchIndex
=
async
(
oracle
:
OutputOracle
<
TSubmissionEventArgs
>
,
oracle
:
OutputOracle
,
fpw
:
number
,
fpw
:
number
,
logger
?:
Logger
logger
?:
Logger
):
Promise
<
number
>
=>
{
):
Promise
<
number
>
=>
{
...
...
packages/fault-detector/src/service.ts
View file @
fc64f875
...
@@ -32,8 +32,9 @@ type Options = {
...
@@ -32,8 +32,9 @@ type Options = {
l1RpcProvider
:
Provider
l1RpcProvider
:
Provider
l2RpcProvider
:
Provider
l2RpcProvider
:
Provider
startBatchIndex
:
number
startBatchIndex
:
number
bedrock
:
boolean
optimismPortalAddress
?:
string
optimismPortalAddress
?:
string
// Deprecated. Bedrock is the only version we support.
bedrock
:
boolean
stateCommitmentChainAddress
?:
string
stateCommitmentChainAddress
?:
string
}
}
...
@@ -44,8 +45,8 @@ type Metrics = {
...
@@ -44,8 +45,8 @@ type Metrics = {
}
}
type
State
=
{
type
State
=
{
f
p
w
:
number
f
aultProofWindo
w
:
number
o
o
:
OutputOracle
<
any
>
o
utputOracle
:
OutputOracle
messenger
:
CrossChainMessenger
messenger
:
CrossChainMessenger
currentBatchIndex
:
number
currentBatchIndex
:
number
diverged
:
boolean
diverged
:
boolean
...
@@ -76,22 +77,23 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
...
@@ -76,22 +77,23 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
desc
:
'
Batch index to start checking from. For bedrock chains, this is the L2 height to start from
'
,
desc
:
'
Batch index to start checking from. For bedrock chains, this is the L2 height to start from
'
,
public
:
true
,
public
:
true
,
},
},
bedrock
:
{
validator
:
validators
.
bool
,
default
:
true
,
desc
:
'
Whether or not the service is running against a Bedrock chain
'
,
public
:
true
,
},
optimismPortalAddress
:
{
optimismPortalAddress
:
{
validator
:
validators
.
str
,
validator
:
validators
.
str
,
default
:
ethers
.
constants
.
AddressZero
,
default
:
ethers
.
constants
.
AddressZero
,
desc
:
'
[Custom Bedrock Chains] Deployed OptimismPortal contract address. Used to retrieve necessary info for ouput verification
'
,
desc
:
'
Deployed OptimismPortal contract address. Used to retrieve necessary info for ouput verification
'
,
public
:
true
,
},
// Deprecated flags.
bedrock
:
{
validator
:
validators
.
bool
,
default
:
true
,
desc
:
'
[Deprecated, must be set to true] Whether or not the service is running against a Bedrock chain
'
,
public
:
true
,
public
:
true
,
},
},
stateCommitmentChainAddress
:
{
stateCommitmentChainAddress
:
{
validator
:
validators
.
str
,
validator
:
validators
.
str
,
default
:
ethers
.
constants
.
AddressZero
,
default
:
ethers
.
constants
.
AddressZero
,
desc
:
'
[
Custom Legacy Chains
] Deployed StateCommitmentChain contract address. Used to fetch necessary info for output verification.
'
,
desc
:
'
[
Deprecated, must be set to 0x0
] Deployed StateCommitmentChain contract address. Used to fetch necessary info for output verification.
'
,
public
:
true
,
public
:
true
,
},
},
},
},
...
@@ -119,10 +121,9 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
...
@@ -119,10 +121,9 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
* will fallback to the pre-defined set of addresses from options, otherwise aborting if unset.
* will fallback to the pre-defined set of addresses from options, otherwise aborting if unset.
*
*
* Required Contracts
* Required Contracts
* -
Bedrock:
OptimismPortal (used to also fetch L2OutputOracle address variable). This is the preferred address
* - OptimismPortal (used to also fetch L2OutputOracle address variable). This is the preferred address
* since in early versions of bedrock, OptimismPortal holds the FINALIZATION_WINDOW variable instead of L2OutputOracle.
* since in early versions of bedrock, OptimismPortal holds the FINALIZATION_WINDOW variable instead of L2OutputOracle.
* The retrieved L2OutputOracle address from OptimismPortal is used to query for output roots.
* The retrieved L2OutputOracle address from OptimismPortal is used to query for output roots.
* - Legacy: StateCommitmentChain to query for output roots.
*
*
* @param l2ChainId op chain id
* @param l2ChainId op chain id
* @returns OEL1ContractsLike set of L1 contracts with only the required addresses set
* @returns OEL1ContractsLike set of L1 contracts with only the required addresses set
...
@@ -130,19 +131,17 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
...
@@ -130,19 +131,17 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
async
getOEL1Contracts
(
l2ChainId
:
number
):
Promise
<
OEL1ContractsLike
>
{
async
getOEL1Contracts
(
l2ChainId
:
number
):
Promise
<
OEL1ContractsLike
>
{
// CrossChainMessenger requires all address to be defined. Default to `AddressZero` to ignore unused contracts
// CrossChainMessenger requires all address to be defined. Default to `AddressZero` to ignore unused contracts
let
contracts
:
OEL1ContractsLike
=
{
let
contracts
:
OEL1ContractsLike
=
{
OptimismPortal
:
ethers
.
constants
.
AddressZero
,
L2OutputOracle
:
ethers
.
constants
.
AddressZero
,
// Unused contracts
AddressManager
:
ethers
.
constants
.
AddressZero
,
AddressManager
:
ethers
.
constants
.
AddressZero
,
BondManager
:
ethers
.
constants
.
AddressZero
,
CanonicalTransactionChain
:
ethers
.
constants
.
AddressZero
,
L1CrossDomainMessenger
:
ethers
.
constants
.
AddressZero
,
L1CrossDomainMessenger
:
ethers
.
constants
.
AddressZero
,
L1StandardBridge
:
ethers
.
constants
.
AddressZero
,
L1StandardBridge
:
ethers
.
constants
.
AddressZero
,
StateCommitmentChain
:
ethers
.
constants
.
AddressZero
,
StateCommitmentChain
:
ethers
.
constants
.
AddressZero
,
CanonicalTransactionChain
:
ethers
.
constants
.
AddressZero
,
BondManager
:
ethers
.
constants
.
AddressZero
,
OptimismPortal
:
ethers
.
constants
.
AddressZero
,
L2OutputOracle
:
ethers
.
constants
.
AddressZero
,
}
}
const
chainType
=
this
.
options
.
bedrock
?
'
bedrock
'
:
'
legacy
'
this
.
logger
.
info
(
`Setting contracts for OP chain type:
${
chainType
}
`
)
const
knownChainId
=
L2ChainID
[
l2ChainId
]
!==
undefined
const
knownChainId
=
L2ChainID
[
l2ChainId
]
!==
undefined
if
(
knownChainId
)
{
if
(
knownChainId
)
{
this
.
logger
.
info
(
`Recognized L2 chain id
${
L2ChainID
[
l2ChainId
]}
`
)
this
.
logger
.
info
(
`Recognized L2 chain id
${
L2ChainID
[
l2ChainId
]}
`
)
...
@@ -152,42 +151,26 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
...
@@ -152,42 +151,26 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
}
}
this
.
logger
.
info
(
'
checking contract address options...
'
)
this
.
logger
.
info
(
'
checking contract address options...
'
)
if
(
this
.
options
.
bedrock
)
{
const
portalAddress
=
this
.
options
.
optimismPortalAddress
const
address
=
this
.
options
.
optimismPortalAddress
if
(
!
knownChainId
&&
portalAddress
===
ethers
.
constants
.
AddressZero
)
{
if
(
!
knownChainId
&&
address
===
ethers
.
constants
.
AddressZero
)
{
this
.
logger
.
error
(
'
OptimismPortal contract unspecified
'
)
this
.
logger
.
error
(
'
OptimismPortal contract unspecified
'
)
throw
new
Error
(
throw
new
Error
(
'
--optimismportalcontractaddress needs to set for custom bedrock op chains
'
'
--optimismportalcontractaddress needs to set for custom bedrock op chains
'
)
)
}
}
if
(
address
!==
ethers
.
constants
.
AddressZero
)
{
this
.
logger
.
info
(
'
set OptimismPortal contract override
'
)
contracts
.
OptimismPortal
=
address
this
.
logger
.
info
(
'
fetching L2OutputOracle contract from OptimismPortal
'
)
const
opts
=
{
address
,
signerOrProvider
:
this
.
options
.
l1RpcProvider
}
const
portalContract
=
getOEContract
(
'
OptimismPortal
'
,
l2ChainId
,
opts
)
contracts
.
L2OutputOracle
=
await
portalContract
.
L2_ORACLE
()
}
// ... for a known chain ids without an override, the L2OutputOracle will already
if
(
portalAddress
!==
ethers
.
constants
.
AddressZero
)
{
// be set via the hardcoded default
this
.
logger
.
info
(
'
set OptimismPortal contract override
'
)
}
else
{
contracts
.
OptimismPortal
=
portalAddress
const
address
=
this
.
options
.
stateCommitmentChainAddress
if
(
!
knownChainId
&&
address
===
ethers
.
constants
.
AddressZero
)
{
this
.
logger
.
error
(
'
StateCommitmentChain contract unspecified
'
)
throw
new
Error
(
'
--statecommitmentchainaddress needs to set for custom legacy op chains
'
)
}
if
(
address
!==
ethers
.
constants
.
AddressZero
)
{
this
.
logger
.
info
(
'
fetching L2OutputOracle contract from OptimismPortal
'
)
this
.
logger
.
info
(
'
set StateCommitmentChain contract override
'
)
const
opts
=
{
portalAddress
,
signerOrProvider
:
this
.
options
.
l1RpcProvider
}
contracts
.
StateCommitmentChain
=
address
const
portalContract
=
getOEContract
(
'
OptimismPortal
'
,
l2ChainId
,
opts
)
}
contracts
.
L2OutputOracle
=
await
portalContract
.
L2_ORACLE
()
}
}
// ... for a known chain ids without an override, the L2OutputOracle will already
// be set via the hardcoded default
return
contracts
return
contracts
}
}
...
@@ -211,7 +194,7 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
...
@@ -211,7 +194,7 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
l2SignerOrProvider
:
this
.
options
.
l2RpcProvider
,
l2SignerOrProvider
:
this
.
options
.
l2RpcProvider
,
l1ChainId
,
l1ChainId
,
l2ChainId
,
l2ChainId
,
bedrock
:
t
his
.
options
.
bedrock
,
bedrock
:
t
rue
,
contracts
:
{
l1
:
await
this
.
getOEL1Contracts
(
l2ChainId
)
},
contracts
:
{
l1
:
await
this
.
getOEL1Contracts
(
l2ChainId
)
},
})
})
...
@@ -219,46 +202,36 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
...
@@ -219,46 +202,36 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
this
.
state
.
diverged
=
false
this
.
state
.
diverged
=
false
// We use this a lot, a bit cleaner to pull out to the top level of the state object.
// We use this a lot, a bit cleaner to pull out to the top level of the state object.
this
.
state
.
fpw
=
await
this
.
state
.
messenger
.
getChallengePeriodSeconds
()
this
.
state
.
faultProofWindow
=
await
this
.
state
.
messenger
.
getChallengePeriodSeconds
()
this
.
logger
.
info
(
`fault proof window is
${
this
.
state
.
fpw
}
seconds`
)
this
.
logger
.
info
(
`fault proof window is
${
this
.
state
.
faultProofWindow
}
seconds`
)
if
(
this
.
options
.
bedrock
)
{
const
outputOracle
=
this
.
state
.
messenger
.
contracts
.
l1
.
L2OutputOracle
const
oo
=
this
.
state
.
messenger
.
contracts
.
l1
.
L2OutputOracle
this
.
state
.
outputOracle
=
{
this
.
state
.
oo
=
{
contract
:
outputOracle
,
contract
:
oo
,
filter
:
outputOracle
.
filters
.
OutputProposed
(),
filter
:
oo
.
filters
.
OutputProposed
(),
getTotalElements
:
async
()
=>
outputOracle
.
nextOutputIndex
(),
getTotalElements
:
async
()
=>
oo
.
nextOutputIndex
(),
getEventIndex
:
(
args
)
=>
args
.
l2OutputIndex
,
getEventIndex
:
(
args
)
=>
args
.
l2OutputIndex
,
}
}
else
{
const
oo
=
this
.
state
.
messenger
.
contracts
.
l1
.
StateCommitmentChain
this
.
state
.
oo
=
{
contract
:
oo
,
filter
:
oo
.
filters
.
StateBatchAppended
(),
getTotalElements
:
async
()
=>
oo
.
getTotalBatches
(),
getEventIndex
:
(
args
)
=>
args
.
_batchIndex
,
}
}
}
// Populate the event cache.
// Populate the event cache.
this
.
logger
.
info
(
'
warming event cache, this might take a while...
'
)
this
.
logger
.
info
(
'
warming event cache, this might take a while...
'
)
await
updateOracleCache
(
this
.
state
.
o
o
,
this
.
logger
)
await
updateOracleCache
(
this
.
state
.
o
utputOracle
,
this
.
logger
)
// Figure out where to start syncing from.
// Figure out where to start syncing from.
if
(
this
.
options
.
startBatchIndex
===
-
1
)
{
if
(
this
.
options
.
startBatchIndex
===
-
1
)
{
this
.
logger
.
info
(
'
finding appropriate starting unfinalized batch
'
)
this
.
logger
.
info
(
'
finding appropriate starting unfinalized batch
'
)
const
firstUnfinalized
=
await
findFirstUnfinalizedStateBatchIndex
(
const
firstUnfinalized
=
await
findFirstUnfinalizedStateBatchIndex
(
this
.
state
.
o
o
,
this
.
state
.
o
utputOracle
,
this
.
state
.
f
p
w
,
this
.
state
.
f
aultProofWindo
w
,
this
.
logger
this
.
logger
)
)
// We may not have an unfinalized batches in the case where no batches have been submitted
// We may not have an unfinalized batches in the case where no batches have been submitted
// for the entire duration of the F
P
W. We generally do not expect this to happen on mainnet,
// for the entire duration of the F
AULTPROOFWINDO
W. We generally do not expect this to happen on mainnet,
// but it happens often on testnets because the F
P
W is very short.
// but it happens often on testnets because the F
AULTPROOFWINDO
W is very short.
if
(
firstUnfinalized
===
undefined
)
{
if
(
firstUnfinalized
===
undefined
)
{
this
.
logger
.
info
(
'
no unfinalized batches found. skipping all batches.
'
)
this
.
logger
.
info
(
'
no unfinalized batches found. skipping all batches.
'
)
const
totalBatches
=
await
this
.
state
.
o
o
.
getTotalElements
()
const
totalBatches
=
await
this
.
state
.
o
utputOracle
.
getTotalElements
()
this
.
state
.
currentBatchIndex
=
totalBatches
.
toNumber
()
-
1
this
.
state
.
currentBatchIndex
=
totalBatches
.
toNumber
()
-
1
}
else
{
}
else
{
this
.
state
.
currentBatchIndex
=
firstUnfinalized
this
.
state
.
currentBatchIndex
=
firstUnfinalized
...
@@ -288,7 +261,7 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
...
@@ -288,7 +261,7 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
let
latestBatchIndex
:
number
let
latestBatchIndex
:
number
try
{
try
{
const
totalBatches
=
await
this
.
state
.
o
o
.
getTotalElements
()
const
totalBatches
=
await
this
.
state
.
o
utputOracle
.
getTotalElements
()
latestBatchIndex
=
totalBatches
.
toNumber
()
-
1
latestBatchIndex
=
totalBatches
.
toNumber
()
-
1
}
catch
(
err
)
{
}
catch
(
err
)
{
this
.
logger
.
error
(
'
failed to query total # of batches
'
,
{
this
.
logger
.
error
(
'
failed to query total # of batches
'
,
{
...
@@ -322,7 +295,7 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
...
@@ -322,7 +295,7 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
let
event
:
PartialEvent
let
event
:
PartialEvent
try
{
try
{
event
=
await
findEventForStateBatch
(
event
=
await
findEventForStateBatch
(
this
.
state
.
o
o
,
this
.
state
.
o
utputOracle
,
this
.
state
.
currentBatchIndex
,
this
.
state
.
currentBatchIndex
,
this
.
logger
this
.
logger
)
)
...
@@ -358,179 +331,89 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
...
@@ -358,179 +331,89 @@ export class FaultDetector extends BaseServiceV2<Options, Metrics, State> {
return
return
}
}
if
(
this
.
options
.
bedrock
)
{
const
outputBlockNumber
=
event
.
args
.
l2BlockNumber
.
toNumber
()
const
outputBlockNumber
=
event
.
args
.
l2BlockNumber
.
toNumber
()
if
(
latestBlock
<
outputBlockNumber
)
{
if
(
latestBlock
<
outputBlockNumber
)
{
this
.
logger
.
info
(
'
L2 node is behind, waiting for sync...
'
,
{
this
.
logger
.
info
(
'
L2 node is behind, waiting for sync...
'
,
{
l2BlockHeight
:
latestBlock
,
l2BlockHeight
:
latestBlock
,
outputBlock
:
outputBlockNumber
,
outputBlock
:
outputBlockNumber
,
})
})
return
return
}
}
let
outputBlock
:
any
let
outputBlock
:
any
try
{
try
{
outputBlock
=
await
(
outputBlock
=
await
(
this
.
options
.
l2RpcProvider
as
ethers
.
providers
.
JsonRpcProvider
this
.
options
.
l2RpcProvider
as
ethers
.
providers
.
JsonRpcProvider
).
send
(
'
eth_getBlockByNumber
'
,
[
).
send
(
'
eth_getBlockByNumber
'
,
[
toRpcHexString
(
outputBlockNumber
),
toRpcHexString
(
outputBlockNumber
),
false
,
false
,
])
])
}
catch
(
err
)
{
}
catch
(
err
)
{
this
.
logger
.
error
(
'
failed to fetch output block
'
,
{
this
.
logger
.
error
(
'
failed to fetch output block
'
,
{
error
:
err
,
error
:
err
,
node
:
'
l2
'
,
node
:
'
l2
'
,
section
:
'
getBlock
'
,
section
:
'
getBlock
'
,
block
:
outputBlockNumber
,
block
:
outputBlockNumber
,
})
})
this
.
metrics
.
nodeConnectionFailures
.
inc
({
this
.
metrics
.
nodeConnectionFailures
.
inc
({
layer
:
'
l2
'
,
layer
:
'
l2
'
,
section
:
'
getBlock
'
,
section
:
'
getBlock
'
,
})
})
await
sleep
(
15000
)
await
sleep
(
15000
)
return
return
}
}
let
messagePasserProofResponse
:
any
let
messagePasserProofResponse
:
any
try
{
try
{
messagePasserProofResponse
=
await
(
messagePasserProofResponse
=
await
(
this
.
options
.
l2RpcProvider
as
ethers
.
providers
.
JsonRpcProvider
this
.
options
.
l2RpcProvider
as
ethers
.
providers
.
JsonRpcProvider
).
send
(
'
eth_getProof
'
,
[
).
send
(
'
eth_getProof
'
,
[
this
.
state
.
messenger
.
contracts
.
l2
.
BedrockMessagePasser
.
address
,
this
.
state
.
messenger
.
contracts
.
l2
.
BedrockMessagePasser
.
address
,
[],
[],
toRpcHexString
(
outputBlockNumber
),
toRpcHexString
(
outputBlockNumber
),
])
])
}
catch
(
err
)
{
}
catch
(
err
)
{
this
.
logger
.
error
(
'
failed to fetch message passer proof
'
,
{
this
.
logger
.
error
(
'
failed to fetch message passer proof
'
,
{
error
:
err
,
error
:
err
,
node
:
'
l2
'
,
node
:
'
l2
'
,
section
:
'
getProof
'
,
section
:
'
getProof
'
,
block
:
outputBlockNumber
,
block
:
outputBlockNumber
,
})
})
this
.
metrics
.
nodeConnectionFailures
.
inc
({
this
.
metrics
.
nodeConnectionFailures
.
inc
({
layer
:
'
l2
'
,
layer
:
'
l2
'
,
section
:
'
getProof
'
,
section
:
'
getProof
'
,
})
})
await
sleep
(
15000
)
await
sleep
(
15000
)
return
return
}
}
const
outputRoot
=
ethers
.
utils
.
solidityKeccak256
(
const
outputRoot
=
ethers
.
utils
.
solidityKeccak256
(
[
'
uint256
'
,
'
bytes32
'
,
'
bytes32
'
,
'
bytes32
'
],
[
'
uint256
'
,
'
bytes32
'
,
'
bytes32
'
,
'
bytes32
'
],
[
[
0
,
0
,
outputBlock
.
stateRoot
,
outputBlock
.
stateRoot
,
messagePasserProofResponse
.
storageHash
,
messagePasserProofResponse
.
storageHash
,
outputBlock
.
hash
,
outputBlock
.
hash
,
]
]
)
)
if
(
outputRoot
!==
event
.
args
.
outputRoot
)
{
if
(
outputRoot
!==
event
.
args
.
outputRoot
)
{
this
.
state
.
diverged
=
true
this
.
state
.
diverged
=
true
this
.
metrics
.
isCurrentlyMismatched
.
set
(
1
)
this
.
metrics
.
isCurrentlyMismatched
.
set
(
1
)
this
.
logger
.
error
(
'
state root mismatch
'
,
{
this
.
logger
.
error
(
'
state root mismatch
'
,
{
blockNumber
:
outputBlock
.
number
,
blockNumber
:
outputBlock
.
number
,
expectedStateRoot
:
event
.
args
.
outputRoot
,
expectedStateRoot
:
event
.
args
.
outputRoot
,
actualStateRoot
:
outputRoot
,
actualStateRoot
:
outputRoot
,
finalizationTime
:
dateformat
(
finalizationTime
:
dateformat
(
new
Date
(
new
Date
(
(
ethers
.
BigNumber
.
from
(
outputBlock
.
timestamp
).
toNumber
()
+
(
ethers
.
BigNumber
.
from
(
outputBlock
.
timestamp
).
toNumber
()
+
this
.
state
.
fpw
)
*
this
.
state
.
faultProofWindow
)
*
1000
1000
),
'
mmmm dS, yyyy, h:MM:ss TT
'
),
),
})
'
mmmm dS, yyyy, h:MM:ss TT
'
return
),
}
})
}
else
{
return
let
batchTransaction
:
Transaction
try
{
batchTransaction
=
await
this
.
options
.
l1RpcProvider
.
getTransaction
(
event
.
transactionHash
)
}
catch
(
err
)
{
this
.
logger
.
error
(
'
failed to acquire batch transaction
'
,
{
error
:
err
,
node
:
'
l1
'
,
section
:
'
getTransaction
'
,
})
this
.
metrics
.
nodeConnectionFailures
.
inc
({
layer
:
'
l1
'
,
section
:
'
getTransaction
'
,
})
await
sleep
(
15000
)
return
}
const
[
stateRoots
]
=
this
.
state
.
oo
.
contract
.
interface
.
decodeFunctionData
(
'
appendStateBatch
'
,
batchTransaction
.
data
)
const
batchStart
=
event
.
args
.
_prevTotalElements
.
toNumber
()
+
1
const
batchSize
=
event
.
args
.
_batchSize
.
toNumber
()
const
batchEnd
=
batchStart
+
batchSize
if
(
latestBlock
<
batchEnd
)
{
this
.
logger
.
info
(
'
L2 node is behind. waiting for sync...
'
,
{
batchBlockStart
:
batchStart
,
batchBlockEnd
:
batchEnd
,
l2BlockHeight
:
latestBlock
,
})
return
}
// `getBlockRange` has a limit of 1000 blocks, so we have to break this request out into
// multiple requests of maximum 1000 blocks in the case that batchSize > 1000.
let
blocks
:
any
[]
=
[]
for
(
let
i
=
0
;
i
<
batchSize
;
i
+=
1000
)
{
let
newBlocks
:
any
[]
try
{
newBlocks
=
await
(
this
.
options
.
l2RpcProvider
as
ethers
.
providers
.
JsonRpcProvider
).
send
(
'
eth_getBlockRange
'
,
[
toRpcHexString
(
batchStart
+
i
),
toRpcHexString
(
batchStart
+
i
+
Math
.
min
(
batchSize
-
i
,
1000
)
-
1
),
false
,
])
}
catch
(
err
)
{
this
.
logger
.
error
(
'
failed to query for blocks in batch
'
,
{
error
:
err
,
node
:
'
l2
'
,
section
:
'
getBlockRange
'
,
})
this
.
metrics
.
nodeConnectionFailures
.
inc
({
layer
:
'
l2
'
,
section
:
'
getBlockRange
'
,
})
await
sleep
(
15000
)
return
}
blocks
=
blocks
.
concat
(
newBlocks
)
}
for
(
const
[
i
,
stateRoot
]
of
stateRoots
.
entries
())
{
if
(
blocks
[
i
].
stateRoot
!==
stateRoot
)
{
this
.
state
.
diverged
=
true
this
.
metrics
.
isCurrentlyMismatched
.
set
(
1
)
this
.
logger
.
error
(
'
state root mismatch
'
,
{
blockNumber
:
blocks
[
i
].
number
,
expectedStateRoot
:
blocks
[
i
].
stateRoot
,
actualStateRoot
:
stateRoot
,
finalizationTime
:
dateformat
(
new
Date
(
(
ethers
.
BigNumber
.
from
(
blocks
[
i
].
timestamp
).
toNumber
()
+
this
.
state
.
fpw
)
*
1000
),
'
mmmm dS, yyyy, h:MM:ss TT
'
),
})
return
}
}
}
}
const
elapsedMs
=
Date
.
now
()
-
startMs
const
elapsedMs
=
Date
.
now
()
-
startMs
...
...
packages/fault-detector/test/helpers.spec.ts
View file @
fc64f875
...
@@ -29,7 +29,7 @@ describe('helpers', () => {
...
@@ -29,7 +29,7 @@ describe('helpers', () => {
let
AddressManager
:
Contract
let
AddressManager
:
Contract
let
ChainStorageContainer
:
Contract
let
ChainStorageContainer
:
Contract
let
StateCommitmentChain
:
Contract
let
StateCommitmentChain
:
Contract
let
oracle
:
OutputOracle
<
any
>
let
oracle
:
OutputOracle
beforeEach
(
async
()
=>
{
beforeEach
(
async
()
=>
{
// Set up fakes
// Set up fakes
FakeBondManager
=
await
smock
.
fake
(
getContractInterface
(
'
BondManager
'
))
FakeBondManager
=
await
smock
.
fake
(
getContractInterface
(
'
BondManager
'
))
...
...
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