Commit 3406775a authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

Merge pull request #2694 from ethereum-optimism/develop

Develop -> Master
parents 31304246 0f794f93
---
'@eth-optimism/teleportr': patch
---
Improve metrics
---
---
chore(deps): bump github.com/ethereum/go-ethereum from 1.10.16 to 1.10.17 in /op-exporter
---
'@eth-optimism/teleportr': patch
---
Increase max disbursements to 15
---
'@eth-optimism/contracts-bedrock': patch
---
Move core-utils to deps instead of devdeps
......@@ -63,7 +63,7 @@ jobs:
yarn-monorepo:
docker:
- image: ethereumoptimism/js-builder:nightly
- image: ethereumoptimism/js-builder:latest
steps:
- restore_cache:
keys:
......@@ -98,8 +98,7 @@ jobs:
- integration-tests/node_modules
- run:
name: Build monorepo
command: |
yarn build
command: yarn build
- save_cache:
key: v2-cache-yarn-build-{{ .Revision }}
paths:
......@@ -366,15 +365,14 @@ jobs:
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" "/input/meta/**/*.md" "/input/op-node/**/*.md" || exit 0
bedrock-solidity:
contracts-bedrock-tests:
docker:
- image: ethereumoptimism/js-builder:nightly
- image: ethereumoptimism/js-builder:latest
steps:
- restore_cache:
keys:
- v2-cache-yarn-build-{{ .Revision }}
- checkout
- run:
name: install
command: yarn install
working_directory: packages/contracts-bedrock
- run:
name: lint
command: yarn lint:check
......@@ -383,10 +381,6 @@ jobs:
name: slither
command: yarn slither || exit 0
working_directory: packages/contracts-bedrock
- run:
name: build
command: yarn build
working_directory: packages/contracts-bedrock
- run:
name: test
command: yarn test
......@@ -468,7 +462,7 @@ jobs:
bedrock-integration-tests:
machine:
image: ethereumoptimism/js-builder:nightly
image: ethereumoptimism/js-builder:latest
docker_layer_caching: true
steps:
- checkout
......@@ -490,7 +484,6 @@ workflows:
jobs:
- yarn-monorepo
- bedrock-go-tests
- bedrock-solidity
- bedrock-markdown
- fuzz-op-node
- go-lint-test-build:
......@@ -522,6 +515,9 @@ workflows:
- contracts-periphery-tests:
requires:
- yarn-monorepo
- contracts-bedrock-tests:
requires:
- yarn-monorepo
- js-lint-test:
name: dtl-tests
package_name: data-transport-layer
......
......@@ -10,6 +10,7 @@ pull_request_rules:
- "#approved-reviews-by>=2"
- "#changes-requested-reviews-by=0"
- "label!=do-not-merge"
- "label!=mergify-ignore"
- or:
- and:
- "label!=SR-Risk"
......
......@@ -56,7 +56,7 @@ jobs:
${{ runner.os }}-yarn-
- name: Install Dependencies
run: yarn
run: yarn --frozen-lockfile
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
......
......@@ -53,7 +53,7 @@ jobs:
${{ runner.os }}-yarn-
- name: Install Dependencies
run: yarn
run: yarn --frozen-lockfile
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
......
......@@ -11,8 +11,8 @@ jobs:
ports:
- 5000:5000
env:
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
steps:
- uses: actions/checkout@v2
......@@ -53,7 +53,7 @@ jobs:
- name: Run the sync tests
working-directory: ./integration-tests
run: |
yarn
yarn --frozen-lockfile
yarn build
yarn test:sync
......
COMPOSEFLAGS=-d
ITESTS_L2_HOST=http://localhost:9545
build: build-go contracts integration-tests
build: build-go build-ts
.PHONY: build
build-go: submodules op-node op-proposer op-batcher
.PHONY: build-go
build-ts: submodules contracts integration-tests
build-ts: submodules
yarn build
.PHONY: build-ts
submodules:
......@@ -42,14 +43,6 @@ mod-tidy:
cd ./op-e2e && go mod tidy && cd ..
.PHONY: mod-tidy
contracts:
cd ./contracts-bedrock && yarn install && yarn build
.PHONY: contracts
integration-tests:
cd ./packages/integration-tests-bedrock && yarn install && yarn build:contracts
.PHONY: integration-tests
clean:
rm -rf ./bin
.PHONY: clean
......@@ -63,12 +56,12 @@ devnet-down:
.PHONY: devnet-down
devnet-clean:
rm -rf ./contracts-bedrock/deployments/devnetL1
rm -rf ./packages/contracts-bedrock/deployments/devnetL1
rm -rf ./.devnet
cd ./ops-bedrock && docker-compose down
docker volume rm ops-bedrock_l1_data
docker volume rm ops-bedrock_l2_data
docker volume rm ops-bedrock_op_log
docker image ls | grep ops-bedrock_ | cut -d ' ' -f 1 | xargs docker rmi
docker volume ls | grep ops-bedrock_ | cut -d ' ' -f 1 | xargs docker volume rm
.PHONY: devnet-clean
test-unit:
......@@ -76,12 +69,12 @@ test-unit:
make -C ./op-proposer test
make -C ./op-batcher test
make -C ./op-e2e test
cd ./contracts-bedrock && yarn test
yarn test
.PHONY: test-unit
test-integration:
bash ./ops-bedrock/test-integration.sh \
./contracts-bedrock/deployments/devnetL1
./packages/contracts-bedrock/deployments/devnetL1
.PHONY: test-integration
devnet-genesis:
......
......@@ -17,7 +17,7 @@ use (
./teleportr
)
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220518163235-a32d414959ea
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f
// For local debugging:
// replace github.com/ethereum/go-ethereum v1.10.17 => ../go-ethereum
//replace github.com/ethereum/go-ethereum v1.10.17 => ../go-ethereum
github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220512193241-32ef0bba48ce h1:Wa0BVNdeyzIoJkrZtI7o2NEw8F98vVIzkPpiFACbdCA=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220512193241-32ef0bba48ce/go.mod h1:zwRwhzbX7GhQgG12DdrLr9aRGGLObKwmZxYrCLICIRc=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220518163235-a32d414959ea h1:xGKKbowc5Q2d4VEYMkJg6E3h5ki2Kgi2r+qxaTHCnxc=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220518163235-a32d414959ea/go.mod h1:zwRwhzbX7GhQgG12DdrLr9aRGGLObKwmZxYrCLICIRc=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f h1:Ad47wE5WEFzyOaaLff7LTRh79mUgWHKuYe4fpGOG23k=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f/go.mod h1:RD3NhcSBjZpj3k+SnQq24wBrmnmie78P5R/P62iNBD8=
github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio=
github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w=
github.com/libp2p/go-yamux v1.4.1 h1:P1Fe9vF4th5JOxxgQvfbOHkrGqIZniTLf+ddhZp8YTI=
......@@ -6,7 +6,7 @@ metadata:
spec:
selector:
app: l2geth-replica
type: ClusterIP
type: NodePort
ports:
- name: rpc
port: 8545
......
......@@ -9,6 +9,9 @@ spec:
containers:
- name: replica-healthcheck
image: ethereumoptimism/replica-healthcheck-v1
envFrom:
- configMapRef:
name: replica-healthcheck-v1
ports:
- containerPort: 7300
name: metrics
......
......@@ -14,6 +14,7 @@ resources:
- ../../bases/l2geth-replica
- ../../bases/servicemonitors
- ../../bases/replica-healthcheck
- ../../bases/replica-healthcheck-v1
- ./volumes.yaml
images:
......@@ -26,6 +27,9 @@ images:
- name: ethereumoptimism/replica-healthcheck
newName: ethereumoptimism/replica-healthcheck
newTag: 0.3.6
- name: ethereumoptimism/replica-healthcheck-v1
newName: ethereumoptimism/replica-healthcheck
newTag: 1.0.6
patchesStrategicMerge:
- ./patches/dtl.yaml
......@@ -44,4 +48,9 @@ patches:
group: apps
version: v1
kind: StatefulSet
name: data-transport-layer
\ No newline at end of file
name: data-transport-layer
configMapGenerator:
- name: replica-healthcheck-v1
envs:
- ./replica-healthcheck-v1.env
HEALTHCHECK__REFERENCE_RPC_PROVIDER=http://sequencer.default:8545
HEALTHCHECK__TARGET_RPC_PROVIDER=http://l2geth-replica:8545
\ No newline at end of file
......@@ -15,18 +15,22 @@ resources:
- ../../bases/l2geth-replica
- ../../bases/servicemonitors
- ../../bases/replica-healthcheck
- ../../bases/replica-healthcheck-v1
- ./volumes.yaml
images:
- name: ethereumoptimism/data-transport-layer
newName: ethereumoptimism/data-transport-layer
newTag: 0.5.21
newTag: prerelease-dtl-race
- name: ethereumoptimism/l2geth
newName: ethereumoptimism/l2geth
newTag: 0.5.14
newTag: prerelease-l2g-l1-sync-recovery
- name: ethereumoptimism/replica-healthcheck
newName: ethereumoptimism/replica-healthcheck
newTag: 0.3.6
- name: ethereumoptimism/replica-healthcheck-v1
newName: ethereumoptimism/replica-healthcheck
newTag: 1.0.6
patchesStrategicMerge:
- ./patches/dtl.yaml
......@@ -45,4 +49,9 @@ patches:
group: apps
version: v1
kind: StatefulSet
name: data-transport-layer
\ No newline at end of file
name: data-transport-layer
configMapGenerator:
- name: replica-healthcheck-v1
envs:
- ./replica-healthcheck-v1.env
HEALTHCHECK__REFERENCE_RPC_PROVIDER=http://sequencer.default:8545
HEALTHCHECK__TARGET_RPC_PROVIDER=http://l2geth-replica:8545
\ No newline at end of file
......@@ -13,7 +13,7 @@ resources:
- ../../bases/data-transport-layer
- ../../bases/l2geth-replica
- ../../bases/servicemonitors
- ../../bases/replica-healthcheck
- ../../bases/replica-healthcheck-v1
- ./ingress.yaml
- ./volumes.yaml
......@@ -24,14 +24,13 @@ images:
- name: ethereumoptimism/l2geth
newName: ethereumoptimism/l2geth
newTag: 0.5.14
- name: ethereumoptimism/replica-healthcheck
- name: ethereumoptimism/replica-healthcheck-v1
newName: ethereumoptimism/replica-healthcheck
newTag: 0.3.6
newTag: 1.0.6
patchesStrategicMerge:
- ./patches/dtl.yaml
- ./patches/l2geth.yaml
- ./patches/replica-healthcheck.yaml
patches:
- path: ./patches/l2geth-volume.yaml
......@@ -45,4 +44,9 @@ patches:
group: apps
version: v1
kind: StatefulSet
name: data-transport-layer
\ No newline at end of file
name: data-transport-layer
configMapGenerator:
- name: replica-healthcheck-v1
envs:
- ./replica-healthcheck-v1.env
HEALTHCHECK__REFERENCE_RPC_PROVIDER=https://kovan.optimism.io
HEALTHCHECK__TARGET_RPC_PROVIDER=http://l2geth-replica:8545
\ No newline at end of file
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: kovan-replica-0-5-17
commonLabels:
network: kovan
provider: internal
bases:
- ../../../envs/kovan-gen5-berlin
- ../../../scripts
resources:
- ../../bases/data-transport-layer
- ../../bases/l2geth-replica
- ../../bases/servicemonitors
- ../../bases/replica-healthcheck-v1
- ./volumes.yaml
images:
- name: ethereumoptimism/data-transport-layer
newName: ethereumoptimism/data-transport-layer
newTag: 0.5.23
- name: ethereumoptimism/l2geth
newName: ethereumoptimism/l2geth
newTag: 0.5.17
- name: ethereumoptimism/replica-healthcheck-v1
newName: ethereumoptimism/replica-healthcheck
newTag: 1.0.6
patchesStrategicMerge:
- ./patches/dtl.yaml
- ./patches/l2geth.yaml
patches:
- path: ./patches/l2geth-volume.yaml
target:
group: apps
version: v1
kind: StatefulSet
name: l2geth-replica
- path: ./patches/dtl-volume.yaml
target:
group: apps
version: v1
kind: StatefulSet
name: data-transport-layer
configMapGenerator:
- name: replica-healthcheck-v1
envs:
- ./replica-healthcheck-v1.env
---
- op: replace
path: /spec/template/spec/volumes/0
value:
name: data-transport-layer
persistentVolumeClaim:
claimName: data-transport-layer-data
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: data-transport-layer
spec:
template:
spec:
initContainers:
- name: wait-for-l1
env:
- name: L1_NODE_WEB3_URL
valueFrom:
secretKeyRef:
name: replica-secrets
key: l1-rpc-endpoint
containers:
- name: data-transport-layer
resources:
limits:
cpu: "2"
memory: 4Gi
requests:
cpu: "1"
memory: 1Gi
env:
- name: DATA_TRANSPORT_LAYER__L1_RPC_ENDPOINT
valueFrom:
secretKeyRef:
name: replica-secrets
key: l1-rpc-endpoint
- name: DATA_TRANSPORT_LAYER__L2_RPC_ENDPOINT
valueFrom:
secretKeyRef:
name: replica-secrets
key: l2-rpc-endpoint
- name: L1_NODE_WEB3_URL
valueFrom:
secretKeyRef:
name: replica-secrets
key: l1-rpc-endpoint
\ No newline at end of file
- op: replace
path: /spec/template/spec/volumes/0
value:
name: l2geth-replica-data
persistentVolumeClaim:
claimName: l2geth-replica-data
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: l2geth-replica
spec:
template:
spec:
containers:
- name: l2geth-replica
env:
- name: IPC_DISABLE
value: "false"
resources:
limits:
cpu: "4"
memory: 12Gi
requests:
cpu: "2"
memory: 8Gi
HEALTHCHECK__REFERENCE_RPC_PROVIDER=https://kovan.optimism.io
HEALTHCHECK__TARGET_RPC_PROVIDER=http://l2geth-replica:8545
\ No newline at end of file
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: l2geth-replica-data
spec:
storageClassName: premium-rwo
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 200Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-transport-layer-data
spec:
storageClassName: premium-rwo
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
......@@ -13,7 +13,6 @@ resources:
- ../../bases/data-transport-layer
- ../../bases/l2geth-replica
- ../../bases/servicemonitors
- ../../bases/replica-healthcheck
- ../../bases/replica-healthcheck-v1
- ./volumes.yaml
- ./ingress.yaml
......@@ -30,12 +29,11 @@ images:
newTag: 0.3.3
- name: ethereumoptimism/replica-healthcheck-v1
newName: ethereumoptimism/replica-healthcheck
newTag: 1.0.4
newTag: 1.0.6
patchesStrategicMerge:
- ./patches/dtl.yaml
- ./patches/l2geth.yaml
- ./patches/replica-healthcheck.yaml
patches:
- path: ./patches/l2geth-volume.yaml
......
......@@ -13,7 +13,6 @@ resources:
- ../../bases/data-transport-layer
- ../../bases/l2geth-replica
- ../../bases/servicemonitors
- ../../bases/replica-healthcheck
- ../../bases/replica-healthcheck-v1
- ./volumes.yaml
......@@ -24,17 +23,13 @@ images:
- name: ethereumoptimism/l2geth
newName: ethereumoptimism/l2geth
newTag: 0.5.17
- name: ethereumoptimism/replica-healthcheck
newName: ethereumoptimism/replica-healthcheck
newTag: 0.3.3
- name: ethereumoptimism/replica-healthcheck-v1
newName: ethereumoptimism/replica-healthcheck
newTag: 1.0.4
newTag: 1.0.6
patchesStrategicMerge:
- ./patches/dtl.yaml
- ./patches/l2geth.yaml
- ./patches/replica-healthcheck.yaml
patches:
- path: ./patches/l2geth-volume.yaml
......
......@@ -160,4 +160,4 @@ replace (
github.com/ethereum-optimism/optimism/op-proposer v0.0.0 => ../op-proposer
)
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602143715-bea96bb3e75d
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f
......@@ -243,8 +243,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602143715-bea96bb3e75d h1:Jc7YIDFx88lmiPrmS2p/mwqbETCJpdm7rj1fagbs6zc=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602143715-bea96bb3e75d/go.mod h1:RD3NhcSBjZpj3k+SnQq24wBrmnmie78P5R/P62iNBD8=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f h1:Ad47wE5WEFzyOaaLff7LTRh79mUgWHKuYe4fpGOG23k=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f/go.mod h1:RD3NhcSBjZpj3k+SnQq24wBrmnmie78P5R/P62iNBD8=
github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY=
......
......@@ -31,7 +31,7 @@ var (
// L2ToL1MessagePasserMetaData contains all meta data concerning the L2ToL1MessagePasser contract.
var L2ToL1MessagePasserMetaData = &bind.MetaData{
ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"WithdrawalInitiated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrawerBalanceBurnt\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"initiateWithdrawal\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"sentMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]",
Bin: "0x608060405234801561001057600080fd5b506104a1806100206000396000f3fe6080604052600436106100435760003560e01c806344df8e701461006c57806382e3702d14610081578063affed0e0146100c6578063c2b3e5ac146100ea57600080fd5b366100675761006533620186a0604051806020016040528060008152506100f8565b005b600080fd5b34801561007857600080fd5b506100656101ae565b34801561008d57600080fd5b506100b161009c366004610256565b60006020819052908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156100d257600080fd5b506100dc60015481565b6040519081526020016100bd565b6100656100f836600461029e565b600061010a600154338634878761020b565b6000818152602081905260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915554905191925073ffffffffffffffffffffffffffffffffffffffff8616913391907f87bf7b546c8de873abb0db5b579ec131f8d0cf5b14f39933551cf9ced23a6136906101989034908990899061040d565b60405180910390a4505060018054810190555050565b604051479081906101be9061024a565b6040518091039082f09050801580156101db573d6000803e3d6000fd5b505060405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b600086868686868660405160200161022896959493929190610435565b6040516020818303038152906040528051906020012090509695505050505050565b60088061048d83390190565b60006020828403121561026857600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156102b357600080fd5b833573ffffffffffffffffffffffffffffffffffffffff811681146102d757600080fd5b925060208401359150604084013567ffffffffffffffff808211156102fb57600080fd5b818601915086601f83011261030f57600080fd5b8135818111156103215761032161026f565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156103675761036761026f565b8160405282815289602084870101111561038057600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b818110156103c8576020818501810151868301820152016103ac565b818111156103da576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b83815282602082015260606040820152600061042c60608301846103a2565b95945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261048060c08301846103a2565b9897505050505050505056fe608060405230fffea164736f6c634300080a000a",
Bin: "0x608060405234801561001057600080fd5b506104ab806100206000396000f3fe6080604052600436106100435760003560e01c806344df8e701461006c57806382e3702d14610081578063affed0e0146100c6578063c2b3e5ac146100ea57600080fd5b366100675761006533620186a0604051806020016040528060008152506100f8565b005b600080fd5b34801561007857600080fd5b506100656101ae565b34801561008d57600080fd5b506100b161009c366004610260565b60006020819052908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156100d257600080fd5b506100dc60015481565b6040519081526020016100bd565b6100656100f83660046102a8565b600061010a60015433863487876101e6565b6000818152602081905260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915554905191925073ffffffffffffffffffffffffffffffffffffffff8616913391907f87bf7b546c8de873abb0db5b579ec131f8d0cf5b14f39933551cf9ced23a61369061019890349089908990610417565b60405180910390a4505060018054810190555050565b476101b881610225565b60405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b60008686868686866040516020016102039695949392919061043f565b6040516020818303038152906040528051906020012090509695505050505050565b8060405161023290610254565b6040518091039082f090508015801561024f573d6000803e3d6000fd5b505050565b60088061049783390190565b60006020828403121561027257600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156102bd57600080fd5b833573ffffffffffffffffffffffffffffffffffffffff811681146102e157600080fd5b925060208401359150604084013567ffffffffffffffff8082111561030557600080fd5b818601915086601f83011261031957600080fd5b81358181111561032b5761032b610279565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561037157610371610279565b8160405282815289602084870101111561038a57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b818110156103d2576020818501810151868301820152016103b6565b818111156103e4576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b83815282602082015260606040820152600061043660608301846103ac565b95945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261048a60c08301846103ac565b9897505050505050505056fe608060405230fffea164736f6c634300080a000a",
}
// L2ToL1MessagePasserABI is the input ABI used to generate the binding from.
......
......@@ -2,4 +2,4 @@
// This file is a generated binding and any manual changes will be lost.
package bindings
var L2ToL1MessagePasserDeployedBin = "0x6080604052600436106100435760003560e01c806344df8e701461006c57806382e3702d14610081578063affed0e0146100c6578063c2b3e5ac146100ea57600080fd5b366100675761006533620186a0604051806020016040528060008152506100f8565b005b600080fd5b34801561007857600080fd5b506100656101ae565b34801561008d57600080fd5b506100b161009c366004610256565b60006020819052908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156100d257600080fd5b506100dc60015481565b6040519081526020016100bd565b6100656100f836600461029e565b600061010a600154338634878761020b565b6000818152602081905260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915554905191925073ffffffffffffffffffffffffffffffffffffffff8616913391907f87bf7b546c8de873abb0db5b579ec131f8d0cf5b14f39933551cf9ced23a6136906101989034908990899061040d565b60405180910390a4505060018054810190555050565b604051479081906101be9061024a565b6040518091039082f09050801580156101db573d6000803e3d6000fd5b505060405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b600086868686868660405160200161022896959493929190610435565b6040516020818303038152906040528051906020012090509695505050505050565b60088061048d83390190565b60006020828403121561026857600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156102b357600080fd5b833573ffffffffffffffffffffffffffffffffffffffff811681146102d757600080fd5b925060208401359150604084013567ffffffffffffffff808211156102fb57600080fd5b818601915086601f83011261030f57600080fd5b8135818111156103215761032161026f565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156103675761036761026f565b8160405282815289602084870101111561038057600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b818110156103c8576020818501810151868301820152016103ac565b818111156103da576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b83815282602082015260606040820152600061042c60608301846103a2565b95945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261048060c08301846103a2565b9897505050505050505056fe608060405230fffea164736f6c634300080a000a"
var L2ToL1MessagePasserDeployedBin = "0x6080604052600436106100435760003560e01c806344df8e701461006c57806382e3702d14610081578063affed0e0146100c6578063c2b3e5ac146100ea57600080fd5b366100675761006533620186a0604051806020016040528060008152506100f8565b005b600080fd5b34801561007857600080fd5b506100656101ae565b34801561008d57600080fd5b506100b161009c366004610260565b60006020819052908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156100d257600080fd5b506100dc60015481565b6040519081526020016100bd565b6100656100f83660046102a8565b600061010a60015433863487876101e6565b6000818152602081905260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915554905191925073ffffffffffffffffffffffffffffffffffffffff8616913391907f87bf7b546c8de873abb0db5b579ec131f8d0cf5b14f39933551cf9ced23a61369061019890349089908990610417565b60405180910390a4505060018054810190555050565b476101b881610225565b60405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b60008686868686866040516020016102039695949392919061043f565b6040516020818303038152906040528051906020012090509695505050505050565b8060405161023290610254565b6040518091039082f090508015801561024f573d6000803e3d6000fd5b505050565b60088061049783390190565b60006020828403121561027257600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156102bd57600080fd5b833573ffffffffffffffffffffffffffffffffffffffff811681146102e157600080fd5b925060208401359150604084013567ffffffffffffffff8082111561030557600080fd5b818601915086601f83011261031957600080fd5b81358181111561032b5761032b610279565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561037157610371610279565b8160405282815289602084870101111561038a57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000815180845260005b818110156103d2576020818501810151868301820152016103b6565b818111156103e4576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b83815282602082015260606040820152600061043660608301846103ac565b95945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261048a60c08301846103ac565b9897505050505050505056fe608060405230fffea164736f6c634300080a000a"
This diff is collapsed.
......@@ -27,4 +27,4 @@ require (
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
)
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602143715-bea96bb3e75d
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f
......@@ -98,8 +98,8 @@ github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ=
github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602143715-bea96bb3e75d h1:Jc7YIDFx88lmiPrmS2p/mwqbETCJpdm7rj1fagbs6zc=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602143715-bea96bb3e75d/go.mod h1:RD3NhcSBjZpj3k+SnQq24wBrmnmie78P5R/P62iNBD8=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f h1:Ad47wE5WEFzyOaaLff7LTRh79mUgWHKuYe4fpGOG23k=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f/go.mod h1:RD3NhcSBjZpj3k+SnQq24wBrmnmie78P5R/P62iNBD8=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
......
......@@ -6,8 +6,6 @@ import (
"errors"
"fmt"
"math/big"
"strconv"
"strings"
"time"
"github.com/ethereum/go-ethereum"
......@@ -98,8 +96,8 @@ func initL1Geth(cfg *SystemConfig, wallet *hdwallet.Wallet, genesis *core.Genesi
}
nodeConfig := &node.Config{
Name: "l1-geth",
WSHost: cfg.L1WsAddr,
WSPort: cfg.L1WsPort,
WSHost: "127.0.0.1",
WSPort: 0,
WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal", "engine"},
HTTPModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal", "engine"},
}
......@@ -107,27 +105,21 @@ func initL1Geth(cfg *SystemConfig, wallet *hdwallet.Wallet, genesis *core.Genesi
return createGethNode(false, nodeConfig, ethConfig, []*ecdsa.PrivateKey{pk})
}
func initL2Geth(name, addr string, l2ChainID *big.Int, genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) {
// init a geth node.
func initL2Geth(name string, l2ChainID *big.Int, genesis *core.Genesis, jwtPath string) (*node.Node, *eth.Ethereum, error) {
ethConfig := &ethconfig.Config{
NetworkId: l2ChainID.Uint64(),
Genesis: genesis,
}
// Parsing ws://127.0.0.1:9091 for "127.0.0.1" and "9091"
s := strings.Split(addr, ":")
_, host, ok := strings.Cut(s[1], "//")
if !ok {
return nil, nil, fmt.Errorf("could not find ws host in %s", addr)
}
port, err := strconv.ParseInt(s[2], 10, 32)
if err != nil {
return nil, nil, fmt.Errorf("failed to parse port from address: %w", err)
}
nodeConfig := &node.Config{
Name: fmt.Sprintf("l2-geth-%v", name),
WSHost: host,
WSPort: int(port),
WSHost: "127.0.0.1",
WSPort: 0,
AuthAddr: "127.0.0.1",
AuthPort: 0,
WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal", "engine"},
HTTPModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal", "engine"},
JWTSecret: jwtPath,
}
return createGethNode(true, nodeConfig, ethConfig, nil)
}
......
......@@ -167,4 +167,4 @@ replace (
github.com/ethereum-optimism/optimism/op-proposer v0.0.0 => ../op-proposer
)
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602143715-bea96bb3e75d
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f
......@@ -244,8 +244,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602143715-bea96bb3e75d h1:Jc7YIDFx88lmiPrmS2p/mwqbETCJpdm7rj1fagbs6zc=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602143715-bea96bb3e75d/go.mod h1:RD3NhcSBjZpj3k+SnQq24wBrmnmie78P5R/P62iNBD8=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f h1:Ad47wE5WEFzyOaaLff7LTRh79mUgWHKuYe4fpGOG23k=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f/go.mod h1:RD3NhcSBjZpj3k+SnQq24wBrmnmie78P5R/P62iNBD8=
github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY=
......
......@@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"
hdwallet "github.com/miguelmota/go-ethereum-hdwallet"
)
......@@ -75,10 +76,12 @@ type SystemConfig struct {
L2OOCfg L2OOContractConfig
DepositCFG DepositContractConfig
L1WsAddr string
L1WsPort int
L1ChainID *big.Int
L2ChainID *big.Int
L1ChainID *big.Int
L2ChainID *big.Int
JWTFilePath string
JWTSecret [32]byte
Nodes map[string]*rollupNode.Config // Per node config. Don't use populate rollup.Config
Loggers map[string]log.Logger
RollupConfig rollup.Config // Shared rollup configs
......@@ -293,8 +296,9 @@ func (cfg SystemConfig) start() (*System, error) {
}
sys.nodes["l1"] = l1Node
sys.backends["l1"] = l1Backend
for name, l2Cfg := range cfg.Nodes {
node, backend, err := initL2Geth(name, l2Cfg.L2EngineAddrs[0], cfg.L2ChainID, l2Genesis)
for name := range cfg.Nodes {
node, backend, err := initL2Geth(name, cfg.L2ChainID, l2Genesis, cfg.JWTFilePath)
if err != nil {
return nil, err
}
......@@ -324,14 +328,28 @@ func (cfg SystemConfig) start() (*System, error) {
}
}
// Configure connections to L1 and L2 for rollup nodes.
// TODO: refactor testing to use in-process rpc connections instead of websockets.
for name, rollupCfg := range cfg.Nodes {
rollupCfg.L1 = &rollupNode.L1EndpointConfig{
L1NodeAddr: l1Node.WSEndpoint(),
L1TrustRPC: false,
}
rollupCfg.L2s = &rollupNode.L2EndpointsConfig{
L2EngineAddrs: []string{sys.nodes[name].WSAuthEndpoint()},
L2EngineJWTSecrets: [][32]byte{cfg.JWTSecret},
}
}
// Geth Clients
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
l1Client, err := ethclient.DialContext(ctx, fmt.Sprintf("ws://%s:%d", cfg.L1WsAddr, cfg.L1WsPort))
l1Srv, err := l1Node.RPCHandler()
if err != nil {
didErrAfterStart = true
return nil, err
}
l1Client := ethclient.NewClient(rpc.DialInProc(l1Srv))
sys.Clients["l1"] = l1Client
for name, node := range sys.nodes {
client, err := ethclient.DialContext(ctx, node.WSEndpoint())
......@@ -512,8 +530,8 @@ func (cfg SystemConfig) start() (*System, error) {
// L2Output Submitter
sys.l2OutputSubmitter, err = l2os.NewL2OutputSubmitter(l2os.Config{
L1EthRpc: "ws://127.0.0.1:9090",
L2EthRpc: sys.cfg.Nodes["sequencer"].L2NodeAddr,
L1EthRpc: sys.nodes["l1"].WSEndpoint(),
L2EthRpc: sys.nodes["sequencer"].WSEndpoint(),
RollupRpc: rollupEndpoint,
L2OOAddress: sys.L2OOContractAddr.String(),
PollInterval: 50 * time.Millisecond,
......@@ -544,8 +562,8 @@ func (cfg SystemConfig) start() (*System, error) {
// Batch Submitter
sys.batchSubmitter, err = bss.NewBatchSubmitter(bss.Config{
L1EthRpc: "ws://127.0.0.1:9090",
L2EthRpc: sys.cfg.Nodes["sequencer"].L2NodeAddr,
L1EthRpc: sys.nodes["l1"].WSEndpoint(),
L2EthRpc: sys.nodes["sequencer"].WSEndpoint(),
RollupRpc: rollupEndpoint,
MinL1TxSize: 1,
MaxL1TxSize: 120000,
......
......@@ -5,6 +5,8 @@ import (
"flag"
"fmt"
"math/big"
"os"
"path"
"testing"
"time"
......@@ -24,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
......@@ -59,8 +62,18 @@ const (
var (
batchInboxAddress = common.Address{0xff, 0x02}
testingJWTSecret = [32]byte{123}
)
func writeDefaultJWT(t *testing.T) string {
// Sadly the geth node config cannot load JWT secret from memory, it has to be a file
jwtPath := path.Join(t.TempDir(), "jwt_secret")
if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(testingJWTSecret[:])), 0600); err != nil {
t.Fatalf("failed to prepare jwt file for geth: %v", err)
}
return jwtPath
}
func defaultSystemConfig(t *testing.T) SystemConfig {
return SystemConfig{
Mnemonic: "squirrel green gallery layer logic title habit chase clog actress language enrich body plate fun pledge gap abuse mansion define either blast alien witness",
......@@ -86,23 +99,14 @@ func defaultSystemConfig(t *testing.T) SystemConfig {
CliqueSignerDerivationPath: cliqueSignerHDPath,
L1InfoPredeployAddress: derive.L1InfoPredeployAddr,
L1BlockTime: 2,
L1WsAddr: "127.0.0.1",
L1WsPort: 9090,
L1ChainID: big.NewInt(900),
L2ChainID: big.NewInt(901),
JWTFilePath: writeDefaultJWT(t),
JWTSecret: testingJWTSecret,
Nodes: map[string]*rollupNode.Config{
"verifier": {
L1NodeAddr: "ws://127.0.0.1:9090",
L2EngineAddrs: []string{"ws://127.0.0.1:9091"},
L2NodeAddr: "ws://127.0.0.1:9091",
L1TrustRPC: false,
},
"verifier": {},
"sequencer": {
L1NodeAddr: "ws://127.0.0.1:9090",
L2EngineAddrs: []string{"ws://127.0.0.1:9092"},
L2NodeAddr: "ws://127.0.0.1:9092",
L1TrustRPC: false,
Sequencer: true,
Sequencer: true,
// Submitter PrivKey is set in system start for rollup nodes where sequencer = true
RPC: node.RPCConfig{
ListenAddr: "127.0.0.1",
......@@ -786,7 +790,7 @@ func TestWithdrawals(t *testing.T) {
header, err = l2Seq.HeaderByNumber(ctx, blockNumber)
require.Nil(t, err)
rpc, err := rpc.Dial(cfg.Nodes["sequencer"].L2NodeAddr)
rpc, err := rpc.Dial(sys.nodes["sequencer"].WSEndpoint())
require.Nil(t, err)
l2client := withdrawals.NewClient(rpc)
......
......@@ -3,7 +3,7 @@ module github.com/ethereum-optimism/optimism/op-exporter
go 1.18
require (
github.com/ethereum/go-ethereum v1.10.16
github.com/ethereum/go-ethereum v1.10.17
github.com/prometheus/client_golang v1.11.0
github.com/sirupsen/logrus v1.7.0
github.com/ybbus/jsonrpc v2.1.2+incompatible
......@@ -42,7 +42,6 @@ require (
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
k8s.io/api v0.21.2 // indirect
k8s.io/klog/v2 v2.8.0 // indirect
k8s.io/utils v0.0.0-20201110183641-67b214c5f920 // indirect
......
This diff is collapsed.
......@@ -63,14 +63,16 @@ func main() {
func RollupNodeMain(ctx *cli.Context) error {
log.Info("Initializing Rollup Node")
cfg, err := opnode.NewConfig(ctx)
logCfg, err := opnode.NewLogConfig(ctx)
if err != nil {
log.Error("Unable to create the rollup node config", "error", err)
log.Error("Unable to create the log config", "error", err)
return err
}
logCfg, err := opnode.NewLogConfig(ctx)
log := logCfg.NewLogger()
cfg, err := opnode.NewConfig(ctx, log)
if err != nil {
log.Error("Unable to create the log config", "error", err)
log.Error("Unable to create the rollup node config", "error", err)
return err
}
snapshotLog, err := opnode.NewSnapshotLogger(ctx)
......@@ -79,7 +81,7 @@ func RollupNodeMain(ctx *cli.Context) error {
return err
}
n, err := node.New(context.Background(), cfg, logCfg.NewLogger(), snapshotLog, VersionWithMeta)
n, err := node.New(context.Background(), cfg, log, snapshotLog, VersionWithMeta)
if err != nil {
log.Error("Unable to create the rollup node", "error", err)
return err
......
......@@ -31,12 +31,6 @@ var (
Required: true,
EnvVar: prefixEnvVar("ROLLUP_CONFIG"),
}
L2EthNodeAddr = cli.StringFlag{
Name: "l2.eth",
Usage: "Address of L2 User JSON-RPC endpoint to use (eth namespace required)",
Required: true,
EnvVar: prefixEnvVar("L2_ETH_RPC"),
}
RPCListenAddr = cli.StringFlag{
Name: "rpc.addr",
Usage: "RPC listening address",
......@@ -56,7 +50,14 @@ var (
Usage: "Trust the L1 RPC, sync faster at risk of malicious/buggy RPC providing bad or inconsistent L1 data",
EnvVar: prefixEnvVar("L1_TRUST_RPC"),
}
L2EngineJWTSecret = cli.StringSliceFlag{
Name: "l2.jwt-secret",
Usage: "Paths to JWT secret keys, one per L2 endpoint, in the same order as the provided l2 addresses. " +
"Keys are 32 bytes, hex encoded in a file. A new key per endpoint will be generated if left empty.",
Required: false,
Value: &cli.StringSlice{},
EnvVar: prefixEnvVar("L2_ENGINE_AUTH"),
}
SequencingEnabledFlag = cli.BoolFlag{
Name: "sequencing.enabled",
Usage: "enable sequencing",
......@@ -92,13 +93,13 @@ var requiredFlags = []cli.Flag{
L1NodeAddr,
L2EngineAddrs,
RollupConfig,
L2EthNodeAddr,
RPCListenAddr,
RPCListenPort,
}
var optionalFlags = append([]cli.Flag{
L1TrustRPC,
L2EngineJWTSecret,
SequencingEnabledFlag,
LogLevelFlag,
LogFormatFlag,
......
......@@ -172,7 +172,7 @@ require (
replace github.com/ethereum-optimism/optimism/op-bindings v0.0.0 => ../op-bindings
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602143715-bea96bb3e75d
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f
replace github.com/ethereum-optimism/optimism/op-proposer v0.0.0 => ../op-proposer
......
......@@ -227,8 +227,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602143715-bea96bb3e75d h1:Jc7YIDFx88lmiPrmS2p/mwqbETCJpdm7rj1fagbs6zc=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602143715-bea96bb3e75d/go.mod h1:RD3NhcSBjZpj3k+SnQq24wBrmnmie78P5R/P62iNBD8=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f h1:Ad47wE5WEFzyOaaLff7LTRh79mUgWHKuYe4fpGOG23k=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f/go.mod h1:RD3NhcSBjZpj3k+SnQq24wBrmnmie78P5R/P62iNBD8=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
......
package node
import (
"context"
"errors"
"fmt"
"github.com/ethereum-optimism/optimism/op-node/backoff"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
)
type L2EndpointsSetup interface {
// Setup a RPC client to a L2 execution engine to process rollup blocks with.
Setup(ctx context.Context, log log.Logger) (cl []*rpc.Client, err error)
Check() error
}
type L1EndpointSetup interface {
// Setup a RPC client to a L1 node to pull rollup input-data from.
Setup(ctx context.Context, log log.Logger) (cl *rpc.Client, trust bool, err error)
}
type L2EndpointsConfig struct {
L2EngineAddrs []string // Addresses of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required)
// JWT secrets for L2 Engine API authentication during HTTP or initial Websocket communication, one per L2 engine.
// Any value for an IPC connection.
L2EngineJWTSecrets [][32]byte
}
var _ L2EndpointsSetup = (*L2EndpointsConfig)(nil)
func (cfg *L2EndpointsConfig) Check() error {
if len(cfg.L2EngineAddrs) == 0 {
return errors.New("need at least one L2 engine to connect to")
}
if len(cfg.L2EngineAddrs) != len(cfg.L2EngineJWTSecrets) {
return fmt.Errorf("have %d L2 engines, but %d authentication secrets", len(cfg.L2EngineAddrs), len(cfg.L2EngineJWTSecrets))
}
return nil
}
func (cfg *L2EndpointsConfig) Setup(ctx context.Context, log log.Logger) ([]*rpc.Client, error) {
if err := cfg.Check(); err != nil {
return nil, err
}
var out []*rpc.Client
for i, addr := range cfg.L2EngineAddrs {
auth := rpc.NewJWTAuthProvider(cfg.L2EngineJWTSecrets[i])
l2Node, err := dialRPCClientWithBackoff(ctx, log, addr, auth)
if err != nil {
// close clients again if we cannot complete the full setup
for _, cl := range out {
cl.Close()
}
return out, err
}
out = append(out, l2Node)
}
return out, nil
}
// PreparedL2Endpoints enables testing with in-process pre-setup RPC connections to L2 engines
type PreparedL2Endpoints struct {
Clients []*rpc.Client
}
func (p *PreparedL2Endpoints) Check() error {
if len(p.Clients) == 0 {
return errors.New("need at least one L2 engine to connect to")
}
return nil
}
var _ L2EndpointsSetup = (*PreparedL2Endpoints)(nil)
func (p *PreparedL2Endpoints) Setup(ctx context.Context, log log.Logger) ([]*rpc.Client, error) {
return p.Clients, nil
}
type L1EndpointConfig struct {
L1NodeAddr string // Address of L1 User JSON-RPC endpoint to use (eth namespace required)
// L1TrustRPC: if we trust the L1 RPC we do not have to validate L1 response contents like headers
// against block hashes, or cached transaction sender addresses.
// Thus we can sync faster at the risk of the source RPC being wrong.
L1TrustRPC bool
}
var _ L1EndpointSetup = (*L1EndpointConfig)(nil)
func (cfg *L1EndpointConfig) Setup(ctx context.Context, log log.Logger) (cl *rpc.Client, trust bool, err error) {
l1Node, err := dialRPCClientWithBackoff(ctx, log, cfg.L1NodeAddr, nil)
if err != nil {
return nil, false, fmt.Errorf("failed to dial L1 address (%s): %w", cfg.L1NodeAddr, err)
}
return l1Node, cfg.L1TrustRPC, nil
}
// PreparedL1Endpoint enables testing with an in-process pre-setup RPC connection to L1
type PreparedL1Endpoint struct {
Client *rpc.Client
TrustRPC bool
}
var _ L1EndpointSetup = (*PreparedL1Endpoint)(nil)
func (p *PreparedL1Endpoint) Setup(ctx context.Context, log log.Logger) (cl *rpc.Client, trust bool, err error) {
return p.Client, p.TrustRPC, nil
}
// 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, auth rpc.HeaderAuthProvider) (*rpc.Client, error) {
bOff := backoff.Exponential()
var ret *rpc.Client
err := backoff.Do(10, bOff, func() error {
var client *rpc.Client
var err error
if auth == nil {
client, err = rpc.DialContext(ctx, addr)
} else {
client, err = rpc.DialWithAuth(ctx, addr, auth)
}
if err != nil {
if client == nil {
return fmt.Errorf("failed to dial address (%s): %w", addr, err)
}
log.Warn("failed to dial address, but may connect later", "addr", addr, "err", err)
}
ret = client
return nil
})
if err != nil {
return nil, err
}
return ret, nil
}
......@@ -9,15 +9,8 @@ import (
)
type Config struct {
// L1 and L2 nodes
L1NodeAddr string // Address of L1 User JSON-RPC endpoint to use (eth namespace required)
L2EngineAddrs []string // Addresses of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required)
L2NodeAddr string // Address of L2 User JSON-RPC endpoint to use (eth namespace required)
// L1TrustRPC: if we trust the L1 RPC we do not have to validate L1 response contents like headers
// against block hashes, or cached transaction sender addresses.
// Thus we can sync faster at the risk of the source RPC being wrong.
L1TrustRPC bool
L1 L1EndpointSetup
L2s L2EndpointsSetup
Rollup rollup.Config
......@@ -43,6 +36,9 @@ type RPCConfig struct {
// Check verifies that the given configuration makes sense
func (cfg *Config) Check() error {
if err := cfg.L2s.Check(); err != nil {
return fmt.Errorf("l2 endpoint config error: %v", err)
}
if err := cfg.Rollup.Check(); err != nil {
return fmt.Errorf("rollup config error: %v", err)
}
......
......@@ -2,6 +2,7 @@ package node
import (
"context"
"errors"
"fmt"
"sync"
"time"
......@@ -12,8 +13,6 @@ import (
multierror "github.com/hashicorp/go-multierror"
"github.com/ethereum-optimism/optimism/op-node/backoff"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/l1"
"github.com/ethereum-optimism/optimism/op-node/l2"
......@@ -47,26 +46,6 @@ type OpNode struct {
// The OpNode handles incoming gossip
var _ p2p.GossipIn = (*OpNode)(nil)
func dialRPCClientWithBackoff(ctx context.Context, log log.Logger, addr string) (*rpc.Client, error) {
bOff := backoff.Exponential()
var ret *rpc.Client
err := backoff.Do(10, bOff, func() error {
client, err := rpc.DialContext(ctx, addr)
if err != nil {
if client == nil {
return fmt.Errorf("failed to dial address (%s): %w", addr, err)
}
log.Warn("failed to dial address, but may connect later", "addr", addr, "err", err)
}
ret = client
return nil
})
if err != nil {
return nil, err
}
return ret, nil
}
func New(ctx context.Context, cfg *Config, log log.Logger, snapshotLog log.Logger, appVersion string) (*OpNode, error) {
if err := cfg.Check(); err != nil {
return nil, err
......@@ -97,7 +76,7 @@ func (n *OpNode) init(ctx context.Context, cfg *Config, snapshotLog log.Logger)
if err := n.initL1(ctx, cfg); err != nil {
return err
}
if err := n.initL2(ctx, cfg, snapshotLog); err != nil {
if err := n.initL2s(ctx, cfg, snapshotLog); err != nil {
return err
}
if err := n.initP2PSigner(ctx, cfg); err != nil {
......@@ -123,14 +102,12 @@ func (n *OpNode) initTracer(ctx context.Context, cfg *Config) error {
}
func (n *OpNode) initL1(ctx context.Context, cfg *Config) error {
l1Node, err := dialRPCClientWithBackoff(ctx, n.log, cfg.L1NodeAddr)
l1Node, trustRPC, err := cfg.L1.Setup(ctx, n.log)
if err != nil {
return fmt.Errorf("failed to dial L1 address (%s): %w", cfg.L1NodeAddr, err)
return fmt.Errorf("failed to get L1 RPC client: %w", err)
}
// TODO: we may need to authenticate the connection with L1
// l1Node.SetHeader()
n.l1Source, err = l1.NewSource(l1Node, n.log, l1.DefaultConfig(&cfg.Rollup, cfg.L1TrustRPC))
n.l1Source, err = l1.NewSource(l1Node, n.log, l1.DefaultConfig(&cfg.Rollup, trustRPC))
if err != nil {
return fmt.Errorf("failed to create L1 source: %v", err)
}
......@@ -153,47 +130,44 @@ func (n *OpNode) initL1(ctx context.Context, cfg *Config) error {
}
// AttachEngine attaches an engine to the rollup node.
func (n *OpNode) AttachEngine(ctx context.Context, cfg *Config, addr string, snapshotLog log.Logger) error {
func (n *OpNode) AttachEngine(ctx context.Context, cfg *Config, tag string, cl *rpc.Client, snapshotLog log.Logger) error {
n.l2Lock.Lock()
defer n.l2Lock.Unlock()
l2Node, err := dialRPCClientWithBackoff(ctx, n.log, addr)
if err != nil {
return err
}
engLog := n.log.New("engine", tag)
engLog := n.log.New("engine", addr)
// TODO: we may need to authenticate the connection with L2
// backend.SetHeader()
client, err := l2.NewSource(l2Node, &cfg.Rollup.Genesis, engLog)
client, err := l2.NewSource(cl, &cfg.Rollup.Genesis, engLog)
if err != nil {
l2Node.Close()
cl.Close()
return err
}
snap := snapshotLog.New("engine_addr", addr)
snap := snapshotLog.New("engine_addr", tag)
engine := driver.NewDriver(cfg.Rollup, client, n.l1Source, n, engLog, snap, cfg.Sequencer)
n.l2Nodes = append(n.l2Nodes, l2Node)
n.l2Nodes = append(n.l2Nodes, cl)
n.l2Engines = append(n.l2Engines, engine)
return nil
}
func (n *OpNode) initL2(ctx context.Context, cfg *Config, snapshotLog log.Logger) error {
for i, addr := range cfg.L2EngineAddrs {
if err := n.AttachEngine(ctx, cfg, addr, snapshotLog); err != nil {
return fmt.Errorf("failed to attach configured engine %d (%s): %v", i, addr, err)
func (n *OpNode) initL2s(ctx context.Context, cfg *Config, snapshotLog log.Logger) error {
clients, err := cfg.L2s.Setup(ctx, n.log)
if err != nil {
return fmt.Errorf("failed to setup L2 execution-engine RPC client(s): %v", err)
}
for i, cl := range clients {
if err := n.AttachEngine(ctx, cfg, fmt.Sprintf("eng_%d", i), cl, snapshotLog); err != nil {
return fmt.Errorf("failed to attach configured engine %d: %v", i, err)
}
}
return nil
}
func (n *OpNode) initRPCServer(ctx context.Context, cfg *Config) error {
l2Node, err := dialRPCClientWithBackoff(ctx, n.log, cfg.L2NodeAddr)
if err != nil {
return fmt.Errorf("failed to dial l2 address (%s): %w", cfg.L2NodeAddr, err)
if len(n.l2Nodes) == 0 {
return errors.New("need at least one L2 node to serve rollup RPC")
}
l2Node := n.l2Nodes[0]
// TODO: attach the p2p node ID to the snapshot logger
client, err := l2.NewReadOnlySource(l2Node, &cfg.Rollup.Genesis, n.log)
......
......@@ -90,7 +90,7 @@ func TestOutputAtBlock(t *testing.T) {
assert.NoError(t, server.Start())
defer server.Stop()
client, err := dialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String())
client, err := dialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String(), nil)
assert.NoError(t, err)
var out []l2.Bytes32
......@@ -115,7 +115,7 @@ func TestVersion(t *testing.T) {
assert.NoError(t, server.Start())
defer server.Stop()
client, err := dialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String())
client, err := dialRPCClientWithBackoff(context.Background(), log, "http://"+server.Addr().String(), nil)
assert.NoError(t, err)
var out string
......
......@@ -198,7 +198,7 @@ func L1InfoDeposit(seqNumber uint64, block L1Info) (*types.DepositTx, error) {
To: &L1InfoPredeployAddr,
Mint: nil,
Value: big.NewInt(0),
Gas: 75_000,
Gas: 150_000, // TODO: temporary work around. Block 1 seems to require more gas than specced.
Data: data,
}, nil
}
......
package opnode
import (
"crypto/rand"
"encoding/json"
"fmt"
"io"
"os"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log"
......@@ -15,7 +21,7 @@ import (
)
// NewConfig creates a Config from the provided flags or environment variables.
func NewConfig(ctx *cli.Context) (*node.Config, error) {
func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) {
rollupConfig, err := NewRollupConfig(ctx)
if err != nil {
return nil, err
......@@ -33,13 +39,21 @@ func NewConfig(ctx *cli.Context) (*node.Config, error) {
return nil, fmt.Errorf("failed to load p2p config: %v", err)
}
l1Endpoint, err := NewL1EndpointConfig(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load l1 endpoint info: %v", err)
}
l2Endpoints, err := NewL2EndpointsConfig(ctx, log)
if err != nil {
return nil, fmt.Errorf("failed to load l2 endpoints info: %v", err)
}
cfg := &node.Config{
L1NodeAddr: ctx.GlobalString(flags.L1NodeAddr.Name),
L2EngineAddrs: ctx.GlobalStringSlice(flags.L2EngineAddrs.Name),
L2NodeAddr: ctx.GlobalString(flags.L2EthNodeAddr.Name),
L1TrustRPC: ctx.GlobalBool(flags.L1TrustRPC.Name),
Rollup: *rollupConfig,
Sequencer: enableSequencing,
L1: l1Endpoint,
L2s: l2Endpoints,
Rollup: *rollupConfig,
Sequencer: enableSequencing,
RPC: node.RPCConfig{
ListenAddr: ctx.GlobalString(flags.RPCListenAddr.Name),
ListenPort: ctx.GlobalInt(flags.RPCListenPort.Name),
......@@ -53,6 +67,48 @@ func NewConfig(ctx *cli.Context) (*node.Config, error) {
return cfg, nil
}
func NewL1EndpointConfig(ctx *cli.Context) (*node.L1EndpointConfig, error) {
return &node.L1EndpointConfig{
L1NodeAddr: ctx.GlobalString(flags.L1NodeAddr.Name),
L1TrustRPC: ctx.GlobalBool(flags.L1TrustRPC.Name),
}, nil
}
func NewL2EndpointsConfig(ctx *cli.Context, log log.Logger) (*node.L2EndpointsConfig, error) {
l2Addrs := ctx.GlobalStringSlice(flags.L2EngineAddrs.Name)
engineJWTSecrets := ctx.GlobalStringSlice(flags.L2EngineJWTSecret.Name)
var secrets [][32]byte
for i, fileName := range engineJWTSecrets {
fileName = strings.TrimSpace(fileName)
if fileName == "" {
return nil, fmt.Errorf("file-name of jwt secret %d is empty", i)
}
if data, err := os.ReadFile(fileName); err == nil {
jwtSecret := common.FromHex(strings.TrimSpace(string(data)))
if len(jwtSecret) != 32 {
return nil, fmt.Errorf("invalid jwt secret in path %s, not 32 hex-formatted bytes", fileName)
}
var secret [32]byte
copy(secret[:], jwtSecret)
secrets = append(secrets, secret)
} else {
log.Warn("Failed to read JWT secret from file, generating a new one now. Configure L2 geth with --authrpc.jwt-secret=" + fmt.Sprintf("%q", fileName))
var secret [32]byte
if _, err := io.ReadFull(rand.Reader, secret[:]); err != nil {
return nil, fmt.Errorf("failed to generate jwt secret: %v", err)
}
secrets = append(secrets, secret)
if err := os.WriteFile(fileName, []byte(hexutil.Encode(secret[:])), 0600); err != nil {
return nil, err
}
}
}
return &node.L2EndpointsConfig{
L2EngineAddrs: l2Addrs,
L2EngineJWTSecrets: secrets,
}, nil
}
func NewRollupConfig(ctx *cli.Context) (*rollup.Config, error) {
rollupConfigPath := ctx.GlobalString(flags.RollupConfig.Name)
file, err := os.Open(rollupConfigPath)
......
......@@ -41,7 +41,7 @@ func WaitForFinalizationPeriod(ctx context.Context, client *ethclient.Client, po
return 0, err
}
finalizationPeriod, err := portal.FINALIZATIONPERIOD(opts)
finalizationPeriod, err := portal.FINALIZATIONPERIODSECONDS(opts)
if err != nil {
return 0, err
}
......
......@@ -158,4 +158,4 @@ replace github.com/ethereum-optimism/optimism/op-node v0.0.0 => ../op-node
replace github.com/ethereum-optimism/optimism/op-bindings v0.0.0 => ../op-bindings
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602143715-bea96bb3e75d
replace github.com/ethereum/go-ethereum v1.10.17 => github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f
......@@ -243,8 +243,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602143715-bea96bb3e75d h1:Jc7YIDFx88lmiPrmS2p/mwqbETCJpdm7rj1fagbs6zc=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602143715-bea96bb3e75d/go.mod h1:RD3NhcSBjZpj3k+SnQq24wBrmnmie78P5R/P62iNBD8=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f h1:Ad47wE5WEFzyOaaLff7LTRh79mUgWHKuYe4fpGOG23k=
github.com/ethereum-optimism/reference-optimistic-geth v0.0.0-20220602230953-dd2e24b3359f/go.mod h1:RD3NhcSBjZpj3k+SnQq24wBrmnmie78P5R/P62iNBD8=
github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY=
......
......@@ -30,6 +30,11 @@ services:
volumes:
- "l2_data:/db"
- ${PWD}/../.devnet/genesis-l2.json:/genesis.json
- ${PWD}/test-jwt-secret.txt:/config/test-jwt-secret.txt
entrypoint: # pass the L2 specific flags by overriding the entry-point and adding extra arguments
- "/bin/sh"
- "/entrypoint.sh"
- "--authrpc.jwtsecret=/config/test-jwt-secret.txt"
op-node:
depends_on:
......@@ -42,10 +47,10 @@ services:
op-node
--l1=ws://l1:8546
--l2=ws://l2:8546
--l2.jwt-secret=/config/test-jwt-secret.txt
--sequencing.enabled
--p2p.sequencer.key=/config/p2p-sequencer-key.txt
--rollup.config=/rollup.json
--l2.eth=http://l2:8545
--rpc.addr=0.0.0.0
--rpc.port=8545
--p2p.listen.ip=0.0.0.0
......@@ -59,6 +64,7 @@ services:
volumes:
- ${PWD}/p2p-sequencer-key.txt:/config/p2p-sequencer-key.txt
- ${PWD}/p2p-node-key.txt:/config/p2p-node-key.txt
- ${PWD}/test-jwt-secret.txt:/config/test-jwt-secret.txt
- ${PWD}/../.devnet/rollup.json:/rollup.json
- op_log:/op_log
......
688f5d737bad920bdfb2fc2f488d6b6209eebda1dae949a8de91398d932c517a
......@@ -26,17 +26,17 @@ L1BlockNumberTest:test_receive() (gas: 17418)
L1CrossDomainMessenger_Test:testCannot_L1MessengerPause() (gas: 10909)
L1CrossDomainMessenger_Test:test_L1MessengerMessageVersion() (gas: 8366)
L1CrossDomainMessenger_Test:test_L1MessengerPause() (gas: 31882)
L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 61129)
L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageToSystemContract() (gas: 44815)
L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 61175)
L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageToSystemContract() (gas: 44859)
L1CrossDomainMessenger_Test:test_L1MessengerRelayShouldRevertIfPaused() (gas: 41631)
L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 78105)
L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 66345)
L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 172148)
L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 1254131)
L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 10566)
L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 58425)
L1StandardBridge_Test:test_depositERC20() (gas: 371479)
L1StandardBridge_Test:test_depositERC20To() (gas: 373256)
L1StandardBridge_Test:test_depositETH() (gas: 105061)
L1StandardBridge_Test:test_depositETHTo() (gas: 111945)
L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 58471)
L1StandardBridge_Test:test_depositERC20() (gas: 452873)
L1StandardBridge_Test:test_depositERC20To() (gas: 454650)
L1StandardBridge_Test:test_depositETH() (gas: 247054)
L1StandardBridge_Test:test_depositETHTo() (gas: 204938)
L1StandardBridge_Test:test_donateETH() (gas: 17545)
L1StandardBridge_Test:test_finalizeERC20Withdrawal() (gas: 438817)
L1StandardBridge_Test:test_finalizeETHWithdrawal() (gas: 48005)
......@@ -45,7 +45,7 @@ L1StandardBridge_Test:test_onlyEOADepositERC20() (gas: 12085)
L1StandardBridge_Test:test_onlyEOADepositETH() (gas: 30637)
L1StandardBridge_Test:test_onlyL2BridgeFinalizeERC20Withdrawal() (gas: 23565)
L1StandardBridge_Test:test_onlyPortalFinalizeERC20Withdrawal() (gas: 22919)
L1StandardBridge_Test:test_receive() (gas: 99476)
L1StandardBridge_Test:test_receive() (gas: 391794)
L2CrossDomainMessenger_Test:testCannot_L2MessengerPause() (gas: 10843)
L2CrossDomainMessenger_Test:test_L2MessengerMessageVersion() (gas: 8410)
L2CrossDomainMessenger_Test:test_L2MessengerPause() (gas: 31837)
......@@ -76,7 +76,7 @@ L2StandardBridge_Test:test_initialize() (gas: 14834)
L2StandardBridge_Test:test_receive() (gas: 136437)
L2StandardBridge_Test:test_withdraw() (gas: 352644)
L2StandardBridge_Test:test_withdrawTo() (gas: 353495)
L2ToL1MessagePasserTest:test_burn() (gas: 112023)
L2ToL1MessagePasserTest:test_burn() (gas: 112046)
L2ToL1MessagePasserTest:test_initiateWithdrawal_fromContract() (gas: 67890)
L2ToL1MessagePasserTest:test_initiateWithdrawal_fromEOA() (gas: 74851)
OVM_ETH_Test:test_approve() (gas: 10695)
......@@ -101,19 +101,27 @@ OptimismMintableTokenFactory_Test:test_createStandardL2Token() (gas: 1106538)
OptimismMintableTokenFactory_Test:test_createStandardL2TokenSameTwice() (gas: 2193987)
OptimismMintableTokenFactory_Test:test_createStandardL2TokenShouldRevertIfRemoteIsZero() (gas: 9374)
OptimismMintableTokenFactory_Test:test_initializeShouldRevert() (gas: 12696)
OptimismPortal_Test:test_OptimismPortalConstructor() (gas: 11302)
OptimismPortal_Test:test_OptimismPortalContractCreationReverts() (gas: 9421)
OptimismPortal_Test:test_OptimismPortalReceiveEth() (gas: 24732)
OptimismPortal_Test:test_cannotVerifyRecentWithdrawal() (gas: 19657)
OptimismPortal_Test:test_depositTransaction_NoValueContract() (gas: 24478)
OptimismPortal_Test:test_depositTransaction_NoValueEOA() (gas: 24846)
OptimismPortal_Test:test_depositTransaction_createWithZeroValueForContract() (gas: 24497)
OptimismPortal_Test:test_depositTransaction_createWithZeroValueForEOA() (gas: 24841)
OptimismPortal_Test:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 31519)
OptimismPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 22971)
OptimismPortal_Test:test_depositTransaction_withEthValueFromContract() (gas: 31210)
OptimismPortal_Test:test_depositTransaction_withEthValueFromEOA() (gas: 31781)
OptimismPortal_Test:test_invalidWithdrawalProof() (gas: 26565)
OptimismPortal_Test:test_OptimismPortalConstructor() (gas: 11413)
OptimismPortal_Test:test_OptimismPortalContractCreationReverts() (gas: 9214)
OptimismPortal_Test:test_OptimismPortalReceiveEth() (gas: 121706)
OptimismPortal_Test:test_cannotVerifyRecentWithdrawal() (gas: 21863)
OptimismPortal_Test:test_depositTransaction_NoValueContract() (gas: 70746)
OptimismPortal_Test:test_depositTransaction_NoValueEOA() (gas: 71114)
OptimismPortal_Test:test_depositTransaction_createWithZeroValueForContract() (gas: 70773)
OptimismPortal_Test:test_depositTransaction_createWithZeroValueForEOA() (gas: 71117)
OptimismPortal_Test:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 77795)
OptimismPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 69947)
OptimismPortal_Test:test_depositTransaction_withEthValueFromContract() (gas: 77478)
OptimismPortal_Test:test_depositTransaction_withEthValueFromEOA() (gas: 78049)
OptimismPortal_Test:test_invalidWithdrawalProof() (gas: 28541)
ResourceMetering_Test:test_initialResourceParams() (gas: 8986)
ResourceMetering_Test:test_updateNoGasDelta() (gas: 2008269)
ResourceMetering_Test:test_updateOneEmptyBlock() (gas: 18078)
ResourceMetering_Test:test_updateParamsNoChange() (gas: 13860)
ResourceMetering_Test:test_updateTenEmptyBlocks() (gas: 20545)
ResourceMetering_Test:test_updateTwoEmptyBlocks() (gas: 20546)
ResourceMetering_Test:test_useMaxSucceeds() (gas: 8017045)
ResourceMetering_Test:test_useMoreThanMaxReverts() (gas: 16024)
SequencerFeeVault_Test:test_constructor() (gas: 7611)
SequencerFeeVault_Test:test_minWithdrawalAmount() (gas: 5429)
SequencerFeeVault_Test:test_receive() (gas: 17280)
......
# @eth-optimism/contracts-bedrock
## 0.1.1
### Patch Changes
- 1aca58c4: Initial release
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
import { SignedMath } from "@openzeppelin/contracts/utils/math/SignedMath.sol";
import { FixedPointMathLib } from "@rari-capital/solmate/src/utils/FixedPointMathLib.sol";
import { Burn } from "../libraries/Burn.sol";
/**
* @title ResourceMetering
* @notice ResourceMetering implements an EIP-1559 style resource metering system where pricing
* updates automatically based on current demand.
*/
contract ResourceMetering {
/**
* Struct representing current resource parameters.
*/
struct ResourceParams {
uint128 prevBaseFee;
uint64 prevBoughtGas;
uint64 prevBlockNum;
}
/**
* Along with the resource limit, determines the target resource limit.
*/
int256 public constant ELASTICITY_MULTIPLIER = 4;
/**
* Denominator that determines max change on fee per block.
*/
int256 public constant BASE_FEE_MAX_CHANGE_DENOMINATOR = 8;
/**
* Maximum amount of deposit gas that can be used within this block.
*/
int256 public constant MAX_RESOURCE_LIMIT = 8_000_000;
/**
* Target amount of deposit gas that should be used within this block.
*/
int256 public constant TARGET_RESOURCE_LIMIT = MAX_RESOURCE_LIMIT / ELASTICITY_MULTIPLIER;
/**
* Minimum base fee value, cannot go lower than this.
*/
int256 public constant MINIMUM_BASE_FEE = 10_000;
/**
* Initial base fee value.
*/
uint128 public constant INITIAL_BASE_FEE = 1_000_000_000;
/**
* EIP-1559 style gas parameters.
*/
ResourceParams public params;
/**
* Sets the initial resource values.
*/
constructor() {
params = ResourceParams({
prevBaseFee: INITIAL_BASE_FEE,
prevBoughtGas: 0,
prevBlockNum: uint64(block.number)
});
}
/**
* Meters access to a function based an amount of a requested resource.
*
* @param _amount Amount of the resource requested.
*/
modifier metered(uint64 _amount) {
// Record initial gas amount so we can refund for it later.
uint256 initialGas = gasleft();
// Run the underlying function.
_;
// Update block number and base fee if necessary.
uint256 blockDiff = block.number - params.prevBlockNum;
if (blockDiff > 0) {
// Handle updating EIP-1559 style gas parameters. We use EIP-1559 to restrict the rate
// at which deposits can be created and therefore limit the potential for deposits to
// spam the L2 system. Fee scheme is very similar to EIP-1559 with minor changes.
int256 gasUsedDelta = int256(uint256(params.prevBoughtGas)) - TARGET_RESOURCE_LIMIT;
int256 baseFeeDelta = (int256(uint256(params.prevBaseFee)) * gasUsedDelta) /
TARGET_RESOURCE_LIMIT /
BASE_FEE_MAX_CHANGE_DENOMINATOR;
// Update base fee by adding the base fee delta and clamp the resulting value between
// min and max.
int256 newBaseFee = SignedMath.min(
SignedMath.max(
int256(uint256(params.prevBaseFee)) + baseFeeDelta,
int256(MINIMUM_BASE_FEE)
),
int256(uint256(type(uint128).max))
);
// If we skipped more than one block, we also need to account for every empty block.
// Empty block means there was no demand for deposits in that block, so we should
// reflect this lack of demand in the fee.
if (blockDiff > 1) {
// Update the base fee by repeatedly applying the exponent 1-(1/change_denominator)
// blockDiff - 1 times. Simulates multiple empty blocks. Clamp the resulting value
// between min and max.
newBaseFee = SignedMath.min(
SignedMath.max(
int256(
(newBaseFee *
(
FixedPointMathLib.powWad(
1e18 - (1e18 / BASE_FEE_MAX_CHANGE_DENOMINATOR),
int256((blockDiff - 1) * 1e18)
)
)) / 1e18
),
int256(MINIMUM_BASE_FEE)
),
int256(uint256(type(uint128).max))
);
}
// Update new base fee, reset bought gas, and update block number.
params.prevBaseFee = uint128(uint256(newBaseFee));
params.prevBoughtGas = 0;
params.prevBlockNum = uint64(block.number);
}
// Make sure we can actually buy the resource amount requested by the user.
params.prevBoughtGas += _amount;
require(
int256(uint256(params.prevBoughtGas)) <= MAX_RESOURCE_LIMIT,
"OptimismPortal: cannot buy more gas than available gas limit"
);
// Determine the amount of ETH to be paid.
uint256 resourceCost = _amount * params.prevBaseFee;
// We currently charge for this ETH amount as an L1 gas burn, so we convert the ETH amount
// into gas by dividing by the L1 base fee. We assume a minimum base fee of 1 gwei to avoid
// division by zero for L1s that don't support 1559 or to avoid excessive gas burns during
// periods of extremely low L1 demand. One-day average gas fee hasn't dipped below 1 gwei
// during any 1 day period in the last 5 years, so should be fine.
uint256 gasCost = resourceCost / Math.max(block.basefee, 1000000000);
// Give the user a refund based on the amount of gas they used to do all of the work up to
// this point. Since we're at the end of the modifier, this should be pretty accurate. Acts
// effectively like a dynamic stipend (with a minimum value).
uint256 usedGas = initialGas - gasleft();
if (gasCost > usedGas) {
Burn.gas(gasCost - usedGas);
}
}
}
//SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
/**
* @title Burner
* @dev This contract is used to remove ETH from
* the L2 circulating supply as it is withdrawn.
*/
contract Burner {
constructor() payable {
selfdestruct(payable(address(this)));
}
}
......@@ -2,7 +2,7 @@
pragma solidity ^0.8.9;
import { WithdrawalVerifier } from "../libraries/Lib_WithdrawalVerifier.sol";
import { Burner } from "./Burner.sol";
import { Burn } from "../libraries/Burn.sol";
/**
* @title L2ToL1MessagePasser
......@@ -101,7 +101,7 @@ contract L2ToL1MessagePasser {
*/
function burn() external {
uint256 balance = address(this).balance;
new Burner{ value: balance }();
Burn.eth(balance);
emit WithdrawerBalanceBurnt(balance);
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
/**
* @title Burner
* @notice Burner self-destructs on creation and sends all ETH to itself, removing all ETH given to
* the contract from the circulating supply.
*/
contract Burner {
constructor() payable {
selfdestruct(payable(address(this)));
}
}
/**
* @title Burn
* @notice Utilities for burning stuff.
*/
library Burn {
/**
* Burns a given amount of ETH.
*
* @param _amount Amount of ETH to burn.
*/
function eth(uint256 _amount) internal {
new Burner{ value: _amount }();
}
/**
* Burns a given amount of gas.
*
* @param _amount Amount of gas to burn.
*/
function gas(uint256 _amount) internal {
uint256 i = 0;
uint256 initialGas = gasleft();
while (initialGas - gasleft() < _amount) {
++i;
}
}
}
......@@ -37,6 +37,9 @@ contract CommonTest is Test {
vm.label(alice, "alice");
vm.label(bob, "bob");
// Make sure we have a non-zero base fee
vm.fee(1000000000);
}
}
contract L2OutputOracle_Initializer is CommonTest {
......
......@@ -136,7 +136,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
vm.expectCall(target, hex"1111");
// set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
vm.store(address(op), 0, bytes32(abi.encode(sender)));
uint256 senderSlotIndex = 1;
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.prank(address(op));
vm.expectEmit(true, true, true, true);
......@@ -190,7 +191,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
L1Messenger.xDomainMessageSender();
address sender = Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER;
vm.store(address(op), 0, bytes32(abi.encode(sender)));
uint256 senderSlotIndex = 1;
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.prank(address(op));
L1Messenger.relayMessage(0, address(0), address(0), 0, 0, hex"");
......
......@@ -24,6 +24,7 @@ contract OptimismPortal_Test is CommonTest {
OptimismPortal op;
function setUp() external {
_setUp();
oracle = new L2OutputOracle(
1800,
2,
......@@ -36,7 +37,7 @@ contract OptimismPortal_Test is CommonTest {
}
function test_OptimismPortalConstructor() external {
assertEq(op.FINALIZATION_PERIOD(), 7 days);
assertEq(op.FINALIZATION_PERIOD_SECONDS(), 7 days);
assertEq(address(op.L2_ORACLE()), address(oracle));
assertEq(op.l2Sender(), 0x000000000000000000000000000000000000dEaD);
}
......@@ -67,7 +68,7 @@ contract OptimismPortal_Test is CommonTest {
// Test: depositTransaction fails when contract creation has a non-zero destination address
function test_OptimismPortalContractCreationReverts() external {
// contract creation must have a target of address(0)
vm.expectRevert(abi.encodeWithSignature("NonZeroCreationTarget()"));
vm.expectRevert("OptimismPortal: must send to address(0) when creating a contract");
op.depositTransaction(address(1), 1, 0, true, hex"");
}
......@@ -260,7 +261,7 @@ contract OptimismPortal_Test is CommonTest {
latestBlockhash: bytes32(0)
});
vm.expectRevert("Proposal is not yet finalized.");
vm.expectRevert("OptimismPortal: proposal is not yet finalized");
op.finalizeWithdrawalTransaction(
0,
alice,
......@@ -282,8 +283,8 @@ contract OptimismPortal_Test is CommonTest {
latestBlockhash: bytes32(0)
});
vm.warp(oracle.nextTimestamp() + op.FINALIZATION_PERIOD());
vm.expectRevert(abi.encodeWithSignature("InvalidOutputRootProof()"));
vm.warp(oracle.nextTimestamp() + op.FINALIZATION_PERIOD_SECONDS());
vm.expectRevert("OptimismPortal: invalid output root proof");
op.finalizeWithdrawalTransaction(
0,
alice,
......
//SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import { CommonTest } from "./CommonTest.t.sol";
import { ResourceMetering } from "../L1/ResourceMetering.sol";
contract MeterUser is ResourceMetering {
function use(uint64 _amount) public metered(_amount) {}
}
contract ResourceMetering_Test is CommonTest {
MeterUser internal meter;
uint64 initialBlockNum;
function setUp() external {
_setUp();
meter = new MeterUser();
initialBlockNum = uint64(block.number);
}
function test_initialResourceParams() external {
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();
assertEq(prevBaseFee, meter.INITIAL_BASE_FEE());
assertEq(prevBoughtGas, 0);
assertEq(prevBlockNum, initialBlockNum);
}
function test_updateParamsNoChange() external {
meter.use(0); // equivalent to just updating the base fee and block number
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();
meter.use(0);
(uint128 postBaseFee, uint64 postBoughtGas, uint64 postBlockNum) = meter.params();
assertEq(postBaseFee, prevBaseFee);
assertEq(postBoughtGas, prevBoughtGas);
assertEq(postBlockNum, prevBlockNum);
}
function test_updateOneEmptyBlock() external {
vm.roll(initialBlockNum + 1);
meter.use(0);
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();
// Base fee decreases by 12.5%
assertEq(prevBaseFee, 875000000);
assertEq(prevBoughtGas, 0);
assertEq(prevBlockNum, initialBlockNum + 1);
}
function test_updateTwoEmptyBlocks() external {
vm.roll(initialBlockNum + 2);
meter.use(0);
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();
assertEq(prevBaseFee, 765624999);
assertEq(prevBoughtGas, 0);
assertEq(prevBlockNum, initialBlockNum + 2);
}
function test_updateTenEmptyBlocks() external {
vm.roll(initialBlockNum + 10);
meter.use(0);
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();
assertEq(prevBaseFee, 263075576);
assertEq(prevBoughtGas, 0);
assertEq(prevBlockNum, initialBlockNum + 10);
}
function test_updateNoGasDelta() external {
uint64 target = uint64(uint256(meter.TARGET_RESOURCE_LIMIT()));
meter.use(target);
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();
assertEq(prevBaseFee, 1000000000);
assertEq(prevBoughtGas, target);
assertEq(prevBlockNum, initialBlockNum);
}
function test_useMaxSucceeds() external {
uint64 target = uint64(uint256(meter.TARGET_RESOURCE_LIMIT()));
uint64 elasticity = uint64(uint256(meter.ELASTICITY_MULTIPLIER()));
meter.use(target * elasticity);
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();
assertEq(prevBoughtGas, target * elasticity);
vm.roll(initialBlockNum + 1);
meter.use(0);
(uint128 postBaseFee, uint64 postBoughtGas, uint64 postBlockNum) = meter.params();
// Base fee increases by 1/8 the difference
assertEq(postBaseFee, 1375000000);
}
function test_useMoreThanMaxReverts() external {
uint64 target = uint64(uint256(meter.TARGET_RESOURCE_LIMIT()));
uint64 elasticity = uint64(uint256(meter.ELASTICITY_MULTIPLIER()));
vm.expectRevert("OptimismPortal: cannot buy more gas than available gas limit");
meter.use(target * elasticity + 1);
}
}
......@@ -12,17 +12,6 @@
"artifacts/src/**/*.json",
"deployments/**/*.json"
],
"dependencies": {
"@openzeppelin/contracts": "^4.5.0",
"@openzeppelin/contracts-upgradeable": "^4.5.2",
"ethers": "^5.6.8",
"hardhat": "^2.9.6",
"@rari-capital/solmate": "7.0.0-alpha.1",
"ds-test": "https://github.com/dapphub/ds-test.git#9310e879db8ba3ea6d5c6489a579118fd264a3f5",
"forge-std": "https://github.com/foundry-rs/forge-std.git#1680d7fb3e00b7b197a7336e7c88e838c7e6a3ec",
"merkle-patricia-tree": "^4.2.4",
"rlp": "^2.2.7"
},
"scripts": {
"build:forge": "forge build",
"build": "hardhat compile && tsc && hardhat typechain",
......@@ -34,13 +23,24 @@
"lint:ts:check": "eslint .",
"lint:contracts:check": "yarn solhint -f table 'contracts/**/*.sol'",
"lint:check": "yarn lint:contracts:check && yarn lint:ts:check",
"lint:ts:fix": "prettier --write .",
"lint:contracts:fix": "prettier --write 'contracts/**/*.sol'",
"lint:ts:fix": "yarn prettier --write .",
"lint:contracts:fix": "yarn prettier --write 'contracts/**/*.sol'",
"lint:fix": "yarn lint:contracts:fix && yarn lint:ts:fix",
"lint": "yarn lint:fix && yarn lint:check"
},
"devDependencies": {
"dependencies": {
"@eth-optimism/core-utils": "^0.8.6",
"@openzeppelin/contracts": "^4.5.0",
"@openzeppelin/contracts-upgradeable": "^4.5.2",
"ethers": "^5.6.8",
"hardhat": "^2.9.6",
"@rari-capital/solmate": "https://github.com/rari-capital/solmate.git#8f9b23f8838670afda0fd8983f2c41e8037ae6bc",
"ds-test": "https://github.com/dapphub/ds-test.git#9310e879db8ba3ea6d5c6489a579118fd264a3f5",
"forge-std": "https://github.com/foundry-rs/forge-std.git#1680d7fb3e00b7b197a7336e7c88e838c7e6a3ec",
"merkle-patricia-tree": "^4.2.4",
"rlp": "^2.2.7"
},
"devDependencies": {
"@foundry-rs/hardhat-forge": "^0.1.5",
"@nomiclabs/hardhat-ethers": "^2.0.0",
"@nomiclabs/hardhat-etherscan": "^2.1.3",
......
......@@ -5,7 +5,5 @@
"outDir": "./dist"
},
"exclude": ["hardhat.config.ts", "deploy", "tasks", "test"],
"include": [
"src/**/*"
]
"include": ["src/**/*"]
}
import { DeployConfig } from '../../src'
const config: DeployConfig = {
retroReceiverOwner: '0xc37f6a6c4AB335E20d10F034B90386E2fb70bbF5',
drippieOwner: '0xc37f6a6c4AB335E20d10F034B90386E2fb70bbF5',
}
export default config
import { DeployConfig } from '../../src'
const config: DeployConfig = {
retroReceiverOwner: '0xc37f6a6c4AB335E20d10F034B90386E2fb70bbF5',
drippieOwner: '0xc37f6a6c4AB335E20d10F034B90386E2fb70bbF5',
}
export default config
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import { ERC20 } from "@rari-capital/solmate/src/tokens/ERC20.sol";
import { ERC721 } from "@rari-capital/solmate/src/tokens/ERC721.sol";
import { Transactor } from "./Transactor.sol";
/**
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Owned } from "@rari-capital/solmate/src/auth/Owned.sol";
/**
* @title Transactor
* @notice Transactor is a minimal contract that can send transactions.
*/
contract Transactor is Ownable {
contract Transactor is Owned {
/**
* @param _owner Initial contract owner.
*/
constructor(address _owner) Ownable() {
transferOwnership(_owner);
}
constructor(address _owner) Owned(_owner) {}
/**
* Sends a CALL to a target address.
......
......@@ -80,7 +80,7 @@ describe('AssetReceiver', () => {
AssetReceiver.connect(signer2)['withdrawETH(address)'](
signer2.address
)
).to.be.revertedWith('Ownable: caller is not the owner')
).to.be.revertedWith('UNAUTHORIZED')
})
})
})
......@@ -119,7 +119,7 @@ describe('AssetReceiver', () => {
DEFAULT_RECIPIENT,
DEFAULT_AMOUNT
)
).to.be.revertedWith('Ownable: caller is not the owner')
).to.be.revertedWith('UNAUTHORIZED')
})
})
})
......@@ -156,7 +156,7 @@ describe('AssetReceiver', () => {
TestERC20.address,
DEFAULT_RECIPIENT
)
).to.be.revertedWith('Ownable: caller is not the owner')
).to.be.revertedWith('UNAUTHORIZED')
})
})
})
......@@ -193,7 +193,7 @@ describe('AssetReceiver', () => {
AssetReceiver.connect(signer2)[
'withdrawERC20(address,address,uint256)'
](TestERC20.address, DEFAULT_RECIPIENT, DEFAULT_AMOUNT)
).to.be.revertedWith('Ownable: caller is not the owner')
).to.be.revertedWith('UNAUTHORIZED')
})
})
})
......@@ -236,7 +236,7 @@ describe('AssetReceiver', () => {
DEFAULT_RECIPIENT,
DEFAULT_TOKEN_ID
)
).to.be.revertedWith('Ownable: caller is not the owner')
).to.be.revertedWith('UNAUTHORIZED')
})
})
})
......
......@@ -74,7 +74,7 @@ describe('AssetReceiver', () => {
gasLimit: 2_000_000,
}
)
).to.be.revertedWith('Ownable: caller is not the owner')
).to.be.revertedWith('UNAUTHORIZED')
})
})
})
......@@ -109,7 +109,7 @@ describe('AssetReceiver', () => {
gasLimit: 2_000_000,
}
)
).to.be.revertedWith('Ownable: caller is not the owner')
).to.be.revertedWith('UNAUTHORIZED')
})
})
})
......
......@@ -96,7 +96,7 @@ describe('Drippie', () => {
DEFAULT_DRIP_NAME,
DEFAULT_DRIP_CONFIG
)
).to.be.revertedWith('Ownable: caller is not the owner')
).to.be.revertedWith('UNAUTHORIZED')
})
})
})
......@@ -182,7 +182,7 @@ describe('Drippie', () => {
it('should revert', async () => {
await expect(
Drippie.connect(signer2).status(DEFAULT_DRIP_NAME, 1)
).to.be.revertedWith('Ownable: caller is not the owner')
).to.be.revertedWith('UNAUTHORIZED')
})
})
})
......
artifacts
cache
\ No newline at end of file
cache
forge-artifacts
[default]
src = 'contracts'
out = 'forge-artifacts'
optimizer = true
optimizer_runs = 999999
extra_output = ['devdoc', 'userdoc', 'metadata', 'storageLayout']
bytecode_hash = "none"
......@@ -2,16 +2,16 @@
"private": true,
"name": "@eth-optimism/integration-tests-bedrock",
"version": "0.5.10",
"description": "[Optimism] Integration tests",
"description": "[Optimism] Bedrock Integration tests",
"scripts": {
"lint": "yarn lint:fix && yarn lint:check",
"lint:fix": "yarn lint:check --fix",
"lint:check": "eslint . --max-warnings=0",
"build:contracts": "forge build --root . -c contracts -o artifacts",
"build:contracts": "forge build",
"test": "echo 'no unit tests'",
"test:actor": "IS_LIVE_NETWORK=true ts-node actor-tests/lib/runner.ts",
"test:integration:live": "NO_NETWORK=true IS_LIVE_NETWORK=true hardhat --network optimism test",
"clean": "rimraf cache artifacts"
"clean": "rimraf cache artifacts foundry-artifacts"
},
"keywords": [
"optimism",
......@@ -19,7 +19,7 @@
"integration",
"tests"
],
"homepage": "https://github.com/ethereum-optimism/optimism/tree/develop/packages/integration-tests#readme",
"homepage": "https://github.com/ethereum-optimism/optimism/tree/develop/packages/integration-tests-bedrock#readme",
"license": "MIT",
"author": "Optimism PBC",
"repository": {
......
......@@ -5,8 +5,8 @@ import { awaitCondition } from '@eth-optimism/core-utils'
/* Imports: Internal */
import { defaultTransactionFactory } from './shared/utils'
import env from './shared/env'
import counterArtifact from '../artifacts/Counter.sol/Counter.json'
import multiDepositorArtifact from '../artifacts/MultiDepositor.sol/MultiDepositor.json'
import counterArtifact from '../forge-artifacts/Counter.sol/Counter.json'
import multiDepositorArtifact from '../forge-artifacts/MultiDepositor.sol/MultiDepositor.json'
describe('Deposits', () => {
let portal: Contract
......
......@@ -6,6 +6,7 @@ import (
"errors"
"math/big"
"strings"
"sync"
"time"
"github.com/ethereum-optimism/optimism/bss-core/metrics"
......@@ -33,7 +34,7 @@ var DisbursementFailedTopic = common.HexToHash(
"0x9b478c095979d3d3a7d602ffd9ee1f0843204d853558ae0882c8fcc0a5bc78cf",
)
const MaxDisbursements = 5
const MaxDisbursements = 15
type Config struct {
Name string
......@@ -48,6 +49,7 @@ type Config struct {
DisburserAddr common.Address
ChainID *big.Int
PrivKey *ecdsa.PrivateKey
ChainMetricsEnable bool
}
type Driver struct {
......@@ -58,10 +60,12 @@ type Driver struct {
walletAddr common.Address
metrics *Metrics
currentDepositIDs []uint64
currentDepositIDs []uint64
chainMetricsEnabled bool
metricsMu sync.Mutex
}
func NewDriver(cfg Config) (*Driver, error) {
func NewDriver(cfg Config, parentCtx context.Context) (*Driver, error) {
if cfg.NumConfirmations == 0 {
panic("NumConfirmations cannot be zero")
}
......@@ -95,15 +99,21 @@ func NewDriver(cfg Config) (*Driver, error) {
)
walletAddr := crypto.PubkeyToAddress(cfg.PrivKey.PublicKey)
metricsInst := NewMetrics(cfg.Name)
return &Driver{
d := &Driver{
cfg: cfg,
depositContract: depositContract,
disburserContract: disburserContract,
rawDisburserContract: rawDisburserContract,
walletAddr: walletAddr,
metrics: NewMetrics(cfg.Name),
}, nil
metrics: metricsInst,
chainMetricsEnabled: cfg.ChainMetricsEnable,
}
if d.chainMetricsEnabled {
go d.collectChainMetricsBackground(parentCtx)
}
return d, nil
}
// Name is an identifier used to prefix logs for a particular service.
......@@ -140,8 +150,8 @@ func (d *Driver) ClearPendingTx(
func (d *Driver) GetBatchBlockRange(
ctx context.Context) (*big.Int, *big.Int, error) {
// Update balance metrics on each iteration.
d.updateBalanceMetrics(ctx)
// Update metrics on each iteration.
d.collectChainMetrics(ctx)
// Clear the current deposit IDs from any prior iteration.
d.currentDepositIDs = nil
......@@ -720,19 +730,63 @@ func (d *Driver) deletePendingTx(startID, endID uint64) error {
return nil
}
func (d *Driver) updateBalanceMetrics(ctx context.Context) {
disburserBal, err := d.cfg.L2Client.BalanceAt(ctx, d.walletAddr, nil)
func (d *Driver) collectChainMetricsBackground(ctx context.Context) {
tick := time.NewTicker(time.Minute)
defer tick.Stop()
for {
select {
case <-tick.C:
log.Info("collecting background metrics")
d.collectChainMetrics(ctx)
case <-ctx.Done():
return
}
}
}
func (d *Driver) collectChainMetrics(ctx context.Context) {
if !d.chainMetricsEnabled {
return
}
subCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
disburserBal, err := d.cfg.L2Client.BalanceAt(subCtx, d.cfg.DisburserAddr, nil)
if err != nil {
log.Error("Error getting disburser wallet balance", "err", err)
disburserBal = big.NewInt(0)
}
depositBal, err := d.cfg.L1Client.BalanceAt(ctx, d.cfg.DepositAddr, nil)
depositBal, err := d.cfg.L1Client.BalanceAt(subCtx, d.cfg.DepositAddr, nil)
if err != nil {
log.Error("Error getting deposit contract balance", "err", err)
depositBal = big.NewInt(0)
}
nextDepositID, err := d.depositContract.TotalDeposits(&bind.CallOpts{
Context: subCtx,
})
if err != nil {
log.Error("Error getting deposit contract total deposits")
nextDepositID = big.NewInt(0)
}
nextDisbursementID, err := d.disburserContract.TotalDisbursements(
&bind.CallOpts{
Context: subCtx,
},
)
if err != nil {
log.Error("Error getting deposit contract total disbursements")
nextDisbursementID = big.NewInt(0)
}
d.metricsMu.Lock()
d.metrics.DisburserBalance.Set(float64(disburserBal.Uint64()))
d.metrics.DepositContractBalance.Set(float64(depositBal.Uint64()))
d.metrics.ContractNextDepositID.Set(float64(nextDepositID.Uint64()))
d.metrics.ContractNextDisbursementID.Set(float64(nextDisbursementID.Uint64()))
d.metricsMu.Unlock()
}
......@@ -66,6 +66,10 @@ type Metrics struct {
// the disburser contract.
ContractNextDisbursementID prometheus.Gauge
// ContractNextDepositID tracks the next deposit id expected by the deposit
// contract.
ContractNextDepositID prometheus.Gauge
// DisburserBalance tracks Teleportr's disburser account balance.
DisburserBalance prometheus.Gauge
......@@ -117,6 +121,11 @@ func NewMetrics(subsystem string) *Metrics {
Help: "Next disbursement id expected by the disburser contract",
Subsystem: base.SubsystemName(),
}),
ContractNextDepositID: promauto.NewGauge(prometheus.GaugeOpts{
Name: "contract_next_deposit_id",
Help: "next deposit id expected by the deposit contract",
Subsystem: base.SubsystemName(),
}),
DisburserBalance: promauto.NewGauge(prometheus.GaugeOpts{
Name: "disburser_balance",
Help: "Balance in Wei of Teleportr's disburser wallet",
......
......@@ -110,7 +110,8 @@ func Main(gitVersion string) func(ctx *cli.Context) error {
DisburserAddr: disburserAddr,
ChainID: chainID,
PrivKey: disburserPrivKey,
})
ChainMetricsEnable: cfg.MetricsServerEnable,
}, ctx)
if err != nil {
return err
}
......
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