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

Merge branch 'develop' into felipe/rewrite-blockorhash

parents 39a7d073 ec104d37
......@@ -3,6 +3,7 @@ version: 2.1
orbs:
go: circleci/go@1.5.0
gcp-cli: circleci/gcp-cli@3.0.1
slack: circleci/slack@4.10.1
commands:
gcp-oidc-authenticate:
description: "Authenticate with GCP using a CircleCI OIDC token."
......@@ -611,10 +612,20 @@ jobs:
- run:
name: markdown lint
command: yarn lint:specs:check
bedrock-markdown-links:
machine:
image: ubuntu-2204:2022.07.1
steps:
- checkout
- run:
name: link lint
command: |
docker run --init -it -v `pwd`:/input lycheeverse/lychee --verbose --no-progress --exclude-loopback --exclude twitter.com --exclude-mail /input/README.md "/input/specs/**/*.md"
make bedrock-markdown-links
- slack/notify:
channel: C055R639XT9 #notify-link-check
event: fail
template: basic_fail_1
fuzz-op-node:
docker:
......@@ -1105,6 +1116,21 @@ jobs:
steps:
- run: echo Done
fpp-verify:
docker:
- image: cimg/go:1.19
steps:
- checkout
- run:
name: verify-goerli
command: |
make verify-goerli
working_directory: op-program
- slack/notify:
channel: C03N11M0BBN
event: fail
template: basic_fail_1
workflows:
main:
jobs:
......@@ -1560,6 +1586,21 @@ workflows:
- oplabs-gcr-release
requires:
- hold
- docker-build:
name: proxyd-docker-release
filters:
tags:
only: /^proxyd\/v.*/
branches:
ignore: /.*/
docker_file: proxyd/Dockerfile
docker_name: proxyd
docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
docker_context: .
context:
- oplabs-gcr-release
requires:
- hold
release-ci-builder:
jobs:
- docker-publish:
......@@ -1575,3 +1616,28 @@ workflows:
docker_context: ./ops/docker/ci-builder
context:
- oplabs-gcr
scheduled-fpp:
triggers:
- schedule:
# run every 4 hours
cron: "0 0,6,12,18 * * *"
filters:
branches:
only: [ "develop" ]
jobs:
- fpp-verify:
context:
- slack
- oplabs-fpp-nodes
scheduled-link-check:
triggers:
- schedule:
# Run once a day, only on the develop branch
cron: "0 0 * * *"
filters:
branches:
only: [ "develop" ]
jobs:
- bedrock-markdown-links:
context: slack
......@@ -120,3 +120,6 @@ tag-bedrock-go-modules:
update-op-geth:
./ops/scripts/update-op-geth.py
.PHONY: update-op-geth
bedrock-markdown-links:
docker run --init -it -v `pwd`:/input lycheeverse/lychee --verbose --no-progress --exclude-loopback --exclude twitter.com --exclude-mail /input/README.md "/input/specs/**/*.md"
......@@ -49,25 +49,25 @@ type Metrics struct {
opmetrics.RefMetrics
txmetrics.TxMetrics
Info prometheus.GaugeVec
Up prometheus.Gauge
info prometheus.GaugeVec
up prometheus.Gauge
// label by openend, closed, fully_submitted, timed_out
ChannelEvs opmetrics.EventVec
channelEvs opmetrics.EventVec
PendingBlocksCount prometheus.GaugeVec
BlocksAddedCount prometheus.Gauge
pendingBlocksCount prometheus.GaugeVec
blocksAddedCount prometheus.Gauge
ChannelInputBytes prometheus.GaugeVec
ChannelReadyBytes prometheus.Gauge
ChannelOutputBytes prometheus.Gauge
ChannelClosedReason prometheus.Gauge
ChannelNumFrames prometheus.Gauge
ChannelComprRatio prometheus.Histogram
ChannelInputBytesTotal prometheus.Counter
ChannelOutputBytesTotal prometheus.Counter
channelInputBytes prometheus.GaugeVec
channelReadyBytes prometheus.Gauge
channelOutputBytes prometheus.Gauge
channelClosedReason prometheus.Gauge
channelNumFrames prometheus.Gauge
channelComprRatio prometheus.Histogram
channelInputBytesTotal prometheus.Counter
channelOutputBytesTotal prometheus.Counter
BatcherTxEvs opmetrics.EventVec
batcherTxEvs opmetrics.EventVec
}
var _ Metricer = (*Metrics)(nil)
......@@ -89,75 +89,75 @@ func NewMetrics(procName string) *Metrics {
RefMetrics: opmetrics.MakeRefMetrics(ns, factory),
TxMetrics: txmetrics.MakeTxMetrics(ns, factory),
Info: *factory.NewGaugeVec(prometheus.GaugeOpts{
info: *factory.NewGaugeVec(prometheus.GaugeOpts{
Namespace: ns,
Name: "info",
Help: "Pseudo-metric tracking version and config info",
}, []string{
"version",
}),
Up: factory.NewGauge(prometheus.GaugeOpts{
up: factory.NewGauge(prometheus.GaugeOpts{
Namespace: ns,
Name: "up",
Help: "1 if the op-batcher has finished starting up",
}),
ChannelEvs: opmetrics.NewEventVec(factory, ns, "", "channel", "Channel", []string{"stage"}),
channelEvs: opmetrics.NewEventVec(factory, ns, "", "channel", "Channel", []string{"stage"}),
PendingBlocksCount: *factory.NewGaugeVec(prometheus.GaugeOpts{
pendingBlocksCount: *factory.NewGaugeVec(prometheus.GaugeOpts{
Namespace: ns,
Name: "pending_blocks_count",
Help: "Number of pending blocks, not added to a channel yet.",
}, []string{"stage"}),
BlocksAddedCount: factory.NewGauge(prometheus.GaugeOpts{
blocksAddedCount: factory.NewGauge(prometheus.GaugeOpts{
Namespace: ns,
Name: "blocks_added_count",
Help: "Total number of blocks added to current channel.",
}),
ChannelInputBytes: *factory.NewGaugeVec(prometheus.GaugeOpts{
channelInputBytes: *factory.NewGaugeVec(prometheus.GaugeOpts{
Namespace: ns,
Name: "input_bytes",
Help: "Number of input bytes to a channel.",
}, []string{"stage"}),
ChannelReadyBytes: factory.NewGauge(prometheus.GaugeOpts{
channelReadyBytes: factory.NewGauge(prometheus.GaugeOpts{
Namespace: ns,
Name: "ready_bytes",
Help: "Number of bytes ready in the compression buffer.",
}),
ChannelOutputBytes: factory.NewGauge(prometheus.GaugeOpts{
channelOutputBytes: factory.NewGauge(prometheus.GaugeOpts{
Namespace: ns,
Name: "output_bytes",
Help: "Number of compressed output bytes from a channel.",
}),
ChannelClosedReason: factory.NewGauge(prometheus.GaugeOpts{
channelClosedReason: factory.NewGauge(prometheus.GaugeOpts{
Namespace: ns,
Name: "channel_closed_reason",
Help: "Pseudo-metric to record the reason a channel got closed.",
}),
ChannelNumFrames: factory.NewGauge(prometheus.GaugeOpts{
channelNumFrames: factory.NewGauge(prometheus.GaugeOpts{
Namespace: ns,
Name: "channel_num_frames",
Help: "Total number of frames of closed channel.",
}),
ChannelComprRatio: factory.NewHistogram(prometheus.HistogramOpts{
channelComprRatio: factory.NewHistogram(prometheus.HistogramOpts{
Namespace: ns,
Name: "channel_compr_ratio",
Help: "Compression ratios of closed channel.",
Buckets: append([]float64{0.1, 0.2}, prometheus.LinearBuckets(0.3, 0.05, 14)...),
}),
ChannelInputBytesTotal: factory.NewCounter(prometheus.CounterOpts{
channelInputBytesTotal: factory.NewCounter(prometheus.CounterOpts{
Namespace: ns,
Name: "input_bytes_total",
Help: "Total number of bytes to a channel.",
}),
ChannelOutputBytesTotal: factory.NewCounter(prometheus.CounterOpts{
channelOutputBytesTotal: factory.NewCounter(prometheus.CounterOpts{
Namespace: ns,
Name: "output_bytes_total",
Help: "Total number of compressed output bytes from a channel.",
}),
BatcherTxEvs: opmetrics.NewEventVec(factory, ns, "", "batcher_tx", "BatcherTx", []string{"stage"}),
batcherTxEvs: opmetrics.NewEventVec(factory, ns, "", "batcher_tx", "BatcherTx", []string{"stage"}),
}
}
......@@ -177,13 +177,13 @@ func (m *Metrics) StartBalanceMetrics(ctx context.Context,
// RecordInfo sets a pseudo-metric that contains versioning and
// config info for the op-batcher.
func (m *Metrics) RecordInfo(version string) {
m.Info.WithLabelValues(version).Set(1)
m.info.WithLabelValues(version).Set(1)
}
// RecordUp sets the up metric to 1.
func (m *Metrics) RecordUp() {
prometheus.MustRegister()
m.Up.Set(1)
m.up.Set(1)
}
const (
......@@ -210,37 +210,37 @@ func (m *Metrics) RecordL2BlocksLoaded(l2ref eth.L2BlockRef) {
}
func (m *Metrics) RecordChannelOpened(id derive.ChannelID, numPendingBlocks int) {
m.ChannelEvs.Record(StageOpened)
m.BlocksAddedCount.Set(0) // reset
m.PendingBlocksCount.WithLabelValues(StageOpened).Set(float64(numPendingBlocks))
m.channelEvs.Record(StageOpened)
m.blocksAddedCount.Set(0) // reset
m.pendingBlocksCount.WithLabelValues(StageOpened).Set(float64(numPendingBlocks))
}
// RecordL2BlocksAdded should be called when L2 block were added to the channel
// builder, with the latest added block.
func (m *Metrics) RecordL2BlocksAdded(l2ref eth.L2BlockRef, numBlocksAdded, numPendingBlocks, inputBytes, outputComprBytes int) {
m.RecordL2Ref(StageAdded, l2ref)
m.BlocksAddedCount.Add(float64(numBlocksAdded))
m.PendingBlocksCount.WithLabelValues(StageAdded).Set(float64(numPendingBlocks))
m.ChannelInputBytes.WithLabelValues(StageAdded).Set(float64(inputBytes))
m.ChannelReadyBytes.Set(float64(outputComprBytes))
m.blocksAddedCount.Add(float64(numBlocksAdded))
m.pendingBlocksCount.WithLabelValues(StageAdded).Set(float64(numPendingBlocks))
m.channelInputBytes.WithLabelValues(StageAdded).Set(float64(inputBytes))
m.channelReadyBytes.Set(float64(outputComprBytes))
}
func (m *Metrics) RecordChannelClosed(id derive.ChannelID, numPendingBlocks int, numFrames int, inputBytes int, outputComprBytes int, reason error) {
m.ChannelEvs.Record(StageClosed)
m.PendingBlocksCount.WithLabelValues(StageClosed).Set(float64(numPendingBlocks))
m.ChannelNumFrames.Set(float64(numFrames))
m.ChannelInputBytes.WithLabelValues(StageClosed).Set(float64(inputBytes))
m.ChannelOutputBytes.Set(float64(outputComprBytes))
m.ChannelInputBytesTotal.Add(float64(inputBytes))
m.ChannelOutputBytesTotal.Add(float64(outputComprBytes))
m.channelEvs.Record(StageClosed)
m.pendingBlocksCount.WithLabelValues(StageClosed).Set(float64(numPendingBlocks))
m.channelNumFrames.Set(float64(numFrames))
m.channelInputBytes.WithLabelValues(StageClosed).Set(float64(inputBytes))
m.channelOutputBytes.Set(float64(outputComprBytes))
m.channelInputBytesTotal.Add(float64(inputBytes))
m.channelOutputBytesTotal.Add(float64(outputComprBytes))
var comprRatio float64
if inputBytes > 0 {
comprRatio = float64(outputComprBytes) / float64(inputBytes)
}
m.ChannelComprRatio.Observe(comprRatio)
m.channelComprRatio.Observe(comprRatio)
m.ChannelClosedReason.Set(float64(ClosedReasonToNum(reason)))
m.channelClosedReason.Set(float64(ClosedReasonToNum(reason)))
}
func ClosedReasonToNum(reason error) int {
......@@ -249,21 +249,21 @@ func ClosedReasonToNum(reason error) int {
}
func (m *Metrics) RecordChannelFullySubmitted(id derive.ChannelID) {
m.ChannelEvs.Record(StageFullySubmitted)
m.channelEvs.Record(StageFullySubmitted)
}
func (m *Metrics) RecordChannelTimedOut(id derive.ChannelID) {
m.ChannelEvs.Record(StageTimedOut)
m.channelEvs.Record(StageTimedOut)
}
func (m *Metrics) RecordBatchTxSubmitted() {
m.BatcherTxEvs.Record(TxStageSubmitted)
m.batcherTxEvs.Record(TxStageSubmitted)
}
func (m *Metrics) RecordBatchTxSuccess() {
m.BatcherTxEvs.Record(TxStageSuccess)
m.batcherTxEvs.Record(TxStageSuccess)
}
func (m *Metrics) RecordBatchTxFailed() {
m.BatcherTxEvs.Record(TxStageFailed)
m.batcherTxEvs.Record(TxStageFailed)
}
package challenger
import (
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/urfave/cli"
flags "github.com/ethereum-optimism/optimism/op-challenger/flags"
sources "github.com/ethereum-optimism/optimism/op-node/sources"
oplog "github.com/ethereum-optimism/optimism/op-service/log"
opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics"
oppprof "github.com/ethereum-optimism/optimism/op-service/pprof"
oprpc "github.com/ethereum-optimism/optimism/op-service/rpc"
txmgr "github.com/ethereum-optimism/optimism/op-service/txmgr"
)
// Config contains the well typed fields that are used to initialize the challenger.
// It is intended for programmatic use.
type Config struct {
L2OutputOracleAddr common.Address
DisputeGameFactory common.Address
NetworkTimeout time.Duration
TxManager txmgr.TxManager
L1Client *ethclient.Client
RollupClient *sources.RollupClient
}
// CLIConfig is a well typed config that is parsed from the CLI params.
// This also contains config options for auxiliary services.
// It is transformed into a `Config` before the Challenger is started.
type CLIConfig struct {
// L1EthRpc is the HTTP provider URL for L1.
L1EthRpc string
// RollupRpc is the HTTP provider URL for the rollup node.
RollupRpc string
// L2OOAddress is the L2OutputOracle contract address.
L2OOAddress string
// DGFAddress is the DisputeGameFactory contract address.
DGFAddress string
TxMgrConfig txmgr.CLIConfig
RPCConfig oprpc.CLIConfig
LogConfig oplog.CLIConfig
MetricsConfig opmetrics.CLIConfig
PprofConfig oppprof.CLIConfig
}
func (c CLIConfig) Check() error {
if err := c.RPCConfig.Check(); err != nil {
return err
}
if err := c.LogConfig.Check(); err != nil {
return err
}
if err := c.MetricsConfig.Check(); err != nil {
return err
}
if err := c.PprofConfig.Check(); err != nil {
return err
}
if err := c.TxMgrConfig.Check(); err != nil {
return err
}
return nil
}
// NewConfig parses the Config from the provided flags or environment variables.
func NewConfig(ctx *cli.Context) CLIConfig {
return CLIConfig{
// Required Flags
L1EthRpc: ctx.GlobalString(flags.L1EthRpcFlag.Name),
RollupRpc: ctx.GlobalString(flags.RollupRpcFlag.Name),
L2OOAddress: ctx.GlobalString(flags.L2OOAddressFlag.Name),
DGFAddress: ctx.GlobalString(flags.DGFAddressFlag.Name),
TxMgrConfig: txmgr.ReadCLIConfig(ctx),
// Optional Flags
RPCConfig: oprpc.ReadCLIConfig(ctx),
LogConfig: oplog.ReadCLIConfig(ctx),
MetricsConfig: opmetrics.ReadCLIConfig(ctx),
PprofConfig: oppprof.ReadCLIConfig(ctx),
}
}
package metrics
import (
"context"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/prometheus/client_golang/prometheus"
opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics"
txmetrics "github.com/ethereum-optimism/optimism/op-service/txmgr/metrics"
)
const Namespace = "op_challenger"
type Metricer interface {
RecordInfo(version string)
RecordUp()
// Records all L1 and L2 block events
opmetrics.RefMetricer
// Record Tx metrics
txmetrics.TxMetricer
RecordValidOutput(l2ref eth.L2BlockRef)
RecordInvalidOutput(l2ref eth.L2BlockRef)
RecordOutputChallenged(l2ref eth.L2BlockRef)
}
type Metrics struct {
ns string
registry *prometheus.Registry
factory opmetrics.Factory
opmetrics.RefMetrics
txmetrics.TxMetrics
info prometheus.GaugeVec
up prometheus.Gauge
}
var _ Metricer = (*Metrics)(nil)
func NewMetrics(procName string) *Metrics {
if procName == "" {
procName = "default"
}
ns := Namespace + "_" + procName
registry := opmetrics.NewRegistry()
factory := opmetrics.With(registry)
return &Metrics{
ns: ns,
registry: registry,
factory: factory,
RefMetrics: opmetrics.MakeRefMetrics(ns, factory),
TxMetrics: txmetrics.MakeTxMetrics(ns, factory),
info: *factory.NewGaugeVec(prometheus.GaugeOpts{
Namespace: ns,
Name: "info",
Help: "Pseudo-metric tracking version and config info",
}, []string{
"version",
}),
up: factory.NewGauge(prometheus.GaugeOpts{
Namespace: ns,
Name: "up",
Help: "1 if the op-proposer has finished starting up",
}),
}
}
func (m *Metrics) Serve(ctx context.Context, host string, port int) error {
return opmetrics.ListenAndServe(ctx, m.registry, host, port)
}
func (m *Metrics) StartBalanceMetrics(ctx context.Context,
l log.Logger, client *ethclient.Client, account common.Address) {
opmetrics.LaunchBalanceMetrics(ctx, l, m.registry, m.ns, client, account)
}
// RecordInfo sets a pseudo-metric that contains versioning and
// config info for the op-proposer.
func (m *Metrics) RecordInfo(version string) {
m.info.WithLabelValues(version).Set(1)
}
// RecordUp sets the up metric to 1.
func (m *Metrics) RecordUp() {
prometheus.MustRegister()
m.up.Set(1)
}
const (
ValidOutput = "valid_output"
InvalidOutput = "invalid_output"
OutputChallenged = "output_challenged"
)
// RecordValidOutput should be called when a valid output is found
func (m *Metrics) RecordValidOutput(l2ref eth.L2BlockRef) {
m.RecordL2Ref(ValidOutput, l2ref)
}
// RecordInvalidOutput should be called when an invalid output is found
func (m *Metrics) RecordInvalidOutput(l2ref eth.L2BlockRef) {
m.RecordL2Ref(InvalidOutput, l2ref)
}
// RecordOutputChallenged should be called when an output is challenged
func (m *Metrics) RecordOutputChallenged(l2ref eth.L2BlockRef) {
m.RecordL2Ref(OutputChallenged, l2ref)
}
func (m *Metrics) Document() []opmetrics.DocumentedMetric {
return m.factory.Document()
}
package metrics
import (
"github.com/ethereum-optimism/optimism/op-node/eth"
opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics"
txmetrics "github.com/ethereum-optimism/optimism/op-service/txmgr/metrics"
)
type noopMetrics struct {
opmetrics.NoopRefMetrics
txmetrics.NoopTxMetrics
}
var NoopMetrics Metricer = new(noopMetrics)
func (*noopMetrics) RecordInfo(version string) {}
func (*noopMetrics) RecordUp() {}
func (*noopMetrics) RecordValidOutput(l2ref eth.L2BlockRef) {}
func (*noopMetrics) RecordInvalidOutput(l2ref eth.L2BlockRef) {}
func (*noopMetrics) RecordOutputChallenged(l2ref eth.L2BlockRef) {}
......@@ -393,6 +393,9 @@ func TestMissingBatchE2E(t *testing.T) {
l2Seq := sys.Clients["sequencer"]
l2Verif := sys.Clients["verifier"]
seqRollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint())
require.Nil(t, err)
seqRollupClient := sources.NewRollupClient(client.NewBaseRPCClient(seqRollupRPCClient))
// Transactor Account
ethPrivKey := cfg.Secrets.Alice
......@@ -414,8 +417,8 @@ func TestMissingBatchE2E(t *testing.T) {
require.Equal(t, ethereum.NotFound, err, "Found transaction in verifier when it should not have been included")
// Wait a short time for the L2 reorg to occur on the sequencer as well.
// The proper thing to do is to wait until the sequencer marks this block safe.
<-time.After(2 * time.Second)
err = waitForSafeHead(ctx, receipt.BlockNumber.Uint64(), seqRollupClient)
require.Nil(t, err, "timeout waiting for L2 reorg on sequencer safe head")
// Assert that the reconciliation process did an L2 reorg on the sequencer to remove the invalid block
ctx2, cancel := context.WithTimeout(context.Background(), time.Second)
......
......@@ -33,6 +33,9 @@ test:
lint:
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint -e "errors.As" -e "errors.Is"
verify-goerli: op-program-host op-program-client
env GO111MODULE=on go run ./verify/cmd/goerli.go $$L1URL $$L2URL
.PHONY: \
op-program \
clean \
......
......@@ -47,7 +47,7 @@ func (s *RetryingL1Source) InfoAndTxsByHash(ctx context.Context, blockHash commo
err := backoff.DoCtx(ctx, maxAttempts, s.strategy, func() error {
i, t, err := s.source.InfoAndTxsByHash(ctx, blockHash)
if err != nil {
s.logger.Warn("Failed to retrieve info and txs", "hash", blockHash, "err", err)
s.logger.Warn("Failed to retrieve l1 info and txs", "hash", blockHash, "err", err)
return err
}
info = i
......@@ -87,7 +87,7 @@ func (s *RetryingL2Source) InfoAndTxsByHash(ctx context.Context, blockHash commo
err := backoff.DoCtx(ctx, maxAttempts, s.strategy, func() error {
i, t, err := s.source.InfoAndTxsByHash(ctx, blockHash)
if err != nil {
s.logger.Warn("Failed to retrieve info and txs", "hash", blockHash, "err", err)
s.logger.Warn("Failed to retrieve l2 info and txs", "hash", blockHash, "err", err)
return err
}
info = i
......
package main
import (
"context"
"fmt"
"math/big"
"os"
"os/exec"
"time"
"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"
"github.com/ethereum/go-ethereum/rpc"
)
const agreedBlockTrailingDistance = 100
func main() {
if len(os.Args) != 3 {
_, _ = fmt.Fprintln(os.Stderr, "Must specify L1 RPC URL and L2 RPC URL as arguments")
os.Exit(2)
}
l1RpcUrl := os.Args[1]
l2RpcUrl := os.Args[2]
goerliOutputAddress := common.HexToAddress("0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0")
err := Run(l1RpcUrl, l2RpcUrl, goerliOutputAddress)
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "Failed: %v\n", err.Error())
os.Exit(1)
}
}
func Run(l1RpcUrl string, l2RpcUrl string, l2OracleAddr common.Address) error {
ctx := context.Background()
l1RpcClient, err := rpc.Dial(l1RpcUrl)
if err != nil {
return fmt.Errorf("dial L1 client: %w", err)
}
l1Client := ethclient.NewClient(l1RpcClient)
l2RpcClient, err := rpc.Dial(l2RpcUrl)
if err != nil {
return fmt.Errorf("dial L2 client: %w", err)
}
l2Client := ethclient.NewClient(l2RpcClient)
outputOracle, err := bindings.NewL2OutputOracle(l2OracleAddr, l1Client)
if err != nil {
return fmt.Errorf("create output oracle bindings: %w", err)
}
// Find L2 finalized head. This is far enough back that we know it's submitted to L1 and won't be re-orged
l2FinalizedHead, err := l2Client.BlockByNumber(ctx, big.NewInt(int64(rpc.FinalizedBlockNumber)))
if err != nil {
return fmt.Errorf("get l2 safe head: %w", err)
}
// Find L1 finalized block. Can't be re-orged and must contain all batches for the L2 finalized block
l1BlockNum := big.NewInt(int64(rpc.FinalizedBlockNumber))
l1HeadBlock, err := l1Client.BlockByNumber(ctx, l1BlockNum)
if err != nil {
return fmt.Errorf("find L1 head: %w", err)
}
// Get the most published L2 output from before the finalized block
callOpts := &bind.CallOpts{Context: ctx}
outputIndex, err := outputOracle.GetL2OutputIndexAfter(callOpts, l2FinalizedHead.Number())
if err != nil {
return fmt.Errorf("get output index after finalized block: %w", err)
}
outputIndex = outputIndex.Sub(outputIndex, big.NewInt(1))
output, err := outputOracle.GetL2Output(callOpts, outputIndex)
if err != nil {
return fmt.Errorf("retrieve latest output: %w", err)
}
l1Head := l1HeadBlock.Hash()
l2Claim := common.Hash(output.OutputRoot)
l2BlockNumber := output.L2BlockNumber
// Use an agreed starting L2 block some distance before the block the output claim is from
agreedBlockNumber := uint64(0)
if l2BlockNumber.Uint64() > agreedBlockTrailingDistance {
agreedBlockNumber = l2BlockNumber.Uint64() - agreedBlockTrailingDistance
}
l2AgreedBlock, err := l2Client.BlockByNumber(ctx, big.NewInt(int64(agreedBlockNumber)))
if err != nil {
return fmt.Errorf("retrieve agreed l2 block: %w", err)
}
l2Head := l2AgreedBlock.Hash()
temp, err := os.MkdirTemp("", "oracledata")
if err != nil {
return fmt.Errorf("create temp dir: %w", err)
}
defer func() {
err := os.RemoveAll(temp)
if err != nil {
println("Failed to remove temp dir:" + err.Error())
}
}()
fmt.Printf("Using temp dir: %s\n", temp)
args := []string{
"--network", "goerli",
"--exec", "./bin/op-program-client",
"--datadir", temp,
"--l1.head", l1Head.Hex(),
"--l2.head", l2Head.Hex(),
"--l2.claim", l2Claim.Hex(),
"--l2.blocknumber", l2BlockNumber.String(),
}
fmt.Printf("Configuration: %s\n", args)
fmt.Println("Running in online mode")
err = runFaultProofProgram(ctx, append(args, "--l1", l1RpcUrl, "--l2", l2RpcUrl))
if err != nil {
return fmt.Errorf("online mode failed: %w", err)
}
fmt.Println("Running in offline mode")
err = runFaultProofProgram(ctx, args)
if err != nil {
return fmt.Errorf("offline mode failed: %w", err)
}
return nil
}
func runFaultProofProgram(ctx context.Context, args []string) error {
ctx, cancel := context.WithTimeout(ctx, 30*time.Minute)
defer cancel()
cmd := exec.CommandContext(ctx, "./bin/op-program", args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}
......@@ -37,8 +37,8 @@ type Metrics struct {
opmetrics.RefMetrics
txmetrics.TxMetrics
Info prometheus.GaugeVec
Up prometheus.Gauge
info prometheus.GaugeVec
up prometheus.Gauge
}
var _ Metricer = (*Metrics)(nil)
......@@ -60,14 +60,14 @@ func NewMetrics(procName string) *Metrics {
RefMetrics: opmetrics.MakeRefMetrics(ns, factory),
TxMetrics: txmetrics.MakeTxMetrics(ns, factory),
Info: *factory.NewGaugeVec(prometheus.GaugeOpts{
info: *factory.NewGaugeVec(prometheus.GaugeOpts{
Namespace: ns,
Name: "info",
Help: "Pseudo-metric tracking version and config info",
}, []string{
"version",
}),
Up: factory.NewGauge(prometheus.GaugeOpts{
up: factory.NewGauge(prometheus.GaugeOpts{
Namespace: ns,
Name: "up",
Help: "1 if the op-proposer has finished starting up",
......@@ -87,13 +87,13 @@ func (m *Metrics) StartBalanceMetrics(ctx context.Context,
// RecordInfo sets a pseudo-metric that contains versioning and
// config info for the op-proposer.
func (m *Metrics) RecordInfo(version string) {
m.Info.WithLabelValues(version).Set(1)
m.info.WithLabelValues(version).Set(1)
}
// RecordUp sets the up metric to 1.
func (m *Metrics) RecordUp() {
prometheus.MustRegister()
m.Up.Set(1)
m.up.Set(1)
}
const (
......
......@@ -11,7 +11,9 @@ REBUILD_ALL_PATTERNS = [
r'^\.github/\.*',
r'^package\.json',
r'^yarn\.lock',
r'ops/check-changed/.*'
r'ops/check-changed/.*',
r'^go\.mod',
r'^go\.sum',
]
WHITELISTED_BRANCHES = {
......
import { DeployConfig } from '../src/deploy-config'
import mainnetJson from './mainnet.json'
// NOTE: The 'mainnet' network is currently being used for bedrock migration rehearsals.
// The system configured below is not yet live on mainnet, and many of the addresses used are
// unsafe for a production system.
// The following addresses are assigned to multiples roles in the system, therfore we save them
// as constants to avoid having to change them in multiple places.
const foundationMultisig = '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266' // hh test signer 0
const feeRecipient = '0x70997970C51812dc3A010C7d01b50e0d17dc79C8' // hh test signer 1
const mintManager = '0x5C4e7Ba1E219E47948e6e3F55019A647bA501005'
const config: DeployConfig = {
finalSystemOwner: foundationMultisig,
controller: foundationMultisig,
portalGuardian: foundationMultisig,
proxyAdminOwner: foundationMultisig,
l1StartingBlockTag:
'0x126e52a0cc0ae18948f567ee9443f4a8f0db67c437706e35baee424eb314a0d0',
l1ChainID: 1,
l2ChainID: 10,
l2BlockTime: 2,
maxSequencerDrift: 600,
sequencerWindowSize: 3600,
channelTimeout: 300,
p2pSequencerAddress: '0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65',
batchInboxAddress: '0xff00000000000000000000000000000000000010',
batchSenderAddress: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',
l2OutputOracleSubmissionInterval: 20,
l2OutputOracleStartingTimestamp: 1679069195,
l2OutputOracleStartingBlockNumber: 79149704,
l2OutputOracleProposer: '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC',
l2OutputOracleChallenger: foundationMultisig,
finalizationPeriodSeconds: 2,
baseFeeVaultRecipient: feeRecipient,
l1FeeVaultRecipient: feeRecipient,
sequencerFeeVaultRecipient: feeRecipient,
governanceTokenName: 'Optimism',
governanceTokenSymbol: 'OP',
governanceTokenOwner: mintManager,
l2GenesisBlockGasLimit: '0x1c9c380',
l2GenesisBlockCoinbase: '0x4200000000000000000000000000000000000011',
l2GenesisBlockBaseFeePerGas: '0x3b9aca00',
gasPriceOracleOverhead: 2100,
gasPriceOracleScalar: 1000000,
eip1559Denominator: 50,
eip1559Elasticity: 10,
l2GenesisRegolithTimeOffset: '0x0',
}
// Re-export the mainnet json as a DeployConfig object.
//
// Notice, the following roles in the system are assigned to the:
// Optimism Foundation Mulitisig:
// - finalSystemOwner
// - controller
// - portalGuardian
// - proxyAdminOwner
// - l2OutputOracleChallenger
//
// The following roles are assigned to the same fee recipient:
// - baseFeeVaultRecipient
// - l1FeeVaultRecipient
// - sequencerFeeVaultRecipient
//
// The following role is assigned to the Mint Manager contract:
// - governanceTokenOwner
const config: DeployConfig = mainnetJson
export default config
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