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

Merge branch 'develop' into jg/race_cond_in_batcher

parents d8cda3f1 edafea3e
---
'@eth-optimism/sdk': patch
---
Updated npm dependencies to latest
...@@ -945,17 +945,8 @@ jobs: ...@@ -945,17 +945,8 @@ jobs:
name: Bring up the stack name: Bring up the stack
command: make devnet-up command: make devnet-up
- run: - run:
name: Check L2 config name: Test the stack
command: go run cmd/check-l2/main.go --l2-rpc-url http://localhost:9545 --l1-rpc-url http://localhost:8545 command: make devnet-test
working_directory: op-chain-ops
- run:
name: Deposit ERC20 through the bridge
command: timeout 8m npx hardhat deposit-erc20 --network devnetL1 --l1-contracts-json-path ../../.devnet/addresses.json
working_directory: packages/sdk
- run:
name: Deposit ETH through the bridge
command: timeout 8m npx hardhat deposit-eth --network devnetL1 --l1-contracts-json-path ../../.devnet/addresses.json
working_directory: packages/sdk
- run: - run:
name: Dump op-node logs name: Dump op-node logs
command: | command: |
......
...@@ -221,17 +221,14 @@ pull_request_rules: ...@@ -221,17 +221,14 @@ pull_request_rules:
label: label:
add: add:
- A-ops - A-ops
- name: Add A-pkg-sdk label and ecopod reviewers - name: Add A-pkg-chain-mon label
conditions: conditions:
- 'files~=^packages/sdk/' - 'files~=^packages/chain-mon/'
- '#label<5' - '#label<5'
actions: actions:
label: label:
add: add:
- A-pkg-sdk - A-pkg-chain-mon
request_reviews:
users:
- roninjin10
- name: Add A-pkg-common-ts label and ecopod reviewers - name: Add A-pkg-common-ts label and ecopod reviewers
conditions: conditions:
- 'files~=^packages/common-ts/' - 'files~=^packages/common-ts/'
...@@ -250,6 +247,57 @@ pull_request_rules: ...@@ -250,6 +247,57 @@ pull_request_rules:
label: label:
add: add:
- A-pkg-contracts-bedrock - A-pkg-contracts-bedrock
- name: Add A-pkg-contracts-ts label
conditions:
- 'files~=^packages/contracts-ts/'
- '#label<5'
actions:
label:
add:
- A-pkg-contracts-ts
- name: Add A-pkg-core-utils label
conditions:
- 'files~=^packages/core-utils/'
- '#label<5'
actions:
label:
add:
- A-pkg-core-utils
- name: Add A-pkg-fee-estimation label
conditions:
- 'files~=^packages/fee-estimation/'
- '#label<5'
actions:
label:
add:
- A-pkg-fee-estimation
- name: Add A-pkg-sdk label and ecopod reviewers
conditions:
- 'files~=^packages/sdk/'
- '#label<5'
actions:
label:
add:
- A-pkg-sdk
request_reviews:
users:
- roninjin10
- name: Add A-pkg-web3js-plugin label
conditions:
- 'files~=^packages/web3js-plugin/'
- '#label<5'
actions:
label:
add:
- A-pkg-web3js-plugin
- name: Add A-proxyd label
conditions:
- 'files~=^proxyd/'
- '#label<5'
actions:
label:
add:
- A-proxyd
- name: Add M-docs label - name: Add M-docs label
conditions: conditions:
- 'files~=^(technical-documents|specs)\/' - 'files~=^(technical-documents|specs)\/'
......
...@@ -96,6 +96,10 @@ devnet-up: ...@@ -96,6 +96,10 @@ devnet-up:
# alias for devnet-up # alias for devnet-up
devnet-up-deploy: devnet-up devnet-up-deploy: devnet-up
devnet-test:
PYTHONPATH=./bedrock-devnet python3 ./bedrock-devnet/main.py --monorepo-dir=. --test
.PHONY: devnet-test
devnet-down: devnet-down:
@(cd ./ops-bedrock && GENESIS_TIMESTAMP=$(shell date +%s) docker-compose stop) @(cd ./ops-bedrock && GENESIS_TIMESTAMP=$(shell date +%s) docker-compose stop)
.PHONY: devnet-down .PHONY: devnet-down
......
...@@ -18,6 +18,7 @@ pjoin = os.path.join ...@@ -18,6 +18,7 @@ pjoin = os.path.join
parser = argparse.ArgumentParser(description='Bedrock devnet launcher') parser = argparse.ArgumentParser(description='Bedrock devnet launcher')
parser.add_argument('--monorepo-dir', help='Directory of the monorepo', default=os.getcwd()) parser.add_argument('--monorepo-dir', help='Directory of the monorepo', default=os.getcwd())
parser.add_argument('--allocs', help='Only create the allocs and exit', type=bool, action=argparse.BooleanOptionalAction) parser.add_argument('--allocs', help='Only create the allocs and exit', type=bool, action=argparse.BooleanOptionalAction)
parser.add_argument('--test', help='Tests the deployment, must already be deployed', type=bool, action=argparse.BooleanOptionalAction)
log = logging.getLogger() log = logging.getLogger()
...@@ -57,6 +58,8 @@ def main(): ...@@ -57,6 +58,8 @@ def main():
ops_bedrock_dir = pjoin(monorepo_dir, 'ops-bedrock') ops_bedrock_dir = pjoin(monorepo_dir, 'ops-bedrock')
deploy_config_dir = pjoin(contracts_bedrock_dir, 'deploy-config'), deploy_config_dir = pjoin(contracts_bedrock_dir, 'deploy-config'),
devnet_config_path = pjoin(contracts_bedrock_dir, 'deploy-config', 'devnetL1.json') devnet_config_path = pjoin(contracts_bedrock_dir, 'deploy-config', 'devnetL1.json')
ops_chain_ops = pjoin(monorepo_dir, 'op-chain-ops')
sdk_dir = pjoin(monorepo_dir, 'packages', 'sdk')
paths = Bunch( paths = Bunch(
mono_repo_dir=monorepo_dir, mono_repo_dir=monorepo_dir,
...@@ -68,6 +71,8 @@ def main(): ...@@ -68,6 +71,8 @@ def main():
devnet_config_path=devnet_config_path, devnet_config_path=devnet_config_path,
op_node_dir=op_node_dir, op_node_dir=op_node_dir,
ops_bedrock_dir=ops_bedrock_dir, ops_bedrock_dir=ops_bedrock_dir,
ops_chain_ops=ops_chain_ops,
sdk_dir=sdk_dir,
genesis_l1_path=pjoin(devnet_dir, 'genesis-l1.json'), genesis_l1_path=pjoin(devnet_dir, 'genesis-l1.json'),
genesis_l2_path=pjoin(devnet_dir, 'genesis-l2.json'), genesis_l2_path=pjoin(devnet_dir, 'genesis-l2.json'),
allocs_path=pjoin(devnet_dir, 'allocs-l1.json'), allocs_path=pjoin(devnet_dir, 'allocs-l1.json'),
...@@ -76,6 +81,11 @@ def main(): ...@@ -76,6 +81,11 @@ def main():
rollup_config_path=pjoin(devnet_dir, 'rollup.json') rollup_config_path=pjoin(devnet_dir, 'rollup.json')
) )
if args.test:
log.info('Testing deployed devnet')
devnet_test(paths)
return
os.makedirs(devnet_dir, exist_ok=True) os.makedirs(devnet_dir, exist_ok=True)
if args.allocs: if args.allocs:
...@@ -250,8 +260,26 @@ def wait_for_rpc_server(url): ...@@ -250,8 +260,26 @@ def wait_for_rpc_server(url):
log.info(f'Waiting for RPC server at {url}') log.info(f'Waiting for RPC server at {url}')
time.sleep(1) time.sleep(1)
def devnet_test(paths):
# Check the L2 config
run_command(
['go', 'run', 'cmd/check-l2/main.go', '--l2-rpc-url', 'http://localhost:9545', '--l1-rpc-url', 'http://localhost:8545'],
cwd=paths.ops_chain_ops,
)
run_command(
['npx', 'hardhat', 'deposit-erc20', '--network', 'devnetL1', '--l1-contracts-json-path', paths.addresses_json_path],
cwd=paths.sdk_dir,
timeout=8*60,
)
run_command(
['npx', 'hardhat', 'deposit-eth', '--network', 'devnetL1', '--l1-contracts-json-path', paths.addresses_json_path],
cwd=paths.sdk_dir,
timeout=8*60,
)
def run_command(args, check=True, shell=False, cwd=None, env=None): def run_command(args, check=True, shell=False, cwd=None, env=None, timeout=None):
env = env if env else {} env = env if env else {}
return subprocess.run( return subprocess.run(
args, args,
...@@ -261,7 +289,8 @@ def run_command(args, check=True, shell=False, cwd=None, env=None): ...@@ -261,7 +289,8 @@ def run_command(args, check=True, shell=False, cwd=None, env=None):
**os.environ, **os.environ,
**env **env
}, },
cwd=cwd cwd=cwd,
timeout=timeout
) )
......
...@@ -24,7 +24,6 @@ require ( ...@@ -24,7 +24,6 @@ require (
github.com/ipfs/go-ds-leveldb v0.5.0 github.com/ipfs/go-ds-leveldb v0.5.0
github.com/jackc/pgtype v1.14.0 github.com/jackc/pgtype v1.14.0
github.com/jackc/pgx/v5 v5.4.3 github.com/jackc/pgx/v5 v5.4.3
github.com/joho/godotenv v1.5.1
github.com/libp2p/go-libp2p v0.27.8 github.com/libp2p/go-libp2p v0.27.8
github.com/libp2p/go-libp2p-pubsub v0.9.3 github.com/libp2p/go-libp2p-pubsub v0.9.3
github.com/libp2p/go-libp2p-testing v0.12.0 github.com/libp2p/go-libp2p-testing v0.12.0
......
...@@ -429,8 +429,6 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD ...@@ -429,8 +429,6 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
......
...@@ -8,7 +8,6 @@ import ( ...@@ -8,7 +8,6 @@ import (
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
geth_log "github.com/ethereum/go-ethereum/log" geth_log "github.com/ethereum/go-ethereum/log"
"github.com/joho/godotenv"
) )
// in future presets can just be onchain config and fetched on initialization // in future presets can just be onchain config and fetched on initialization
...@@ -89,13 +88,7 @@ type MetricsConfig struct { ...@@ -89,13 +88,7 @@ type MetricsConfig struct {
// LoadConfig loads the `indexer.toml` config file from a given path // LoadConfig loads the `indexer.toml` config file from a given path
func LoadConfig(logger geth_log.Logger, path string) (Config, error) { func LoadConfig(logger geth_log.Logger, path string) (Config, error) {
if err := godotenv.Load(); err != nil { logger.Info("Loading config file", "path", path)
logger.Warn("Unable to load .env file", err)
logger.Info("Continuing without .env file")
} else {
logger.Info("Loaded .env file")
}
var conf Config var conf Config
data, err := os.ReadFile(path) data, err := os.ReadFile(path)
...@@ -105,6 +98,8 @@ func LoadConfig(logger geth_log.Logger, path string) (Config, error) { ...@@ -105,6 +98,8 @@ func LoadConfig(logger geth_log.Logger, path string) (Config, error) {
data = []byte(os.ExpandEnv(string(data))) data = []byte(os.ExpandEnv(string(data)))
logger.Debug("Decoding config file", "data", string(data))
if _, err := toml.Decode(string(data), &conf); err != nil { if _, err := toml.Decode(string(data), &conf); err != nil {
logger.Info("Failed to decode config file", "message", err) logger.Info("Failed to decode config file", "message", err)
return conf, err return conf, err
......
SHELL := /bin/bash SHELL := /usr/bin/env bash
pkg := bindings pkg := bindings
monorepo-base := $(shell dirname $(realpath .)) monorepo-base := $(shell dirname $(realpath .))
......
#!/bin/bash #!/usr/bin/env bash
HASH=$1 HASH=$1
......
...@@ -15,7 +15,7 @@ import ( ...@@ -15,7 +15,7 @@ import (
var ( var (
l1EthRpc = "http://example.com:8545" l1EthRpc = "http://example.com:8545"
gameAddressValue = "0xaa00000000000000000000000000000000000000" gameFactoryAddressValue = "0xbb00000000000000000000000000000000000000"
cannonNetwork = chaincfg.AvailableNetworks()[0] cannonNetwork = chaincfg.AvailableNetworks()[0]
otherCannonNetwork = chaincfg.AvailableNetworks()[1] otherCannonNetwork = chaincfg.AvailableNetworks()[1]
cannonBin = "./bin/cannon" cannonBin = "./bin/cannon"
...@@ -44,14 +44,14 @@ func TestLogLevel(t *testing.T) { ...@@ -44,14 +44,14 @@ func TestLogLevel(t *testing.T) {
func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) { func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(config.TraceTypeAlphabet)) cfg := configForArgs(t, addRequiredArgs(config.TraceTypeAlphabet))
defaultCfg := config.NewConfig(l1EthRpc, common.HexToAddress(gameAddressValue), config.TraceTypeAlphabet, true) defaultCfg := config.NewConfig(common.HexToAddress(gameFactoryAddressValue), l1EthRpc, config.TraceTypeAlphabet, true)
// Add in the extra CLI options required when using alphabet trace type // Add in the extra CLI options required when using alphabet trace type
defaultCfg.AlphabetTrace = alphabetTrace defaultCfg.AlphabetTrace = alphabetTrace
require.Equal(t, defaultCfg, cfg) require.Equal(t, defaultCfg, cfg)
} }
func TestDefaultConfigIsValid(t *testing.T) { func TestDefaultConfigIsValid(t *testing.T) {
cfg := config.NewConfig(l1EthRpc, common.HexToAddress(gameAddressValue), config.TraceTypeAlphabet, true) cfg := config.NewConfig(common.HexToAddress(gameFactoryAddressValue), l1EthRpc, config.TraceTypeAlphabet, true)
// Add in options that are required based on the specific trace type // Add in options that are required based on the specific trace type
// To avoid needing to specify unused options, these aren't included in the params for NewConfig // To avoid needing to specify unused options, these aren't included in the params for NewConfig
cfg.AlphabetTrace = alphabetTrace cfg.AlphabetTrace = alphabetTrace
...@@ -89,9 +89,26 @@ func TestTraceType(t *testing.T) { ...@@ -89,9 +89,26 @@ func TestTraceType(t *testing.T) {
}) })
} }
func TestGameAddress(t *testing.T) { func TestGameFactoryAddress(t *testing.T) {
t.Run("Required", func(t *testing.T) { t.Run("Required", func(t *testing.T) {
verifyArgsInvalid(t, "flag game-address is required", addRequiredArgsExcept(config.TraceTypeAlphabet, "--game-address")) verifyArgsInvalid(t, "flag game-factory-address is required", addRequiredArgsExcept(config.TraceTypeAlphabet, "--game-factory-address"))
})
t.Run("Valid", func(t *testing.T) {
addr := common.Address{0xbb, 0xcc, 0xdd}
cfg := configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--game-factory-address", "--game-factory-address="+addr.Hex()))
require.Equal(t, addr, cfg.GameFactoryAddress)
})
t.Run("Invalid", func(t *testing.T) {
verifyArgsInvalid(t, "invalid address: foo", addRequiredArgsExcept(config.TraceTypeAlphabet, "--game-factory-address", "--game-factory-address=foo"))
})
}
func TestGameAddress(t *testing.T) {
t.Run("Optional", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--game-address"))
require.NoError(t, cfg.Check())
}) })
t.Run("Valid", func(t *testing.T) { t.Run("Valid", func(t *testing.T) {
...@@ -316,7 +333,7 @@ func requiredArgs(traceType config.TraceType) map[string]string { ...@@ -316,7 +333,7 @@ func requiredArgs(traceType config.TraceType) map[string]string {
args := map[string]string{ args := map[string]string{
"--agree-with-proposed-output": agreeWithProposedOutput, "--agree-with-proposed-output": agreeWithProposedOutput,
"--l1-eth-rpc": l1EthRpc, "--l1-eth-rpc": l1EthRpc,
"--game-address": gameAddressValue, "--game-factory-address": gameFactoryAddressValue,
"--trace-type": traceType.String(), "--trace-type": traceType.String(),
} }
switch traceType { switch traceType {
......
...@@ -18,7 +18,7 @@ var ( ...@@ -18,7 +18,7 @@ var (
ErrMissingCannonAbsolutePreState = errors.New("missing cannon absolute pre-state") ErrMissingCannonAbsolutePreState = errors.New("missing cannon absolute pre-state")
ErrMissingAlphabetTrace = errors.New("missing alphabet trace") ErrMissingAlphabetTrace = errors.New("missing alphabet trace")
ErrMissingL1EthRPC = errors.New("missing l1 eth rpc url") ErrMissingL1EthRPC = errors.New("missing l1 eth rpc url")
ErrMissingGameAddress = errors.New("missing game address") ErrMissingGameFactoryAddress = errors.New("missing game factory address")
ErrMissingCannonSnapshotFreq = errors.New("missing cannon snapshot freq") ErrMissingCannonSnapshotFreq = errors.New("missing cannon snapshot freq")
ErrMissingCannonRollupConfig = errors.New("missing cannon network or rollup config path") ErrMissingCannonRollupConfig = errors.New("missing cannon network or rollup config path")
ErrMissingCannonL2Genesis = errors.New("missing cannon network or l2 genesis path") ErrMissingCannonL2Genesis = errors.New("missing cannon network or l2 genesis path")
...@@ -65,6 +65,7 @@ const DefaultCannonSnapshotFreq = uint(1_000_000_000) ...@@ -65,6 +65,7 @@ const DefaultCannonSnapshotFreq = uint(1_000_000_000)
// It is used to initialize the challenger. // It is used to initialize the challenger.
type Config struct { type Config struct {
L1EthRpc string // L1 RPC Url L1EthRpc string // L1 RPC Url
GameFactoryAddress common.Address // Address of the dispute game factory
GameAddress common.Address // Address of the fault game GameAddress common.Address // Address of the fault game
AgreeWithProposedOutput bool // Temporary config if we agree or disagree with the posted output AgreeWithProposedOutput bool // Temporary config if we agree or disagree with the posted output
...@@ -88,14 +89,14 @@ type Config struct { ...@@ -88,14 +89,14 @@ type Config struct {
} }
func NewConfig( func NewConfig(
gameFactoryAddress common.Address,
l1EthRpc string, l1EthRpc string,
gameAddress common.Address,
traceType TraceType, traceType TraceType,
agreeWithProposedOutput bool, agreeWithProposedOutput bool,
) Config { ) Config {
return Config{ return Config{
L1EthRpc: l1EthRpc, L1EthRpc: l1EthRpc,
GameAddress: gameAddress, GameFactoryAddress: gameFactoryAddress,
AgreeWithProposedOutput: agreeWithProposedOutput, AgreeWithProposedOutput: agreeWithProposedOutput,
...@@ -111,8 +112,8 @@ func (c Config) Check() error { ...@@ -111,8 +112,8 @@ func (c Config) Check() error {
if c.L1EthRpc == "" { if c.L1EthRpc == "" {
return ErrMissingL1EthRPC return ErrMissingL1EthRPC
} }
if c.GameAddress == (common.Address{}) { if c.GameFactoryAddress == (common.Address{}) {
return ErrMissingGameAddress return ErrMissingGameFactoryAddress
} }
if c.TraceType == "" { if c.TraceType == "" {
return ErrMissingTraceType return ErrMissingTraceType
......
...@@ -10,7 +10,7 @@ import ( ...@@ -10,7 +10,7 @@ import (
var ( var (
validL1EthRpc = "http://localhost:8545" validL1EthRpc = "http://localhost:8545"
validGameAddress = common.HexToAddress("0x7bdd3b028C4796eF0EAf07d11394d0d9d8c24139") validGameFactoryAddress = common.Address{0x23}
validAlphabetTrace = "abcdefgh" validAlphabetTrace = "abcdefgh"
validCannonBin = "./bin/cannon" validCannonBin = "./bin/cannon"
validCannonOpProgramBin = "./bin/op-program" validCannonOpProgramBin = "./bin/op-program"
...@@ -22,7 +22,7 @@ var ( ...@@ -22,7 +22,7 @@ var (
) )
func validConfig(traceType TraceType) Config { func validConfig(traceType TraceType) Config {
cfg := NewConfig(validL1EthRpc, validGameAddress, traceType, agreeWithProposedOutput) cfg := NewConfig(validGameFactoryAddress, validL1EthRpc, traceType, agreeWithProposedOutput)
switch traceType { switch traceType {
case TraceTypeAlphabet: case TraceTypeAlphabet:
cfg.AlphabetTrace = validAlphabetTrace cfg.AlphabetTrace = validAlphabetTrace
...@@ -62,10 +62,16 @@ func TestL1EthRpcRequired(t *testing.T) { ...@@ -62,10 +62,16 @@ func TestL1EthRpcRequired(t *testing.T) {
require.ErrorIs(t, config.Check(), ErrMissingL1EthRPC) require.ErrorIs(t, config.Check(), ErrMissingL1EthRPC)
} }
func TestGameAddressRequired(t *testing.T) { func TestGameFactoryAddressRequired(t *testing.T) {
config := validConfig(TraceTypeCannon)
config.GameFactoryAddress = common.Address{}
require.ErrorIs(t, config.Check(), ErrMissingGameFactoryAddress)
}
func TestGameAddressNotRequired(t *testing.T) {
config := validConfig(TraceTypeCannon) config := validConfig(TraceTypeCannon)
config.GameAddress = common.Address{} config.GameAddress = common.Address{}
require.ErrorIs(t, config.Check(), ErrMissingGameAddress) require.NoError(t, config.Check())
} }
func TestAlphabetTraceRequired(t *testing.T) { func TestAlphabetTraceRequired(t *testing.T) {
......
...@@ -21,7 +21,7 @@ const execTestCannonPrestate = "/foo/pre.json" ...@@ -21,7 +21,7 @@ const execTestCannonPrestate = "/foo/pre.json"
func TestGenerateProof(t *testing.T) { func TestGenerateProof(t *testing.T) {
input := "starting.json" input := "starting.json"
cfg := config.NewConfig("http://localhost:8888", common.Address{0xaa}, config.TraceTypeCannon, true) cfg := config.NewConfig(common.Address{0xbb}, "http://localhost:8888", config.TraceTypeCannon, true)
cfg.CannonDatadir = t.TempDir() cfg.CannonDatadir = t.TempDir()
cfg.CannonAbsolutePreState = "pre.json" cfg.CannonAbsolutePreState = "pre.json"
cfg.CannonBin = "./bin/cannon" cfg.CannonBin = "./bin/cannon"
......
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
openum "github.com/ethereum-optimism/optimism/op-service/enum" openum "github.com/ethereum-optimism/optimism/op-service/enum"
oplog "github.com/ethereum-optimism/optimism/op-service/log" oplog "github.com/ethereum-optimism/optimism/op-service/log"
"github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
...@@ -29,7 +30,12 @@ var ( ...@@ -29,7 +30,12 @@ var (
Usage: "HTTP provider URL for L1.", Usage: "HTTP provider URL for L1.",
EnvVars: prefixEnvVars("L1_ETH_RPC"), EnvVars: prefixEnvVars("L1_ETH_RPC"),
} }
DGFAddressFlag = &cli.StringFlag{ FactoryAddressFlag = &cli.StringFlag{
Name: "game-factory-address",
Usage: "Address of the fault game factory contract.",
EnvVars: prefixEnvVars("GAME_FACTORY_ADDRESS"),
}
GameAddressFlag = &cli.StringFlag{
Name: "game-address", Name: "game-address",
Usage: "Address of the Fault Game contract.", Usage: "Address of the Fault Game contract.",
EnvVars: prefixEnvVars("GAME_ADDRESS"), EnvVars: prefixEnvVars("GAME_ADDRESS"),
...@@ -105,7 +111,7 @@ var ( ...@@ -105,7 +111,7 @@ var (
// requiredFlags are checked by [CheckRequired] // requiredFlags are checked by [CheckRequired]
var requiredFlags = []cli.Flag{ var requiredFlags = []cli.Flag{
L1EthRpcFlag, L1EthRpcFlag,
DGFAddressFlag, FactoryAddressFlag,
TraceTypeFlag, TraceTypeFlag,
AgreeWithProposedOutputFlag, AgreeWithProposedOutputFlag,
} }
...@@ -113,6 +119,7 @@ var requiredFlags = []cli.Flag{ ...@@ -113,6 +119,7 @@ var requiredFlags = []cli.Flag{
// optionalFlags is a list of unchecked cli flags // optionalFlags is a list of unchecked cli flags
var optionalFlags = []cli.Flag{ var optionalFlags = []cli.Flag{
AlphabetFlag, AlphabetFlag,
GameAddressFlag,
CannonNetworkFlag, CannonNetworkFlag,
CannonRollupConfigFlag, CannonRollupConfigFlag,
CannonL2GenesisFlag, CannonL2GenesisFlag,
...@@ -181,10 +188,17 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) { ...@@ -181,10 +188,17 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
if err := CheckRequired(ctx); err != nil { if err := CheckRequired(ctx); err != nil {
return nil, err return nil, err
} }
dgfAddress, err := opservice.ParseAddress(ctx.String(DGFAddressFlag.Name)) gameFactoryAddress, err := opservice.ParseAddress(ctx.String(FactoryAddressFlag.Name))
if err != nil { if err != nil {
return nil, err return nil, err
} }
var gameAddress common.Address
if ctx.IsSet(GameAddressFlag.Name) {
gameAddress, err = opservice.ParseAddress(ctx.String(GameAddressFlag.Name))
if err != nil {
return nil, err
}
}
txMgrConfig := txmgr.ReadCLIConfig(ctx) txMgrConfig := txmgr.ReadCLIConfig(ctx)
...@@ -194,7 +208,8 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) { ...@@ -194,7 +208,8 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
// Required Flags // Required Flags
L1EthRpc: ctx.String(L1EthRpcFlag.Name), L1EthRpc: ctx.String(L1EthRpcFlag.Name),
TraceType: traceTypeFlag, TraceType: traceTypeFlag,
GameAddress: dgfAddress, GameFactoryAddress: gameFactoryAddress,
GameAddress: gameAddress,
AlphabetTrace: ctx.String(AlphabetFlag.Name), AlphabetTrace: ctx.String(AlphabetFlag.Name),
CannonNetwork: ctx.String(CannonNetworkFlag.Name), CannonNetwork: ctx.String(CannonNetworkFlag.Name),
CannonRollupConfigPath: ctx.String(CannonRollupConfigFlag.Name), CannonRollupConfigPath: ctx.String(CannonRollupConfigFlag.Name),
......
#!/bin/bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
SOURCE_DIR=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd) SOURCE_DIR=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
CHALLENGER_DIR=$(echo ${SOURCE_DIR%/*/*}) CHALLENGER_DIR=$(echo ${SOURCE_DIR%/*/*})
MONOREPO_DIR=$(echo ${SOURCE_DIR%/*/*/*})
# Check that the fault game address file exists # Check that the fault game address file exists
FAULT_GAME_ADDR_FILE="$CHALLENGER_DIR/.fault-game-address" FAULT_GAME_ADDR_FILE="$CHALLENGER_DIR/.fault-game-address"
...@@ -14,6 +15,7 @@ fi ...@@ -14,6 +15,7 @@ fi
# Charlie's Address: 0xF45B7537828CB2fffBC69996B054c2Aaf36DC778 # Charlie's Address: 0xF45B7537828CB2fffBC69996B054c2Aaf36DC778
CHARLIE_KEY="74feb147d72bfae943e6b4e483410933d9e447d5dc47d52432dcc2c1454dabb7" CHARLIE_KEY="74feb147d72bfae943e6b4e483410933d9e447d5dc47d52432dcc2c1454dabb7"
DISPUTE_GAME_PROXY=$(jq -r .DisputeGameFactoryProxy $MONOREPO_DIR/.devnet/addresses.json)
FAULT_GAME_ADDRESS=$(cat $FAULT_GAME_ADDR_FILE) FAULT_GAME_ADDRESS=$(cat $FAULT_GAME_ADDR_FILE)
echo "Fault dispute game address: $FAULT_GAME_ADDRESS" echo "Fault dispute game address: $FAULT_GAME_ADDRESS"
...@@ -21,6 +23,7 @@ $CHALLENGER_DIR/bin/op-challenger \ ...@@ -21,6 +23,7 @@ $CHALLENGER_DIR/bin/op-challenger \
--l1-eth-rpc http://localhost:8545 \ --l1-eth-rpc http://localhost:8545 \
--trace-type="alphabet" \ --trace-type="alphabet" \
--alphabet "abcdefgh" \ --alphabet "abcdefgh" \
--game-factory-address $DISPUTE_GAME_PROXY \
--game-address $FAULT_GAME_ADDRESS \ --game-address $FAULT_GAME_ADDRESS \
--private-key $CHARLIE_KEY \ --private-key $CHARLIE_KEY \
--num-confirmations 1 \ --num-confirmations 1 \
......
#!/bin/bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
......
#!/bin/bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
SOURCE_DIR=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd) SOURCE_DIR=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
CHALLENGER_DIR=$(echo ${SOURCE_DIR%/*/*}) CHALLENGER_DIR=$(echo ${SOURCE_DIR%/*/*})
MONOREPO_DIR=$(echo ${SOURCE_DIR%/*/*/*})
# Check that the fault game address file exists # Check that the fault game address file exists
FAULT_GAME_ADDR_FILE="$CHALLENGER_DIR/.fault-game-address" FAULT_GAME_ADDR_FILE="$CHALLENGER_DIR/.fault-game-address"
...@@ -14,6 +15,7 @@ fi ...@@ -14,6 +15,7 @@ fi
# Mallory's Address: 0x4641c704a6c743f73ee1f36C7568Fbf4b80681e4 # Mallory's Address: 0x4641c704a6c743f73ee1f36C7568Fbf4b80681e4
MALLORY_KEY="28d7045146193f5f4eeb151c4843544b1b0d30a7ac1680c845a416fac65a7715" MALLORY_KEY="28d7045146193f5f4eeb151c4843544b1b0d30a7ac1680c845a416fac65a7715"
DISPUTE_GAME_PROXY=$(jq -r .DisputeGameFactoryProxy $MONOREPO_DIR/.devnet/addresses.json)
FAULT_GAME_ADDRESS=$(cat $FAULT_GAME_ADDR_FILE) FAULT_GAME_ADDRESS=$(cat $FAULT_GAME_ADDR_FILE)
echo "Fault dispute game address: $FAULT_GAME_ADDRESS" echo "Fault dispute game address: $FAULT_GAME_ADDRESS"
...@@ -21,6 +23,7 @@ $CHALLENGER_DIR/bin/op-challenger \ ...@@ -21,6 +23,7 @@ $CHALLENGER_DIR/bin/op-challenger \
--l1-eth-rpc http://localhost:8545 \ --l1-eth-rpc http://localhost:8545 \
--trace-type="alphabet" \ --trace-type="alphabet" \
--alphabet "abcdexyz" \ --alphabet "abcdexyz" \
--game-factory-address $DISPUTE_GAME_PROXY \
--game-address $FAULT_GAME_ADDRESS \ --game-address $FAULT_GAME_ADDRESS \
--private-key $MALLORY_KEY \ --private-key $MALLORY_KEY \
--num-confirmations 1 \ --num-confirmations 1 \
......
#!/bin/bash #!/usr/bin/env bash
# set -x # set -x
......
#!/bin/bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
......
...@@ -15,6 +15,7 @@ type AlphabetGameHelper struct { ...@@ -15,6 +15,7 @@ type AlphabetGameHelper struct {
func (g *AlphabetGameHelper) StartChallenger(ctx context.Context, l1Endpoint string, name string, options ...challenger.Option) *challenger.Helper { func (g *AlphabetGameHelper) StartChallenger(ctx context.Context, l1Endpoint string, name string, options ...challenger.Option) *challenger.Helper {
opts := []challenger.Option{ opts := []challenger.Option{
func(c *config.Config) { func(c *config.Config) {
c.GameFactoryAddress = g.factoryAddr
c.GameAddress = g.addr c.GameAddress = g.addr
c.TraceType = config.TraceTypeAlphabet c.TraceType = config.TraceTypeAlphabet
// By default the challenger agrees with the root claim (thus disagrees with the proposed output) // By default the challenger agrees with the root claim (thus disagrees with the proposed output)
......
...@@ -24,7 +24,7 @@ type CannonGameHelper struct { ...@@ -24,7 +24,7 @@ type CannonGameHelper struct {
} }
func (g *CannonGameHelper) StartChallenger(ctx context.Context, rollupCfg *rollup.Config, l2Genesis *core.Genesis, l1Endpoint string, l2Endpoint string, name string, options ...challenger.Option) *challenger.Helper { func (g *CannonGameHelper) StartChallenger(ctx context.Context, rollupCfg *rollup.Config, l2Genesis *core.Genesis, l1Endpoint string, l2Endpoint string, name string, options ...challenger.Option) *challenger.Helper {
opts := []challenger.Option{createConfigOption(g.t, rollupCfg, l2Genesis, g.addr, l2Endpoint)} opts := []challenger.Option{createConfigOption(g.t, rollupCfg, l2Genesis, g.factoryAddr, g.addr, l2Endpoint)}
opts = append(opts, options...) opts = append(opts, options...)
c := challenger.NewChallenger(g.t, ctx, l1Endpoint, name, opts...) c := challenger.NewChallenger(g.t, ctx, l1Endpoint, name, opts...)
g.t.Cleanup(func() { g.t.Cleanup(func() {
...@@ -34,7 +34,7 @@ func (g *CannonGameHelper) StartChallenger(ctx context.Context, rollupCfg *rollu ...@@ -34,7 +34,7 @@ func (g *CannonGameHelper) StartChallenger(ctx context.Context, rollupCfg *rollu
} }
func (g *CannonGameHelper) CreateHonestActor(ctx context.Context, rollupCfg *rollup.Config, l2Genesis *core.Genesis, l1Client bind.ContractCaller, l1Endpoint string, l2Endpoint string, options ...challenger.Option) *HonestHelper { func (g *CannonGameHelper) CreateHonestActor(ctx context.Context, rollupCfg *rollup.Config, l2Genesis *core.Genesis, l1Client bind.ContractCaller, l1Endpoint string, l2Endpoint string, options ...challenger.Option) *HonestHelper {
opts := []challenger.Option{createConfigOption(g.t, rollupCfg, l2Genesis, g.addr, l2Endpoint)} opts := []challenger.Option{createConfigOption(g.t, rollupCfg, l2Genesis, g.factoryAddr, g.addr, l2Endpoint)}
opts = append(opts, options...) opts = append(opts, options...)
cfg := challenger.NewChallengerConfig(g.t, l1Endpoint, opts...) cfg := challenger.NewChallengerConfig(g.t, l1Endpoint, opts...)
provider, err := cannon.NewTraceProvider(ctx, testlog.Logger(g.t, log.LvlInfo).New("role", "CorrectTrace"), cfg, l1Client) provider, err := cannon.NewTraceProvider(ctx, testlog.Logger(g.t, log.LvlInfo).New("role", "CorrectTrace"), cfg, l1Client)
...@@ -48,9 +48,17 @@ func (g *CannonGameHelper) CreateHonestActor(ctx context.Context, rollupCfg *rol ...@@ -48,9 +48,17 @@ func (g *CannonGameHelper) CreateHonestActor(ctx context.Context, rollupCfg *rol
} }
} }
func createConfigOption(t *testing.T, rollupCfg *rollup.Config, l2Genesis *core.Genesis, gameAddr common.Address, l2Endpoint string) challenger.Option { func createConfigOption(
t *testing.T,
rollupCfg *rollup.Config,
l2Genesis *core.Genesis,
factoryAddr common.Address,
gameAddr common.Address,
l2Endpoint string,
) challenger.Option {
return func(c *config.Config) { return func(c *config.Config) {
require := require.New(t) require := require.New(t)
c.GameFactoryAddress = factoryAddr
c.GameAddress = gameAddr c.GameAddress = gameAddr
c.TraceType = config.TraceTypeCannon c.TraceType = config.TraceTypeCannon
c.AgreeWithProposedOutput = false c.AgreeWithProposedOutput = false
......
...@@ -17,12 +17,13 @@ import ( ...@@ -17,12 +17,13 @@ import (
) )
type FaultGameHelper struct { type FaultGameHelper struct {
t *testing.T t *testing.T
require *require.Assertions require *require.Assertions
client *ethclient.Client client *ethclient.Client
opts *bind.TransactOpts opts *bind.TransactOpts
game *bindings.FaultDisputeGame game *bindings.FaultDisputeGame
addr common.Address factoryAddr common.Address
addr common.Address
} }
func (g *FaultGameHelper) GameDuration(ctx context.Context) time.Duration { func (g *FaultGameHelper) GameDuration(ctx context.Context) time.Duration {
......
...@@ -119,12 +119,13 @@ func (h *FactoryHelper) StartAlphabetGame(ctx context.Context, claimedAlphabet s ...@@ -119,12 +119,13 @@ func (h *FactoryHelper) StartAlphabetGame(ctx context.Context, claimedAlphabet s
return &AlphabetGameHelper{ return &AlphabetGameHelper{
FaultGameHelper: FaultGameHelper{ FaultGameHelper: FaultGameHelper{
t: h.t, t: h.t,
require: h.require, require: h.require,
client: h.client, client: h.client,
opts: h.opts, opts: h.opts,
game: game, game: game,
addr: createdEvent.DisputeProxy, factoryAddr: h.factoryAddr,
addr: createdEvent.DisputeProxy,
}, },
claimedAlphabet: claimedAlphabet, claimedAlphabet: claimedAlphabet,
} }
...@@ -137,7 +138,7 @@ func (h *FactoryHelper) StartCannonGame(ctx context.Context, rootClaim common.Ha ...@@ -137,7 +138,7 @@ func (h *FactoryHelper) StartCannonGame(ctx context.Context, rootClaim common.Ha
func (h *FactoryHelper) StartCannonGameWithCorrectRoot(ctx context.Context, rollupCfg *rollup.Config, l2Genesis *core.Genesis, l1Endpoint string, l2Endpoint string, options ...challenger.Option) (*CannonGameHelper, *HonestHelper) { func (h *FactoryHelper) StartCannonGameWithCorrectRoot(ctx context.Context, rollupCfg *rollup.Config, l2Genesis *core.Genesis, l1Endpoint string, l2Endpoint string, options ...challenger.Option) (*CannonGameHelper, *HonestHelper) {
l2BlockNumber, l1Head := h.prepareCannonGame(ctx) l2BlockNumber, l1Head := h.prepareCannonGame(ctx)
challengerOpts := []challenger.Option{createConfigOption(h.t, rollupCfg, l2Genesis, common.Address{0xaa}, l2Endpoint)} challengerOpts := []challenger.Option{createConfigOption(h.t, rollupCfg, l2Genesis, h.factoryAddr, common.Address{0xaa}, l2Endpoint)}
challengerOpts = append(challengerOpts, options...) challengerOpts = append(challengerOpts, options...)
cfg := challenger.NewChallengerConfig(h.t, l1Endpoint, challengerOpts...) cfg := challenger.NewChallengerConfig(h.t, l1Endpoint, challengerOpts...)
opts := &bind.CallOpts{Context: ctx} opts := &bind.CallOpts{Context: ctx}
...@@ -200,20 +201,20 @@ func (h *FactoryHelper) createCannonGame(ctx context.Context, l2BlockNumber uint ...@@ -200,20 +201,20 @@ func (h *FactoryHelper) createCannonGame(ctx context.Context, l2BlockNumber uint
return &CannonGameHelper{ return &CannonGameHelper{
FaultGameHelper: FaultGameHelper{ FaultGameHelper: FaultGameHelper{
t: h.t, t: h.t,
require: h.require, require: h.require,
client: h.client, client: h.client,
opts: h.opts, opts: h.opts,
game: game, game: game,
addr: createdEvent.DisputeProxy, factoryAddr: h.factoryAddr,
addr: createdEvent.DisputeProxy,
}, },
} }
} }
func (h *FactoryHelper) StartChallenger(ctx context.Context, l1Endpoint string, name string, options ...challenger.Option) *challenger.Helper { func (h *FactoryHelper) StartChallenger(ctx context.Context, l1Endpoint string, name string, options ...challenger.Option) *challenger.Helper {
opts := []challenger.Option{ opts := []challenger.Option{
func(c *config.Config) { func(c *config.Config) {
// Uncomment when challenger actually supports setting the game factory address c.GameFactoryAddress = h.factoryAddr
//c.FactoryAddress = h.factoryAddr
c.TraceType = config.TraceTypeAlphabet c.TraceType = config.TraceTypeAlphabet
}, },
} }
......
...@@ -34,9 +34,9 @@ import ( ...@@ -34,9 +34,9 @@ import (
"github.com/ethereum-optimism/optimism/op-node/rollup/driver" "github.com/ethereum-optimism/optimism/op-node/rollup/driver"
"github.com/ethereum-optimism/optimism/op-node/sources" "github.com/ethereum-optimism/optimism/op-node/sources"
"github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-service/backoff"
"github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/eth"
oppprof "github.com/ethereum-optimism/optimism/op-service/pprof" oppprof "github.com/ethereum-optimism/optimism/op-service/pprof"
"github.com/ethereum-optimism/optimism/op-service/retry"
) )
func TestL2OutputSubmitter(t *testing.T) { func TestL2OutputSubmitter(t *testing.T) {
...@@ -533,7 +533,7 @@ func TestSystemMockP2P(t *testing.T) { ...@@ -533,7 +533,7 @@ func TestSystemMockP2P(t *testing.T) {
// poll to see if the verifier node is connected & meshed on gossip. // poll to see if the verifier node is connected & meshed on gossip.
// Without this verifier, we shouldn't start sending blocks around, or we'll miss them and fail the test. // Without this verifier, we shouldn't start sending blocks around, or we'll miss them and fail the test.
backOffStrategy := backoff.Exponential() backOffStrategy := retry.Exponential()
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
if check() { if check() {
break break
......
...@@ -8,7 +8,7 @@ import ( ...@@ -8,7 +8,7 @@ import (
"regexp" "regexp"
"time" "time"
"github.com/ethereum-optimism/optimism/op-service/backoff" "github.com/ethereum-optimism/optimism/op-service/retry"
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
...@@ -103,8 +103,8 @@ func NewRPC(ctx context.Context, lgr log.Logger, addr string, opts ...RPCOption) ...@@ -103,8 +103,8 @@ func NewRPC(ctx context.Context, lgr log.Logger, addr string, opts ...RPCOption)
// Dials a JSON-RPC endpoint repeatedly, with a backoff, until a client connection is established. Auth is optional. // Dials a JSON-RPC endpoint repeatedly, with a backoff, until a client connection is established. Auth is optional.
func dialRPCClientWithBackoff(ctx context.Context, log log.Logger, addr string, attempts int, opts ...rpc.ClientOption) (*rpc.Client, error) { func dialRPCClientWithBackoff(ctx context.Context, log log.Logger, addr string, attempts int, opts ...rpc.ClientOption) (*rpc.Client, error) {
bOff := backoff.Exponential() bOff := retry.Exponential()
return backoff.Do(ctx, attempts, bOff, func() (*rpc.Client, error) { return retry.Do(ctx, attempts, bOff, func() (*rpc.Client, error) {
if !IsURLAvailable(addr) { if !IsURLAvailable(addr) {
log.Warn("failed to dial address, but may connect later", "addr", addr) log.Warn("failed to dial address, but may connect later", "addr", addr)
return nil, fmt.Errorf("address unavailable (%s)", addr) return nil, fmt.Errorf("address unavailable (%s)", addr)
......
echo $1
jq '.frames[] | {timestamp, inclusion_block}' $1
jq '.batches[]|.Timestamp' $1
...@@ -15,8 +15,8 @@ import ( ...@@ -15,8 +15,8 @@ import (
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-service/backoff"
"github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/retry"
) )
// Deprecated: use eth.SyncStatus instead. // Deprecated: use eth.SyncStatus instead.
...@@ -178,7 +178,7 @@ func (s *Driver) eventLoop() { ...@@ -178,7 +178,7 @@ func (s *Driver) eventLoop() {
var delayedStepReq <-chan time.Time var delayedStepReq <-chan time.Time
// keep track of consecutive failed attempts, to adjust the backoff time accordingly // keep track of consecutive failed attempts, to adjust the backoff time accordingly
bOffStrategy := backoff.Exponential() bOffStrategy := retry.Exponential()
stepAttempts := 0 stepAttempts := 0
// step requests a derivation step to be taken. Won't deadlock if the channel is full. // step requests a derivation step to be taken. Won't deadlock if the channel is full.
......
...@@ -11,8 +11,8 @@ import ( ...@@ -11,8 +11,8 @@ import (
"github.com/ethereum-optimism/optimism/op-node/client" "github.com/ethereum-optimism/optimism/op-node/client"
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/sources/caching" "github.com/ethereum-optimism/optimism/op-node/sources/caching"
"github.com/ethereum-optimism/optimism/op-service/backoff"
"github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/retry"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peer"
...@@ -130,10 +130,10 @@ func (s *SyncClient) eventLoop() { ...@@ -130,10 +130,10 @@ func (s *SyncClient) eventLoop() {
defer s.wg.Done() defer s.wg.Done()
s.log.Info("Starting sync client event loop") s.log.Info("Starting sync client event loop")
backoffStrategy := &backoff.ExponentialStrategy{ backoffStrategy := &retry.ExponentialStrategy{
Min: 1000, Min: 1000 * time.Millisecond,
Max: 20_000, Max: 20_000 * time.Millisecond,
MaxJitter: 250, MaxJitter: 250 * time.Millisecond,
} }
for { for {
...@@ -142,7 +142,7 @@ func (s *SyncClient) eventLoop() { ...@@ -142,7 +142,7 @@ func (s *SyncClient) eventLoop() {
s.log.Debug("Shutting down RPC sync worker") s.log.Debug("Shutting down RPC sync worker")
return return
case reqNum := <-s.requests: case reqNum := <-s.requests:
_, err := backoff.Do(s.resCtx, 5, backoffStrategy, func() (interface{}, error) { _, err := retry.Do(s.resCtx, 5, backoffStrategy, func() (interface{}, error) {
// Limit the maximum time for fetching payloads // Limit the maximum time for fetching payloads
ctx, cancel := context.WithTimeout(s.resCtx, time.Second*10) ctx, cancel := context.WithTimeout(s.resCtx, time.Second*10)
defer cancel() defer cancel()
......
...@@ -4,8 +4,8 @@ import ( ...@@ -4,8 +4,8 @@ import (
"context" "context"
"math" "math"
"github.com/ethereum-optimism/optimism/op-service/backoff"
"github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/retry"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
...@@ -16,19 +16,19 @@ const maxAttempts = math.MaxInt // Succeed or die trying ...@@ -16,19 +16,19 @@ const maxAttempts = math.MaxInt // Succeed or die trying
type RetryingL1Source struct { type RetryingL1Source struct {
logger log.Logger logger log.Logger
source L1Source source L1Source
strategy backoff.Strategy strategy retry.Strategy
} }
func NewRetryingL1Source(logger log.Logger, source L1Source) *RetryingL1Source { func NewRetryingL1Source(logger log.Logger, source L1Source) *RetryingL1Source {
return &RetryingL1Source{ return &RetryingL1Source{
logger: logger, logger: logger,
source: source, source: source,
strategy: backoff.Exponential(), strategy: retry.Exponential(),
} }
} }
func (s *RetryingL1Source) InfoByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, error) { func (s *RetryingL1Source) InfoByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, error) {
return backoff.Do(ctx, maxAttempts, s.strategy, func() (eth.BlockInfo, error) { return retry.Do(ctx, maxAttempts, s.strategy, func() (eth.BlockInfo, error) {
res, err := s.source.InfoByHash(ctx, blockHash) res, err := s.source.InfoByHash(ctx, blockHash)
if err != nil { if err != nil {
s.logger.Warn("Failed to retrieve info", "hash", blockHash, "err", err) s.logger.Warn("Failed to retrieve info", "hash", blockHash, "err", err)
...@@ -38,7 +38,7 @@ func (s *RetryingL1Source) InfoByHash(ctx context.Context, blockHash common.Hash ...@@ -38,7 +38,7 @@ func (s *RetryingL1Source) InfoByHash(ctx context.Context, blockHash common.Hash
} }
func (s *RetryingL1Source) InfoAndTxsByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, error) { func (s *RetryingL1Source) InfoAndTxsByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, error) {
return backoff.Do2(ctx, maxAttempts, s.strategy, func() (eth.BlockInfo, types.Transactions, error) { return retry.Do2(ctx, maxAttempts, s.strategy, func() (eth.BlockInfo, types.Transactions, error) {
i, t, err := s.source.InfoAndTxsByHash(ctx, blockHash) i, t, err := s.source.InfoAndTxsByHash(ctx, blockHash)
if err != nil { if err != nil {
s.logger.Warn("Failed to retrieve l1 info and txs", "hash", blockHash, "err", err) s.logger.Warn("Failed to retrieve l1 info and txs", "hash", blockHash, "err", err)
...@@ -48,7 +48,7 @@ func (s *RetryingL1Source) InfoAndTxsByHash(ctx context.Context, blockHash commo ...@@ -48,7 +48,7 @@ func (s *RetryingL1Source) InfoAndTxsByHash(ctx context.Context, blockHash commo
} }
func (s *RetryingL1Source) FetchReceipts(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Receipts, error) { func (s *RetryingL1Source) FetchReceipts(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Receipts, error) {
return backoff.Do2(ctx, maxAttempts, s.strategy, func() (eth.BlockInfo, types.Receipts, error) { return retry.Do2(ctx, maxAttempts, s.strategy, func() (eth.BlockInfo, types.Receipts, error) {
i, r, err := s.source.FetchReceipts(ctx, blockHash) i, r, err := s.source.FetchReceipts(ctx, blockHash)
if err != nil { if err != nil {
s.logger.Warn("Failed to fetch receipts", "hash", blockHash, "err", err) s.logger.Warn("Failed to fetch receipts", "hash", blockHash, "err", err)
...@@ -62,11 +62,11 @@ var _ L1Source = (*RetryingL1Source)(nil) ...@@ -62,11 +62,11 @@ var _ L1Source = (*RetryingL1Source)(nil)
type RetryingL2Source struct { type RetryingL2Source struct {
logger log.Logger logger log.Logger
source L2Source source L2Source
strategy backoff.Strategy strategy retry.Strategy
} }
func (s *RetryingL2Source) InfoAndTxsByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, error) { func (s *RetryingL2Source) InfoAndTxsByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, error) {
return backoff.Do2(ctx, maxAttempts, s.strategy, func() (eth.BlockInfo, types.Transactions, error) { return retry.Do2(ctx, maxAttempts, s.strategy, func() (eth.BlockInfo, types.Transactions, error) {
i, t, err := s.source.InfoAndTxsByHash(ctx, blockHash) i, t, err := s.source.InfoAndTxsByHash(ctx, blockHash)
if err != nil { if err != nil {
s.logger.Warn("Failed to retrieve l2 info and txs", "hash", blockHash, "err", err) s.logger.Warn("Failed to retrieve l2 info and txs", "hash", blockHash, "err", err)
...@@ -76,7 +76,7 @@ func (s *RetryingL2Source) InfoAndTxsByHash(ctx context.Context, blockHash commo ...@@ -76,7 +76,7 @@ func (s *RetryingL2Source) InfoAndTxsByHash(ctx context.Context, blockHash commo
} }
func (s *RetryingL2Source) NodeByHash(ctx context.Context, hash common.Hash) ([]byte, error) { func (s *RetryingL2Source) NodeByHash(ctx context.Context, hash common.Hash) ([]byte, error) {
return backoff.Do(ctx, maxAttempts, s.strategy, func() ([]byte, error) { return retry.Do(ctx, maxAttempts, s.strategy, func() ([]byte, error) {
n, err := s.source.NodeByHash(ctx, hash) n, err := s.source.NodeByHash(ctx, hash)
if err != nil { if err != nil {
s.logger.Warn("Failed to retrieve node", "hash", hash, "err", err) s.logger.Warn("Failed to retrieve node", "hash", hash, "err", err)
...@@ -86,7 +86,7 @@ func (s *RetryingL2Source) NodeByHash(ctx context.Context, hash common.Hash) ([] ...@@ -86,7 +86,7 @@ func (s *RetryingL2Source) NodeByHash(ctx context.Context, hash common.Hash) ([]
} }
func (s *RetryingL2Source) CodeByHash(ctx context.Context, hash common.Hash) ([]byte, error) { func (s *RetryingL2Source) CodeByHash(ctx context.Context, hash common.Hash) ([]byte, error) {
return backoff.Do(ctx, maxAttempts, s.strategy, func() ([]byte, error) { return retry.Do(ctx, maxAttempts, s.strategy, func() ([]byte, error) {
c, err := s.source.CodeByHash(ctx, hash) c, err := s.source.CodeByHash(ctx, hash)
if err != nil { if err != nil {
s.logger.Warn("Failed to retrieve code", "hash", hash, "err", err) s.logger.Warn("Failed to retrieve code", "hash", hash, "err", err)
...@@ -96,7 +96,7 @@ func (s *RetryingL2Source) CodeByHash(ctx context.Context, hash common.Hash) ([] ...@@ -96,7 +96,7 @@ func (s *RetryingL2Source) CodeByHash(ctx context.Context, hash common.Hash) ([]
} }
func (s *RetryingL2Source) OutputByRoot(ctx context.Context, root common.Hash) (eth.Output, error) { func (s *RetryingL2Source) OutputByRoot(ctx context.Context, root common.Hash) (eth.Output, error) {
return backoff.Do(ctx, maxAttempts, s.strategy, func() (eth.Output, error) { return retry.Do(ctx, maxAttempts, s.strategy, func() (eth.Output, error) {
o, err := s.source.OutputByRoot(ctx, root) o, err := s.source.OutputByRoot(ctx, root)
if err != nil { if err != nil {
s.logger.Warn("Failed to fetch l2 output", "root", root, "err", err) s.logger.Warn("Failed to fetch l2 output", "root", root, "err", err)
...@@ -110,7 +110,7 @@ func NewRetryingL2Source(logger log.Logger, source L2Source) *RetryingL2Source { ...@@ -110,7 +110,7 @@ func NewRetryingL2Source(logger log.Logger, source L2Source) *RetryingL2Source {
return &RetryingL2Source{ return &RetryingL2Source{
logger: logger, logger: logger,
source: source, source: source,
strategy: backoff.Exponential(), strategy: retry.Exponential(),
} }
} }
......
...@@ -7,8 +7,8 @@ import ( ...@@ -7,8 +7,8 @@ import (
"github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-node/testutils" "github.com/ethereum-optimism/optimism/op-node/testutils"
"github.com/ethereum-optimism/optimism/op-service/backoff"
"github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/retry"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
...@@ -104,8 +104,8 @@ func createL1Source(t *testing.T) (*RetryingL1Source, *testutils.MockL1Source) { ...@@ -104,8 +104,8 @@ func createL1Source(t *testing.T) (*RetryingL1Source, *testutils.MockL1Source) {
logger := testlog.Logger(t, log.LvlDebug) logger := testlog.Logger(t, log.LvlDebug)
mock := &testutils.MockL1Source{} mock := &testutils.MockL1Source{}
source := NewRetryingL1Source(logger, mock) source := NewRetryingL1Source(logger, mock)
// Avoid sleeping in tests by using a fixed backoff strategy with no delay // Avoid sleeping in tests by using a fixed retry strategy with no delay
source.strategy = backoff.Fixed(0) source.strategy = retry.Fixed(0)
return source, mock return source, mock
} }
...@@ -217,8 +217,8 @@ func createL2Source(t *testing.T) (*RetryingL2Source, *MockL2Source) { ...@@ -217,8 +217,8 @@ func createL2Source(t *testing.T) (*RetryingL2Source, *MockL2Source) {
logger := testlog.Logger(t, log.LvlDebug) logger := testlog.Logger(t, log.LvlDebug)
mock := &MockL2Source{} mock := &MockL2Source{}
source := NewRetryingL2Source(logger, mock) source := NewRetryingL2Source(logger, mock)
// Avoid sleeping in tests by using a fixed backoff strategy with no delay // Avoid sleeping in tests by using a fixed retry strategy with no delay
source.strategy = backoff.Fixed(0) source.strategy = retry.Fixed(0)
return source, mock return source, mock
} }
......
...@@ -7,7 +7,7 @@ import ( ...@@ -7,7 +7,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/client" "github.com/ethereum-optimism/optimism/op-node/client"
"github.com/ethereum-optimism/optimism/op-node/sources" "github.com/ethereum-optimism/optimism/op-node/sources"
"github.com/ethereum-optimism/optimism/op-service/backoff" "github.com/ethereum-optimism/optimism/op-service/retry"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
...@@ -49,8 +49,8 @@ func DialRollupClientWithTimeout(timeout time.Duration, log log.Logger, url stri ...@@ -49,8 +49,8 @@ func DialRollupClientWithTimeout(timeout time.Duration, log log.Logger, url stri
// Dials a JSON-RPC endpoint repeatedly, with a backoff, until a client connection is established. Auth is optional. // Dials a JSON-RPC endpoint repeatedly, with a backoff, until a client connection is established. Auth is optional.
func dialRPCClientWithBackoff(ctx context.Context, log log.Logger, addr string) (*rpc.Client, error) { func dialRPCClientWithBackoff(ctx context.Context, log log.Logger, addr string) (*rpc.Client, error) {
bOff := backoff.Fixed(defaultRetryTime) bOff := retry.Fixed(defaultRetryTime)
return backoff.Do(ctx, defaultRetryCount, bOff, func() (*rpc.Client, error) { return retry.Do(ctx, defaultRetryCount, bOff, func() (*rpc.Client, error) {
if !client.IsURLAvailable(addr) { if !client.IsURLAvailable(addr) {
log.Warn("failed to dial address, but may connect later", "addr", addr) log.Warn("failed to dial address, but may connect later", "addr", addr)
return nil, fmt.Errorf("address unavailable (%s)", addr) return nil, fmt.Errorf("address unavailable (%s)", addr)
......
package backoff package retry
import ( import (
"context" "context"
......
package backoff package retry
import ( import (
"context" "context"
......
package backoff package retry
import ( import (
"math" "math"
...@@ -16,35 +16,34 @@ type Strategy interface { ...@@ -16,35 +16,34 @@ type Strategy interface {
// ExponentialStrategy performs exponential backoff. The exponential backoff // ExponentialStrategy performs exponential backoff. The exponential backoff
// function is min(e.Min + (2^attempt * 1000) + randBetween(0, e.MaxJitter), e.Max) // function is min(e.Min + (2^attempt * 1000) + randBetween(0, e.MaxJitter), e.Max)
type ExponentialStrategy struct { type ExponentialStrategy struct {
// Min is the minimum amount of time to wait between attempts in ms. // Min is the minimum amount of time to wait between attempts.
Min float64 Min time.Duration
// Max is the maximum amount of time to wait between attempts in ms. // Max is the maximum amount of time to wait between attempts.
Max float64 Max time.Duration
// MaxJitter is the maximum amount of random jitter to insert between // MaxJitter is the maximum amount of random jitter to insert between attempts.
// attempts in ms. MaxJitter time.Duration
MaxJitter int
} }
func (e *ExponentialStrategy) Duration(attempt int) time.Duration { func (e *ExponentialStrategy) Duration(attempt int) time.Duration {
var jitter int var jitter time.Duration
if e.MaxJitter > 0 { if e.MaxJitter > 0 {
jitter = rand.Intn(e.MaxJitter) jitter = time.Duration(rand.Int63n(e.MaxJitter.Nanoseconds()))
} }
dur := e.Min + (math.Pow(2, float64(attempt)) * 1000) dur := e.Min + time.Duration(int(math.Pow(2, float64(attempt))*1000))*time.Millisecond
dur += float64(jitter) dur += jitter
if dur > e.Max { if dur > e.Max {
return time.Millisecond * time.Duration(e.Max) return e.Max
} }
return time.Millisecond * time.Duration(dur) return dur
} }
func Exponential() Strategy { func Exponential() Strategy {
return &ExponentialStrategy{ return &ExponentialStrategy{
Max: 10000, Max: time.Duration(10000 * time.Millisecond),
MaxJitter: 250, MaxJitter: time.Duration(250 * time.Millisecond),
} }
} }
......
package backoff package retry
import ( import (
"testing" "testing"
...@@ -9,13 +9,13 @@ import ( ...@@ -9,13 +9,13 @@ import (
func TestExponential(t *testing.T) { func TestExponential(t *testing.T) {
strategy := &ExponentialStrategy{ strategy := &ExponentialStrategy{
Min: 3000, Min: 3000 * time.Millisecond,
Max: 10000, Max: 10000 * time.Millisecond,
MaxJitter: 0, MaxJitter: 0,
} }
durations := []int{4, 5, 7, 10, 10} durations := []time.Duration{4, 5, 7, 10, 10}
for i, dur := range durations { for i, dur := range durations {
require.Equal(t, time.Millisecond*time.Duration(dur*1000), strategy.Duration(i)) require.Equal(t, dur*time.Second, strategy.Duration(i))
} }
} }
...@@ -17,7 +17,7 @@ import ( ...@@ -17,7 +17,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-service/backoff" "github.com/ethereum-optimism/optimism/op-service/retry"
"github.com/ethereum-optimism/optimism/op-service/txmgr/metrics" "github.com/ethereum-optimism/optimism/op-service/txmgr/metrics"
) )
...@@ -176,7 +176,7 @@ func (m *SimpleTxManager) send(ctx context.Context, candidate TxCandidate) (*typ ...@@ -176,7 +176,7 @@ func (m *SimpleTxManager) send(ctx context.Context, candidate TxCandidate) (*typ
ctx, cancel = context.WithTimeout(ctx, m.cfg.TxSendTimeout) ctx, cancel = context.WithTimeout(ctx, m.cfg.TxSendTimeout)
defer cancel() defer cancel()
} }
tx, err := backoff.Do(ctx, 30, backoff.Fixed(2*time.Second), func() (*types.Transaction, error) { tx, err := retry.Do(ctx, 30, retry.Fixed(2*time.Second), func() (*types.Transaction, error) {
tx, err := m.craftTx(ctx, candidate) tx, err := m.craftTx(ctx, candidate)
if err != nil { if err != nil {
m.l.Warn("Failed to create a transaction, will retry", "err", err) m.l.Warn("Failed to create a transaction, will retry", "err", err)
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
"express-prom-bundle": "^6.4.1", "express-prom-bundle": "^6.4.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"morgan": "^1.10.0", "morgan": "^1.10.0",
"pino": "^6.11.3", "pino": "^8.15.0",
"pino-multi-stream": "^5.3.0", "pino-multi-stream": "^5.3.0",
"pino-sentry": "^0.14.0", "pino-sentry": "^0.14.0",
"prom-client": "^13.1.0" "prom-client": "^13.1.0"
......
...@@ -11,7 +11,7 @@ export const logLevels = [ ...@@ -11,7 +11,7 @@ export const logLevels = [
'error', 'error',
'fatal', 'fatal',
] as const ] as const
export type LogLevel = typeof logLevels[number] export type LogLevel = (typeof logLevels)[number]
export interface LoggerOptions { export interface LoggerOptions {
name: string name: string
......
#!/bin/bash #!/usr/bin/env bash
rm -rf artifacts forge-artifacts rm -rf artifacts forge-artifacts
......
#!/bin/bash #!/usr/bin/env bash
if ! command -v forge &> /dev/null if ! command -v forge &> /dev/null
then then
......
...@@ -12,6 +12,7 @@ ignores: [ ...@@ -12,6 +12,7 @@ ignores: [
"chai", "chai",
"ts-node", "ts-node",
"typedoc", "typedoc",
"typescript",
"ethereum-waffle", "ethereum-waffle",
"nyc" "nyc"
] ]
...@@ -41,30 +41,31 @@ ...@@ -41,30 +41,31 @@
"@ethersproject/transactions": "^5.7.0", "@ethersproject/transactions": "^5.7.0",
"@nomiclabs/hardhat-ethers": "^2.0.2", "@nomiclabs/hardhat-ethers": "^2.0.2",
"@nomiclabs/hardhat-waffle": "^2.0.1", "@nomiclabs/hardhat-waffle": "^2.0.1",
"@types/chai": "^4.3.5",
"@types/chai-as-promised": "^7.1.5",
"@types/mocha": "^10.0.1",
"@types/node": "^20.5.0",
"chai-as-promised": "^7.1.1", "chai-as-promised": "^7.1.1",
"ethereum-waffle": "^4.0.10", "ethereum-waffle": "^4.0.10",
"ethers": "^5.7.0", "ethers": "^5.7.2",
"hardhat": "^2.9.6", "hardhat": "^2.9.6",
"hardhat-deploy": "^0.11.4", "hardhat-deploy": "^0.11.4",
"isomorphic-fetch": "^3.0.0", "isomorphic-fetch": "^3.0.0",
"mocha": "^10.0.0", "mocha": "^10.2.0",
"nyc": "^15.1.0", "nyc": "^15.1.0",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"typedoc": "^0.22.13", "typedoc": "^0.24.8",
"viem": "^0.3.30", "typescript": "^5.1.6",
"vitest": "^0.28.3", "viem": "^1.6.0",
"zod": "^3.11.6" "vitest": "^0.34.2",
"zod": "^3.22.1"
}, },
"dependencies": { "dependencies": {
"@eth-optimism/contracts": "0.6.0", "@eth-optimism/contracts": "0.6.0",
"@eth-optimism/contracts-bedrock": "0.16.0", "@eth-optimism/contracts-bedrock": "workspace:*",
"@eth-optimism/core-utils": "0.12.3", "@eth-optimism/core-utils": "workspace:*",
"@types/chai": "^4.2.18",
"@types/chai-as-promised": "^7.1.4",
"@types/mocha": "^10.0.1",
"@types/node": "^20.5.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"merkletreejs": "^0.2.27", "merkletreejs": "^0.3.10",
"rlp": "^2.2.7" "rlp": "^2.2.7"
}, },
"peerDependencies": { "peerDependencies": {
......
# @eth-optimism/web3.js-plugin # @eth-optimism/web3.js-plugin
## 0.1.2
### Patch Changes
- [#6873](https://github.com/ethereum-optimism/optimism/pull/6873) [`fdab6caa7`](https://github.com/ethereum-optimism/optimism/commit/fdab6caa7e6684b08882d2a766ccd727068c2b2f) Thanks [@spacesailor24](https://github.com/spacesailor24)! - Update code exmaples in README
## 0.1.1 ## 0.1.1
### Patch Changes ### Patch Changes
......
...@@ -28,10 +28,10 @@ yarn add @eth-optimism/web3.js-plugin ...@@ -28,10 +28,10 @@ yarn add @eth-optimism/web3.js-plugin
```typescript ```typescript
import Web3 from 'web3' import Web3 from 'web3'
import OptimismFeeEstimationPlugin from '@eth-optimism/web3.js-plugin' import { OptimismPlugin } from '@eth-optimism/web3.js-plugin'
const web3 = new Web3('http://yourProvider.com') const web3 = new Web3('http://yourProvider.com')
web3.registerPlugin(new OptimismFeeEstimationPlugin()) web3.registerPlugin(new OptimismPlugin())
``` ```
You will now have access to the following functions under the `op` namespace, i.e. `web3.op.someMethod` You will now have access to the following functions under the `op` namespace, i.e. `web3.op.someMethod`
...@@ -76,12 +76,15 @@ async estimateFees(transaction: Transaction, returnFormat?: ReturnFormat) ...@@ -76,12 +76,15 @@ async estimateFees(transaction: Transaction, returnFormat?: ReturnFormat)
```typescript ```typescript
import Web3 from 'web3' import Web3 from 'web3'
import { OptimismPlugin } from '@eth-optimism/web3.js-plugin'
import { import {
l2StandardBridgeABI, l2StandardBridgeABI,
l2StandardBridgeAddress, l2StandardBridgeAddress,
} from '@eth-optimism/contracts-ts' } from '@eth-optimism/contracts-ts'
const web3 = new Web3('https://mainnet.optimism.io') const web3 = new Web3('https://mainnet.optimism.io')
web3.registerPlugin(new OptimismPlugin())
const l2BridgeContract = new web3.eth.Contract( const l2BridgeContract = new web3.eth.Contract(
l2StandardBridgeABI, l2StandardBridgeABI,
optimistAddress[420] optimistAddress[420]
...@@ -117,12 +120,15 @@ console.log(totalFee) // 26608988767659n ...@@ -117,12 +120,15 @@ console.log(totalFee) // 26608988767659n
```typescript ```typescript
import Web3 from 'web3' import Web3 from 'web3'
import { OptimismPlugin } from '@eth-optimism/web3.js-plugin'
import { import {
l2StandardBridgeABI, l2StandardBridgeABI,
l2StandardBridgeAddress, l2StandardBridgeAddress,
} from '@eth-optimism/contracts-ts' } from '@eth-optimism/contracts-ts'
const web3 = new Web3('https://mainnet.optimism.io') const web3 = new Web3('https://mainnet.optimism.io')
web3.registerPlugin(new OptimismPlugin())
const l2BridgeContract = new web3.eth.Contract( const l2BridgeContract = new web3.eth.Contract(
l2StandardBridgeABI, l2StandardBridgeABI,
optimistAddress[420] optimistAddress[420]
......
{ {
"name": "@eth-optimism/web3.js-plugin", "name": "@eth-optimism/web3.js-plugin",
"version": "0.1.1", "version": "0.1.2",
"description": "A Web3.js plugin for doing OP-Chain gas estimation", "description": "A Web3.js plugin for doing OP-Chain gas estimation",
"license": "MIT", "license": "MIT",
"repository": { "repository": {
......
This diff is collapsed.
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