Commit e2dd14a0 authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into feat/static-peer-reconnect

parents 5262f00f 38773bb1
---
'@eth-optimism/fault-detector': minor
---
Updates the fault detector to support Bedrock networks.
......@@ -5,6 +5,8 @@ import (
"fmt"
"os"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
......@@ -120,6 +122,9 @@ type MigrationData struct {
func (m *MigrationData) ToWithdrawals() ([]*crossdomain.LegacyWithdrawal, error) {
messages := make([]*crossdomain.LegacyWithdrawal, 0)
for _, msg := range m.OvmMessages {
if msg.Who != predeploys.L2CrossDomainMessengerAddr {
continue
}
wd, err := msg.ToLegacyWithdrawal()
if err != nil {
return nil, err
......@@ -130,6 +135,9 @@ func (m *MigrationData) ToWithdrawals() ([]*crossdomain.LegacyWithdrawal, error)
}
}
for _, msg := range m.EvmMessages {
if msg.Who != predeploys.L2CrossDomainMessengerAddr {
continue
}
wd, err := msg.ToLegacyWithdrawal()
if err != nil {
return nil, err
......
......@@ -3,7 +3,6 @@ package eth
import (
"bytes"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
......@@ -52,12 +51,16 @@ func (res *AccountResult) Verify(stateRoot common.Hash) error {
if err != nil {
return fmt.Errorf("failed to verify storage value %d with key %s (path %x) in storage trie %s: %w", i, entry.Key, path, res.StorageHash, err)
}
if !bytes.Equal(val, val) {
comparison, err := rlp.EncodeToBytes(entry.Value.ToInt().Bytes())
if err != nil {
return fmt.Errorf("failed to encode storage value %d with key %s (path %x) in storage trie %s: %w", i, entry.Key, path, res.StorageHash, err)
}
if !bytes.Equal(val, comparison) {
return fmt.Errorf("value %d in storage proof does not match proven value at key %s (path %x)", i, entry.Key, path)
}
}
accountClaimed := []any{uint64(res.Nonce), (*big.Int)(res.Balance).Bytes(), res.StorageHash, res.CodeHash}
accountClaimed := []any{uint64(res.Nonce), res.Balance.ToInt().Bytes(), res.StorageHash, res.CodeHash}
accountClaimedValue, err := rlp.EncodeToBytes(accountClaimed)
if err != nil {
return fmt.Errorf("failed to encode account from retrieved values: %w", err)
......
This diff is collapsed.
ignores: [
"@babel/eslint-parser",
"@types/level",
"@typescript-eslint/parser",
"eslint-plugin-import",
"eslint-plugin-unicorn",
......
......@@ -52,7 +52,7 @@
"ethers": "^5.7.0",
"express": "^4.17.1",
"express-prom-bundle": "^6.3.6",
"level": "^6.0.1",
"level6": "npm:level@^6.0.1",
"levelup": "^4.4.0"
},
"devDependencies": {
......
/* Imports: External */
import { BaseService, LegacyMetrics } from '@eth-optimism/common-ts'
import { LevelUp } from 'levelup'
import level from 'level'
import level from 'level6'
import { Counter } from 'prom-client'
/* Imports: Internal */
......
import { Contract } from 'ethers'
import { Contract, BigNumber } from 'ethers'
export interface OutputOracle<TSubmissionEventArgs> {
contract: Contract
filter: any
getTotalElements: () => Promise<BigNumber>
getEventIndex: (args: TSubmissionEventArgs) => BigNumber
}
/**
* Partial event interface, meant to reduce the size of the event cache to avoid
......@@ -41,27 +48,32 @@ const getCache = (
}
/**
* Updates the event cache for the SCC.
* Updates the event cache for a contract and event.
*
* @param scc The State Commitment Chain contract.
* @param contract Contract to update cache for.
* @param filter Event filter to use.
*/
export const updateStateBatchEventCache = async (
scc: Contract
export const updateOracleCache = async <TSubmissionEventArgs>(
oracle: OutputOracle<TSubmissionEventArgs>
): Promise<void> => {
const cache = getCache(scc.address)
const cache = getCache(oracle.contract.address)
let currentBlock = cache.highestBlock
const endingBlock = await scc.provider.getBlockNumber()
const endingBlock = await oracle.contract.provider.getBlockNumber()
let step = endingBlock - currentBlock
let failures = 0
while (currentBlock < endingBlock) {
try {
const events = await scc.queryFilter(
scc.filters.StateBatchAppended(),
const events = await oracle.contract.queryFilter(
oracle.filter,
currentBlock,
currentBlock + step
)
// Throw the events into the cache.
for (const event of events) {
cache.eventCache[event.args._batchIndex.toNumber()] = {
cache.eventCache[
oracle.getEventIndex(event.args as TSubmissionEventArgs).toNumber()
] = {
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
args: event.args,
......@@ -97,15 +109,15 @@ export const updateStateBatchEventCache = async (
/**
* Finds the Event that corresponds to a given state batch by index.
*
* @param scc StateCommitmentChain contract.
* @param oracle Output oracle contract
* @param index State batch index to search for.
* @returns Event corresponding to the batch.
*/
export const findEventForStateBatch = async (
scc: Contract,
export const findEventForStateBatch = async <TSubmissionEventArgs>(
oracle: OutputOracle<TSubmissionEventArgs>,
index: number
): Promise<PartialEvent> => {
const cache = getCache(scc.address)
const cache = getCache(oracle.contract.address)
// Try to find the event in cache first.
if (cache.eventCache[index]) {
......@@ -113,7 +125,7 @@ export const findEventForStateBatch = async (
}
// Update the event cache if we don't have the event.
await updateStateBatchEventCache(scc)
await updateOracleCache(oracle)
// Event better be in cache now!
if (cache.eventCache[index] === undefined) {
......@@ -126,23 +138,23 @@ export const findEventForStateBatch = async (
/**
* Finds the first state batch index that has not yet passed the fault proof window.
*
* @param scc StateCommitmentChain contract.
* @param oracle Output oracle contract.
* @returns Starting state root batch index.
*/
export const findFirstUnfinalizedStateBatchIndex = async (
scc: Contract
export const findFirstUnfinalizedStateBatchIndex = async <TSubmissionEventArgs>(
oracle: OutputOracle<TSubmissionEventArgs>,
fpw: number
): Promise<number> => {
const fpw = (await scc.FRAUD_PROOF_WINDOW()).toNumber()
const latestBlock = await scc.provider.getBlock('latest')
const totalBatches = (await scc.getTotalBatches()).toNumber()
const latestBlock = await oracle.contract.provider.getBlock('latest')
const totalBatches = (await oracle.getTotalElements()).toNumber()
// Perform a binary search to find the next batch that will pass the challenge period.
let lo = 0
let hi = totalBatches
while (lo !== hi) {
const mid = Math.floor((lo + hi) / 2)
const event = await findEventForStateBatch(scc, mid)
const block = await scc.provider.getBlock(event.blockNumber)
const event = await findEventForStateBatch(oracle, mid)
const block = await oracle.contract.provider.getBlock(event.blockNumber)
if (block.timestamp + fpw < latestBlock.timestamp) {
lo = mid + 1
......
This diff is collapsed.
......@@ -12,6 +12,7 @@ import { expect } from './setup'
import {
findEventForStateBatch,
findFirstUnfinalizedStateBatchIndex,
OutputOracle,
} from '../src'
describe('helpers', () => {
......@@ -28,6 +29,7 @@ describe('helpers', () => {
let AddressManager: Contract
let ChainStorageContainer: Contract
let StateCommitmentChain: Contract
let oracle: OutputOracle<any>
beforeEach(async () => {
// Set up fakes
FakeBondManager = await smock.fake(getContractInterface('BondManager'))
......@@ -67,6 +69,13 @@ describe('helpers', () => {
// Set up mock returns
FakeCanonicalTransactionChain.getTotalElements.returns(1000000000) // just needs to be large
FakeBondManager.isCollateralized.returns(true)
oracle = {
contract: StateCommitmentChain,
filter: StateCommitmentChain.filters.StateBatchAppended(),
getTotalElements: async () => StateCommitmentChain.getTotalBatches(),
getEventIndex: (args: any) => args._batchIndex,
}
})
describe('findEventForStateBatch', () => {
......@@ -79,7 +88,7 @@ describe('helpers', () => {
})
it('should return the event', async () => {
const event = await findEventForStateBatch(StateCommitmentChain, 0)
const event = await findEventForStateBatch(oracle, 0)
expect(event.args._batchIndex).to.equal(0)
})
......@@ -88,7 +97,7 @@ describe('helpers', () => {
describe('when the event does not exist', () => {
it('should throw an error', async () => {
await expect(
findEventForStateBatch(StateCommitmentChain, 0)
findEventForStateBatch(oracle, 0)
).to.eventually.be.rejectedWith('unable to find event for batch')
})
})
......@@ -119,7 +128,8 @@ describe('helpers', () => {
it('should find the first batch older than the FPW', async () => {
const first = await findFirstUnfinalizedStateBatchIndex(
StateCommitmentChain
oracle,
challengeWindowSeconds
)
expect(first).to.equal(1)
......@@ -144,7 +154,8 @@ describe('helpers', () => {
it('should return zero', async () => {
const first = await findFirstUnfinalizedStateBatchIndex(
StateCommitmentChain
oracle,
challengeWindowSeconds
)
expect(first).to.equal(0)
......@@ -177,7 +188,8 @@ describe('helpers', () => {
it('should return undefined', async () => {
const first = await findFirstUnfinalizedStateBatchIndex(
StateCommitmentChain
oracle,
challengeWindowSeconds
)
expect(first).to.equal(undefined)
......
......@@ -12090,7 +12090,7 @@ level-ws@^2.0.0:
readable-stream "^3.1.0"
xtend "^4.0.1"
level@^6.0.1:
"level6@npm:level@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/level/-/level-6.0.1.tgz#dc34c5edb81846a6de5079eac15706334b0d7cd6"
integrity sha512-psRSqJZCsC/irNhfHzrVZbmPYXDcEYhA5TVNwr+V92jF44rbf86hqGp8fiT702FyiArScYIlPSBTDUASCVNSpw==
......
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