Commit fdfc1e3d authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

Merge pull request #4727 from ethereum-optimism/develop

Develop -> Master PR
parents e9a230d6 169a0d75
---
'@eth-optimism/data-transport-layer': patch
---
Fixes a bug in the DTL that would cause it to not be able to sync beyond the deposit shutoff block.
---
'@eth-optimism/ci-builder': minor
'@eth-optimism/foundry': minor
---
Bump foundry to 2ff99025abade470a795724c10648c800a41025e
......@@ -8,7 +8,7 @@ There are plenty of ways to contribute, in particular we appreciate support in t
- Fixing and responding to existing issues. You can start off with those tagged ["good first issue"](https://github.com/ethereum-optimism/optimism/contribute) which are meant as introductory issues for external contributors.
- Improving the [community site](https://community.optimism.io/), [documentation](https://github.com/ethereum-optimism/community-hub) and [tutorials](https://github.com/ethereum-optimism/optimism-tutorial).
- Become an "Optimizer" and answer questions in the [Optimism Discord](https://discord.optimism.io).
- Get involved in the protocol design process by proposing changes or new features or write parts of the spec yourself in the [optimistic-specs repo](https://github.com/ethereum-optimism/optimistic-specs).
- Get involved in the protocol design process by proposing changes or new features or write parts of the spec yourself in the [specs subdirectory](./specs/).
Note that we have a [Code of Conduct](https://github.com/ethereum-optimism/.github/blob/master/CODE_OF_CONDUCT.md), please follow it in all your interactions with the project.
......
......@@ -13,7 +13,7 @@ import (
)
var (
Version = "v0.10.9"
Version = "v0.10.10"
GitCommit = ""
GitDate = ""
)
......
......@@ -4,9 +4,9 @@ go 1.18
require (
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3
github.com/ethereum-optimism/optimism/op-node v0.10.9
github.com/ethereum-optimism/optimism/op-proposer v0.10.9
github.com/ethereum-optimism/optimism/op-service v0.10.9
github.com/ethereum-optimism/optimism/op-node v0.10.10
github.com/ethereum-optimism/optimism/op-proposer v0.10.10
github.com/ethereum-optimism/optimism/op-service v0.10.10
github.com/ethereum/go-ethereum v1.10.26
github.com/urfave/cli v1.22.9
)
......@@ -23,7 +23,7 @@ require (
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
github.com/ethereum-optimism/optimism/op-bindings v0.10.9 // indirect
github.com/ethereum-optimism/optimism/op-bindings v0.10.10 // indirect
github.com/fjl/memsize v0.0.1 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.1 // indirect
......
......@@ -107,14 +107,14 @@ github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs=
github.com/ethereum-optimism/op-geth v0.0.0-20221216190603-60b51d600468 h1:7KgjBYDji5AKi42eRYI+n8Gs+ZJVilSASL3WBu82c3M=
github.com/ethereum-optimism/op-geth v0.0.0-20221216190603-60b51d600468/go.mod h1:p0Yox74PhYlq1HvijrCBCD9A3cI7rXco7hT6KrQr+rY=
github.com/ethereum-optimism/optimism/op-bindings v0.10.9 h1:FC+M7om33BYBTcdHyZwDX8H/igrZsxtdk+xZAnfIRJg=
github.com/ethereum-optimism/optimism/op-bindings v0.10.9/go.mod h1:9ZSUq/rjlzp3uYyBN4sZmhTc3oZgDVqJ4wrUja7vj6c=
github.com/ethereum-optimism/optimism/op-node v0.10.9 h1:93B8u5hGvXyyESYIMeCGfkZbwFt+gJBx44c1PUvEjrA=
github.com/ethereum-optimism/optimism/op-node v0.10.9/go.mod h1:rtMSVpV5++c/3y3ShyIxaDEm1UmS6iCibY20DFx9HPs=
github.com/ethereum-optimism/optimism/op-proposer v0.10.9 h1:/RLP/eBUhT4N/bHobQnaJAcgb4Gg7mO9C/nv3nDnvV8=
github.com/ethereum-optimism/optimism/op-proposer v0.10.9/go.mod h1:hRF9v4ERcX42J5xIPPD5BnKTOFSKpzrV+meyi1IHXq4=
github.com/ethereum-optimism/optimism/op-service v0.10.9 h1:B6cU47e5MqibqsPzATmNHvjvy04aa8yfgWe5Lv2VQCg=
github.com/ethereum-optimism/optimism/op-service v0.10.9/go.mod h1:wbtHqi1fv00B3agj7a2zdP3OFanEfGZ23zPgGgFCF/c=
github.com/ethereum-optimism/optimism/op-bindings v0.10.10 h1:Khi7m2IyNdB2JeMdW3Y1YibePTiAzuLMHe8hBE2WQzs=
github.com/ethereum-optimism/optimism/op-bindings v0.10.10/go.mod h1:9ZSUq/rjlzp3uYyBN4sZmhTc3oZgDVqJ4wrUja7vj6c=
github.com/ethereum-optimism/optimism/op-node v0.10.10 h1:edmxboiYSIk9n4A3paEF7I0m5qi+v+6FBFkqAfpFU7Y=
github.com/ethereum-optimism/optimism/op-node v0.10.10/go.mod h1:EEcHgMdKiWasJGO5uzspRN2xM1/OB+ehgVgMj4RgPas=
github.com/ethereum-optimism/optimism/op-proposer v0.10.10 h1:VOpHt1T/CnaYhjbhj/rG+yU+/Tay3fkHSrU/2s8e2po=
github.com/ethereum-optimism/optimism/op-proposer v0.10.10/go.mod h1:oRPWIlr9DsVT4iNHmXs1AVhUYlU6I9GZ50YqnKcADWc=
github.com/ethereum-optimism/optimism/op-service v0.10.10 h1:B5mGpATX6zPkDABoh6smCjh6Z5mA2KWh71MD1i6T5ww=
github.com/ethereum-optimism/optimism/op-service v0.10.10/go.mod h1:wbtHqi1fv00B3agj7a2zdP3OFanEfGZ23zPgGgFCF/c=
github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ=
github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
......
......@@ -3,7 +3,7 @@ module github.com/ethereum-optimism/optimism/op-chain-ops
go 1.18
require (
github.com/ethereum-optimism/optimism/op-bindings v0.10.9
github.com/ethereum-optimism/optimism/op-bindings v0.10.10
github.com/ethereum-optimism/optimism/op-node v0.10.1
github.com/ethereum/go-ethereum v1.10.26
github.com/holiman/uint256 v1.2.0
......@@ -23,7 +23,7 @@ require (
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
github.com/edsrzf/mmap-go v1.1.0 // indirect
github.com/ethereum-optimism/optimism/op-service v0.10.9 // indirect
github.com/ethereum-optimism/optimism/op-service v0.10.10 // indirect
github.com/go-kit/kit v0.10.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.1 // indirect
......
......@@ -79,12 +79,12 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/op-geth v0.0.0-20221216190603-60b51d600468 h1:7KgjBYDji5AKi42eRYI+n8Gs+ZJVilSASL3WBu82c3M=
github.com/ethereum-optimism/op-geth v0.0.0-20221216190603-60b51d600468/go.mod h1:p0Yox74PhYlq1HvijrCBCD9A3cI7rXco7hT6KrQr+rY=
github.com/ethereum-optimism/optimism/op-bindings v0.10.9 h1:FC+M7om33BYBTcdHyZwDX8H/igrZsxtdk+xZAnfIRJg=
github.com/ethereum-optimism/optimism/op-bindings v0.10.9/go.mod h1:9ZSUq/rjlzp3uYyBN4sZmhTc3oZgDVqJ4wrUja7vj6c=
github.com/ethereum-optimism/optimism/op-bindings v0.10.10 h1:Khi7m2IyNdB2JeMdW3Y1YibePTiAzuLMHe8hBE2WQzs=
github.com/ethereum-optimism/optimism/op-bindings v0.10.10/go.mod h1:9ZSUq/rjlzp3uYyBN4sZmhTc3oZgDVqJ4wrUja7vj6c=
github.com/ethereum-optimism/optimism/op-node v0.10.1 h1:kVBaOEOYLV22XEHRhB7dfdmoXepO0kx/RsZQK+Bpk1Y=
github.com/ethereum-optimism/optimism/op-node v0.10.1/go.mod h1:pup7wiiUs9g8cZKwXeB5tEGCqwUUwFVmej9MmSIm6S8=
github.com/ethereum-optimism/optimism/op-service v0.10.9 h1:B6cU47e5MqibqsPzATmNHvjvy04aa8yfgWe5Lv2VQCg=
github.com/ethereum-optimism/optimism/op-service v0.10.9/go.mod h1:wbtHqi1fv00B3agj7a2zdP3OFanEfGZ23zPgGgFCF/c=
github.com/ethereum-optimism/optimism/op-service v0.10.10 h1:B5mGpATX6zPkDABoh6smCjh6Z5mA2KWh71MD1i6T5ww=
github.com/ethereum-optimism/optimism/op-service v0.10.10/go.mod h1:wbtHqi1fv00B3agj7a2zdP3OFanEfGZ23zPgGgFCF/c=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
......
......@@ -10,12 +10,12 @@ require (
github.com/docker/docker v20.10.21+incompatible
github.com/docker/go-connections v0.4.0
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3
github.com/ethereum-optimism/optimism/op-batcher v0.10.9
github.com/ethereum-optimism/optimism/op-bindings v0.10.9
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.9
github.com/ethereum-optimism/optimism/op-node v0.10.9
github.com/ethereum-optimism/optimism/op-proposer v0.10.9
github.com/ethereum-optimism/optimism/op-service v0.10.9
github.com/ethereum-optimism/optimism/op-batcher v0.10.10
github.com/ethereum-optimism/optimism/op-bindings v0.10.10
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.10
github.com/ethereum-optimism/optimism/op-node v0.10.10
github.com/ethereum-optimism/optimism/op-proposer v0.10.10
github.com/ethereum-optimism/optimism/op-service v0.10.10
github.com/ethereum/go-ethereum v1.10.26
github.com/google/gofuzz v1.2.1-0.20220503160820-4a35382e8fc8
github.com/libp2p/go-libp2p v0.23.3
......@@ -73,7 +73,6 @@ require (
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
github.com/ipfs/go-cid v0.3.2 // indirect
github.com/ipfs/go-datastore v0.6.0 // indirect
github.com/ipfs/go-ds-leveldb v0.5.0 // indirect
github.com/ipfs/go-log v1.0.5 // indirect
github.com/ipfs/go-log/v2 v2.5.1 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
......
......@@ -159,18 +159,18 @@ github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs=
github.com/ethereum-optimism/op-geth v0.0.0-20221216190603-60b51d600468 h1:7KgjBYDji5AKi42eRYI+n8Gs+ZJVilSASL3WBu82c3M=
github.com/ethereum-optimism/op-geth v0.0.0-20221216190603-60b51d600468/go.mod h1:p0Yox74PhYlq1HvijrCBCD9A3cI7rXco7hT6KrQr+rY=
github.com/ethereum-optimism/optimism/op-batcher v0.10.9 h1:4jVwnc56rJO+acKMz9L86+AV/q/QgYLU0zshfHW5aZ8=
github.com/ethereum-optimism/optimism/op-batcher v0.10.9/go.mod h1:VN53ECiipFG8uo5stH9YBa968YA1ii7Fg1pw+WjpK6I=
github.com/ethereum-optimism/optimism/op-bindings v0.10.9 h1:FC+M7om33BYBTcdHyZwDX8H/igrZsxtdk+xZAnfIRJg=
github.com/ethereum-optimism/optimism/op-bindings v0.10.9/go.mod h1:9ZSUq/rjlzp3uYyBN4sZmhTc3oZgDVqJ4wrUja7vj6c=
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.9 h1:1zO/XGavOhKE39D6bmdyVJehLFq9IBgJpbbt+8gPfu4=
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.9/go.mod h1:17sjIp7SXPN8Bi/yPgmOm6DiYbdOmsxjlgLZLAWg004=
github.com/ethereum-optimism/optimism/op-node v0.10.9 h1:93B8u5hGvXyyESYIMeCGfkZbwFt+gJBx44c1PUvEjrA=
github.com/ethereum-optimism/optimism/op-node v0.10.9/go.mod h1:rtMSVpV5++c/3y3ShyIxaDEm1UmS6iCibY20DFx9HPs=
github.com/ethereum-optimism/optimism/op-proposer v0.10.9 h1:/RLP/eBUhT4N/bHobQnaJAcgb4Gg7mO9C/nv3nDnvV8=
github.com/ethereum-optimism/optimism/op-proposer v0.10.9/go.mod h1:hRF9v4ERcX42J5xIPPD5BnKTOFSKpzrV+meyi1IHXq4=
github.com/ethereum-optimism/optimism/op-service v0.10.9 h1:B6cU47e5MqibqsPzATmNHvjvy04aa8yfgWe5Lv2VQCg=
github.com/ethereum-optimism/optimism/op-service v0.10.9/go.mod h1:wbtHqi1fv00B3agj7a2zdP3OFanEfGZ23zPgGgFCF/c=
github.com/ethereum-optimism/optimism/op-batcher v0.10.10 h1:uujkdVCjRv7WJA9205PMwqXpCAeG0IxYu4hREPkK1IY=
github.com/ethereum-optimism/optimism/op-batcher v0.10.10/go.mod h1:dhTcmYjZyHKKfLAP9qQgXRBbrDvckBmNo3/Yu4zqaqg=
github.com/ethereum-optimism/optimism/op-bindings v0.10.10 h1:Khi7m2IyNdB2JeMdW3Y1YibePTiAzuLMHe8hBE2WQzs=
github.com/ethereum-optimism/optimism/op-bindings v0.10.10/go.mod h1:9ZSUq/rjlzp3uYyBN4sZmhTc3oZgDVqJ4wrUja7vj6c=
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.10 h1:99OW6aQMSsBLTSplvVfvSrZy8ZH3qs5dG5T0o1Ffwd0=
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.10/go.mod h1:dWZgOwVz2nK/pFY9fVFxStjYFVqnbz954pwIysStmEY=
github.com/ethereum-optimism/optimism/op-node v0.10.10 h1:edmxboiYSIk9n4A3paEF7I0m5qi+v+6FBFkqAfpFU7Y=
github.com/ethereum-optimism/optimism/op-node v0.10.10/go.mod h1:EEcHgMdKiWasJGO5uzspRN2xM1/OB+ehgVgMj4RgPas=
github.com/ethereum-optimism/optimism/op-proposer v0.10.10 h1:VOpHt1T/CnaYhjbhj/rG+yU+/Tay3fkHSrU/2s8e2po=
github.com/ethereum-optimism/optimism/op-proposer v0.10.10/go.mod h1:oRPWIlr9DsVT4iNHmXs1AVhUYlU6I9GZ50YqnKcADWc=
github.com/ethereum-optimism/optimism/op-service v0.10.10 h1:B5mGpATX6zPkDABoh6smCjh6Z5mA2KWh71MD1i6T5ww=
github.com/ethereum-optimism/optimism/op-service v0.10.10/go.mod h1:wbtHqi1fv00B3agj7a2zdP3OFanEfGZ23zPgGgFCF/c=
github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ=
github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
......@@ -290,7 +290,6 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
......@@ -342,15 +341,12 @@ github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mq
github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po=
github.com/ipfs/go-cid v0.3.2 h1:OGgOd+JCFM+y1DjWPmVH+2/4POtpDzwcr7VgnB7mZXc=
github.com/ipfs/go-cid v0.3.2/go.mod h1:gQ8pKqT/sUxGY+tIwy1RPpAojYu7jAyCp5Tz1svoupw=
github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk=
github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk=
github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8=
github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
github.com/ipfs/go-ds-badger v0.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1Ro=
github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo=
github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q=
github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g=
......@@ -400,7 +396,6 @@ github.com/koron/go-ssdp v0.0.3 h1:JivLMY45N76b4p/vsWGOKewBQu6uf39y8l+AQ7sDKx8=
github.com/koron/go-ssdp v0.0.3/go.mod h1:b2MxI6yh02pKrsyNoQUsk4+YNikaGhe4894J+Q5lDvA=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
......@@ -658,7 +653,6 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI=
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48=
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
......
......@@ -4,6 +4,8 @@ import (
"time"
"github.com/urfave/cli"
"github.com/ethereum-optimism/optimism/op-node/p2p"
)
func p2pEnv(v string) string {
......@@ -199,6 +201,45 @@ var (
Value: "",
EnvVar: p2pEnv("SEQUENCER_KEY"),
}
GossipMeshDFlag = cli.UintFlag{
Name: "p2p.gossip.mesh.d",
Usage: "Configure GossipSub topic stable mesh target count, a.k.a. desired outbound degree, number of peers to gossip to",
Required: false,
Hidden: true,
Value: p2p.DefaultMeshD,
EnvVar: p2pEnv("GOSSIP_MESH_D"),
}
GossipMeshDloFlag = cli.UintFlag{
Name: "p2p.gossip.mesh.lo",
Usage: "Configure GossipSub topic stable mesh low watermark, a.k.a. lower bound of outbound degree",
Required: false,
Hidden: true,
Value: p2p.DefaultMeshDlo,
EnvVar: p2pEnv("GOSSIP_MESH_DLO"),
}
GossipMeshDhiFlag = cli.UintFlag{
Name: "p2p.gossip.mesh.dhi",
Usage: "Configure GossipSub topic stable mesh high watermark, a.k.a. upper bound of outbound degree, additional peers will not receive gossip",
Required: false,
Hidden: true,
Value: p2p.DefaultMeshDhi,
EnvVar: p2pEnv("GOSSIP_MESH_DHI"),
}
GossipMeshDlazyFlag = cli.UintFlag{
Name: "p2p.gossip.mesh.dlazy",
Usage: "Configure GossipSub gossip target, a.k.a. target degree for gossip only (not messaging like p2p.gossip.mesh.d, just announcements of IHAVE",
Required: false,
Hidden: true,
Value: p2p.DefaultMeshDlazy,
EnvVar: p2pEnv("GOSSIP_MESH_DLAZY"),
}
GossipFloodPublishFlag = cli.BoolFlag{
Name: "p2p.gossip.mesh.floodpublish",
Usage: "Configure GossipSub to publish messages to all known peers on the topic, outside of the mesh, also see Dlazy as less aggressive alternative.",
Required: false,
Hidden: true,
EnvVar: p2pEnv("GOSSIP_FLOOD_PUBLISH"),
}
)
// None of these flags are strictly required.
......@@ -229,4 +270,9 @@ var p2pFlags = []cli.Flag{
PeerstorePath,
DiscoveryPath,
SequencerP2PKeyFlag,
GossipMeshDFlag,
GossipMeshDloFlag,
GossipMeshDhiFlag,
GossipMeshDlazyFlag,
GossipFloodPublishFlag,
}
......@@ -6,9 +6,9 @@ require (
github.com/btcsuite/btcd v0.23.3
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0
github.com/ethereum-optimism/optimism/op-bindings v0.10.9
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.9
github.com/ethereum-optimism/optimism/op-service v0.10.9
github.com/ethereum-optimism/optimism/op-bindings v0.10.10
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.10
github.com/ethereum-optimism/optimism/op-service v0.10.10
github.com/ethereum/go-ethereum v1.10.26
github.com/golang/snappy v0.0.4
github.com/google/go-cmp v0.5.8
......
......@@ -145,12 +145,12 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/op-geth v0.0.0-20221216190603-60b51d600468 h1:7KgjBYDji5AKi42eRYI+n8Gs+ZJVilSASL3WBu82c3M=
github.com/ethereum-optimism/op-geth v0.0.0-20221216190603-60b51d600468/go.mod h1:p0Yox74PhYlq1HvijrCBCD9A3cI7rXco7hT6KrQr+rY=
github.com/ethereum-optimism/optimism/op-bindings v0.10.9 h1:FC+M7om33BYBTcdHyZwDX8H/igrZsxtdk+xZAnfIRJg=
github.com/ethereum-optimism/optimism/op-bindings v0.10.9/go.mod h1:9ZSUq/rjlzp3uYyBN4sZmhTc3oZgDVqJ4wrUja7vj6c=
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.9 h1:1zO/XGavOhKE39D6bmdyVJehLFq9IBgJpbbt+8gPfu4=
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.9/go.mod h1:17sjIp7SXPN8Bi/yPgmOm6DiYbdOmsxjlgLZLAWg004=
github.com/ethereum-optimism/optimism/op-service v0.10.9 h1:B6cU47e5MqibqsPzATmNHvjvy04aa8yfgWe5Lv2VQCg=
github.com/ethereum-optimism/optimism/op-service v0.10.9/go.mod h1:wbtHqi1fv00B3agj7a2zdP3OFanEfGZ23zPgGgFCF/c=
github.com/ethereum-optimism/optimism/op-bindings v0.10.10 h1:Khi7m2IyNdB2JeMdW3Y1YibePTiAzuLMHe8hBE2WQzs=
github.com/ethereum-optimism/optimism/op-bindings v0.10.10/go.mod h1:9ZSUq/rjlzp3uYyBN4sZmhTc3oZgDVqJ4wrUja7vj6c=
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.10 h1:99OW6aQMSsBLTSplvVfvSrZy8ZH3qs5dG5T0o1Ffwd0=
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.10/go.mod h1:dWZgOwVz2nK/pFY9fVFxStjYFVqnbz954pwIysStmEY=
github.com/ethereum-optimism/optimism/op-service v0.10.10 h1:B5mGpATX6zPkDABoh6smCjh6Z5mA2KWh71MD1i6T5ww=
github.com/ethereum-optimism/optimism/op-service v0.10.10/go.mod h1:wbtHqi1fv00B3agj7a2zdP3OFanEfGZ23zPgGgFCF/c=
github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ=
github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
......
......@@ -15,7 +15,7 @@ import (
var (
// UnsafeBlockSignerAddressSystemConfigStorageSlot is the storage slot identifier of the unsafeBlockSigner
// `address` storage value in the SystemConfig L1 contract.
// `address` storage value in the SystemConfig L1 contract. Computed as `keccak256("systemconfig.unsafeblocksigner")`
UnsafeBlockSignerAddressSystemConfigStorageSlot = common.HexToHash("0x65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08")
)
......
package cli
import (
"crypto/rand"
"encoding/hex"
"errors"
"fmt"
"io"
"net"
"os"
"strings"
ds "github.com/ipfs/go-datastore"
"github.com/ipfs/go-datastore/sync"
leveldb "github.com/ipfs/go-ds-leveldb"
lconf "github.com/libp2p/go-libp2p/config"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/multiformats/go-multiaddr"
"github.com/ethereum-optimism/optimism/op-node/flags"
"github.com/ethereum-optimism/optimism/op-node/p2p"
"github.com/urfave/cli"
"github.com/ethereum/go-ethereum/p2p/enode"
)
func NewConfig(ctx *cli.Context) (*p2p.Config, error) {
conf := &p2p.Config{}
if ctx.GlobalBool(flags.DisableP2P.Name) {
conf.DisableP2P = true
return conf, nil
}
p, err := loadNetworkPrivKey(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load p2p priv key: %w", err)
}
conf.Priv = p
if err := loadListenOpts(conf, ctx); err != nil {
return nil, fmt.Errorf("failed to load p2p listen options: %w", err)
}
if err := loadDiscoveryOpts(conf, ctx); err != nil {
return nil, fmt.Errorf("failed to load p2p discovery options: %w", err)
}
if err := loadLibp2pOpts(conf, ctx); err != nil {
return nil, fmt.Errorf("failed to load p2p options: %w", err)
}
if err := loadGossipOptions(conf, ctx); err != nil {
return nil, fmt.Errorf("failed to load p2p gossip options: %w", err)
}
conf.ConnGater = p2p.DefaultConnGater
conf.ConnMngr = p2p.DefaultConnManager
return conf, nil
}
func validatePort(p uint) (uint16, error) {
if p == 0 {
return 0, nil
}
if p >= (1 << 16) {
return 0, fmt.Errorf("port out of range: %d", p)
}
if p < 1024 {
return 0, fmt.Errorf("port is reserved for system: %d", p)
}
return uint16(p), nil
}
func loadListenOpts(conf *p2p.Config, ctx *cli.Context) error {
listenIP := ctx.GlobalString(flags.ListenIP.Name)
if listenIP != "" { // optional
conf.ListenIP = net.ParseIP(listenIP)
if conf.ListenIP == nil {
return fmt.Errorf("failed to parse IP %q", listenIP)
}
}
var err error
conf.ListenTCPPort, err = validatePort(ctx.GlobalUint(flags.ListenTCPPort.Name))
if err != nil {
return fmt.Errorf("bad listen TCP port: %w", err)
}
conf.ListenUDPPort, err = validatePort(ctx.GlobalUint(flags.ListenUDPPort.Name))
if err != nil {
return fmt.Errorf("bad listen UDP port: %w", err)
}
return nil
}
func loadDiscoveryOpts(conf *p2p.Config, ctx *cli.Context) error {
if ctx.GlobalBool(flags.NoDiscovery.Name) {
conf.NoDiscovery = true
}
var err error
conf.AdvertiseTCPPort, err = validatePort(ctx.GlobalUint(flags.AdvertiseTCPPort.Name))
if err != nil {
return fmt.Errorf("bad advertised TCP port: %w", err)
}
conf.AdvertiseUDPPort, err = validatePort(ctx.GlobalUint(flags.AdvertiseUDPPort.Name))
if err != nil {
return fmt.Errorf("bad advertised UDP port: %w", err)
}
adIP := ctx.GlobalString(flags.AdvertiseIP.Name)
if adIP != "" { // optional
ips, err := net.LookupIP(adIP)
if err != nil {
return fmt.Errorf("failed to lookup IP of %q to advertise in ENR: %w", adIP, err)
}
// Find the first v4 IP it resolves to
for _, ip := range ips {
if ipv4 := ip.To4(); ipv4 != nil {
conf.AdvertiseIP = ipv4
break
}
}
if conf.AdvertiseIP == nil {
return fmt.Errorf("failed to parse IP %q", adIP)
}
}
dbPath := ctx.GlobalString(flags.DiscoveryPath.Name)
if dbPath == "" {
dbPath = "opnode_discovery_db"
}
if dbPath == "memory" {
dbPath = ""
}
conf.DiscoveryDB, err = enode.OpenDB(dbPath)
if err != nil {
return fmt.Errorf("failed to open discovery db: %w", err)
}
conf.Bootnodes = p2p.DefaultBootnodes
records := strings.Split(ctx.GlobalString(flags.Bootnodes.Name), ",")
for i, recordB64 := range records {
recordB64 = strings.TrimSpace(recordB64)
if recordB64 == "" { // ignore empty records
continue
}
nodeRecord, err := enode.Parse(enode.ValidSchemes, recordB64)
if err != nil {
return fmt.Errorf("bootnode record %d (of %d) is invalid: %q err: %w", i, len(records), recordB64, err)
}
conf.Bootnodes = append(conf.Bootnodes, nodeRecord)
}
return nil
}
func loadLibp2pOpts(conf *p2p.Config, ctx *cli.Context) error {
addrs := strings.Split(ctx.GlobalString(flags.StaticPeers.Name), ",")
for i, addr := range addrs {
addr = strings.TrimSpace(addr)
if addr == "" {
continue // skip empty multi addrs
}
a, err := multiaddr.NewMultiaddr(addr)
if err != nil {
return fmt.Errorf("failed to parse multi addr of static peer %d (out of %d): %q err: %w", i, len(addrs), addr, err)
}
conf.StaticPeers = append(conf.StaticPeers, a)
}
for _, v := range strings.Split(ctx.GlobalString(flags.HostMux.Name), ",") {
v = strings.ToLower(strings.TrimSpace(v))
var mc lconf.MsMuxC
var err error
switch v {
case "yamux":
mc, err = p2p.YamuxC()
case "mplex":
mc, err = p2p.MplexC()
default:
return fmt.Errorf("could not recognize mux %s", v)
}
if err != nil {
return fmt.Errorf("failed to make %s constructor: %w", v, err)
}
conf.HostMux = append(conf.HostMux, mc)
}
secArr := strings.Split(ctx.GlobalString(flags.HostSecurity.Name), ",")
for _, v := range secArr {
v = strings.ToLower(strings.TrimSpace(v))
var sc lconf.MsSecC
var err error
switch v {
case "none": // no security, for debugging etc.
if len(conf.HostSecurity) > 0 || len(secArr) > 1 {
return errors.New("cannot mix secure transport protocols with no-security")
}
conf.NoTransportSecurity = true
case "noise":
sc, err = p2p.NoiseC()
case "tls":
sc, err = p2p.TlsC()
default:
return fmt.Errorf("could not recognize security %s", v)
}
if err != nil {
return fmt.Errorf("failed to make %s constructor: %w", v, err)
}
conf.HostSecurity = append(conf.HostSecurity, sc)
}
conf.PeersLo = ctx.GlobalUint(flags.PeersLo.Name)
conf.PeersHi = ctx.GlobalUint(flags.PeersHi.Name)
conf.PeersGrace = ctx.GlobalDuration(flags.PeersGrace.Name)
conf.NAT = ctx.GlobalBool(flags.NAT.Name)
conf.UserAgent = ctx.GlobalString(flags.UserAgent.Name)
conf.TimeoutNegotiation = ctx.GlobalDuration(flags.TimeoutNegotiation.Name)
conf.TimeoutAccept = ctx.GlobalDuration(flags.TimeoutAccept.Name)
conf.TimeoutDial = ctx.GlobalDuration(flags.TimeoutDial.Name)
peerstorePath := ctx.GlobalString(flags.PeerstorePath.Name)
if peerstorePath == "" {
return errors.New("peerstore path must be specified, use 'memory' to explicitly not persist peer records")
}
var err error
var store ds.Batching
if peerstorePath == "memory" {
store = sync.MutexWrap(ds.NewMapDatastore())
} else {
store, err = leveldb.NewDatastore(peerstorePath, nil) // default leveldb options are fine
if err != nil {
return fmt.Errorf("failed to open leveldb db for peerstore: %w", err)
}
}
conf.Store = store
return nil
}
func loadNetworkPrivKey(ctx *cli.Context) (*crypto.Secp256k1PrivateKey, error) {
raw := ctx.GlobalString(flags.P2PPrivRaw.Name)
if raw != "" {
return parsePriv(raw)
}
keyPath := ctx.GlobalString(flags.P2PPrivPath.Name)
if keyPath == "" {
return nil, errors.New("no p2p private key path specified, cannot auto-generate key without path")
}
f, err := os.OpenFile(keyPath, os.O_RDONLY, 0600)
if os.IsNotExist(err) {
p, _, err := crypto.GenerateSecp256k1Key(rand.Reader)
if err != nil {
return nil, fmt.Errorf("failed to generate new p2p priv key: %w", err)
}
b, err := p.Raw()
if err != nil {
return nil, fmt.Errorf("failed to encode new p2p priv key: %w", err)
}
f, err := os.OpenFile(keyPath, os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
return nil, fmt.Errorf("failed to store new p2p priv key: %w", err)
}
defer f.Close()
if _, err := f.WriteString(hex.EncodeToString(b)); err != nil {
return nil, fmt.Errorf("failed to write new p2p priv key: %w", err)
}
return (p).(*crypto.Secp256k1PrivateKey), nil
} else {
defer f.Close()
data, err := io.ReadAll(f)
if err != nil {
return nil, fmt.Errorf("failed to read priv key file: %w", err)
}
return parsePriv(strings.TrimSpace(string(data)))
}
}
func parsePriv(data string) (*crypto.Secp256k1PrivateKey, error) {
if len(data) > 2 && data[:2] == "0x" {
data = data[2:]
}
b, err := hex.DecodeString(data)
if err != nil {
return nil, errors.New("p2p priv key is not formatted in hex chars")
}
p, err := crypto.UnmarshalSecp256k1PrivateKey(b)
if err != nil {
// avoid logging the priv key in the error, but hint at likely input length problem
return nil, fmt.Errorf("failed to parse priv key from %d bytes", len(b))
}
return (p).(*crypto.Secp256k1PrivateKey), nil
}
func loadGossipOptions(conf *p2p.Config, ctx *cli.Context) error {
conf.MeshD = ctx.GlobalInt(flags.GossipMeshDFlag.Name)
conf.MeshDLo = ctx.GlobalInt(flags.GossipMeshDloFlag.Name)
conf.MeshDHi = ctx.GlobalInt(flags.GossipMeshDhiFlag.Name)
conf.MeshDLazy = ctx.GlobalInt(flags.GossipMeshDlazyFlag.Name)
conf.FloodPublish = ctx.GlobalBool(flags.GossipFloodPublishFlag.Name)
return nil
}
package cli
import (
"fmt"
"github.com/ethereum/go-ethereum/crypto"
"github.com/urfave/cli"
"github.com/ethereum-optimism/optimism/op-node/flags"
"github.com/ethereum-optimism/optimism/op-node/p2p"
)
// TODO: implement remote signer setup (config to authenticated endpoint)
// and remote signer itself (e.g. a open http client to make signing requests)
// LoadSignerSetup loads a configuration for a Signer to be set up later
func LoadSignerSetup(ctx *cli.Context) (p2p.SignerSetup, error) {
key := ctx.GlobalString(flags.SequencerP2PKeyFlag.Name)
if key != "" {
// Mnemonics are bad because they leak *all* keys when they leak.
// Unencrypted keys from file are bad because they are easy to leak (and we are not checking file permissions).
priv, err := crypto.HexToECDSA(key)
if err != nil {
return nil, fmt.Errorf("failed to read batch submitter key: %w", err)
}
return &p2p.PreparedSigner{Signer: p2p.NewLocalSigner(priv)}, nil
}
// TODO: create remote signer
return nil, nil
}
This diff is collapsed.
......@@ -34,7 +34,11 @@ const (
globalValidateThrottle = 512
gossipHeartbeat = 500 * time.Millisecond
// seenMessagesTTL limits the duration that message IDs are remembered for gossip deduplication purposes
seenMessagesTTL = 80 * gossipHeartbeat
seenMessagesTTL = 80 * gossipHeartbeat
DefaultMeshD = 8 // topic stable mesh target count
DefaultMeshDlo = 6 // topic stable mesh low watermark
DefaultMeshDhi = 12 // topic stable mesh high watermark
DefaultMeshDlazy = 6 // gossip target
)
// Message domains, the msg id function uncompresses to keep data monomorphic,
......@@ -43,6 +47,10 @@ const (
var MessageDomainInvalidSnappy = [4]byte{0, 0, 0, 0}
var MessageDomainValidSnappy = [4]byte{1, 0, 0, 0}
type GossipSetupConfigurables interface {
ConfigureGossip(params *pubsub.GossipSubParams) []pubsub.Option
}
type GossipRuntimeConfig interface {
P2PSequencerAddress() common.Address
}
......@@ -106,12 +114,24 @@ func BuildMsgIdFn(cfg *rollup.Config) pubsub.MsgIdFunction {
}
}
func (p *Config) ConfigureGossip(params *pubsub.GossipSubParams) []pubsub.Option {
params.D = p.MeshD
params.Dlo = p.MeshDLo
params.Dhi = p.MeshDHi
params.Dlazy = p.MeshDLazy
// in the future we may add more advanced options like scoring and PX / direct-mesh / episub
return []pubsub.Option{
pubsub.WithFloodPublish(p.FloodPublish),
}
}
func BuildGlobalGossipParams(cfg *rollup.Config) pubsub.GossipSubParams {
params := pubsub.DefaultGossipSubParams()
params.D = 8 // topic stable mesh target count
params.Dlo = 6 // topic stable mesh low watermark
params.Dhi = 12 // topic stable mesh high watermark
params.Dlazy = 6 // gossip target
params.D = DefaultMeshD // topic stable mesh target count
params.Dlo = DefaultMeshDlo // topic stable mesh low watermark
params.Dhi = DefaultMeshDhi // topic stable mesh high watermark
params.Dlazy = DefaultMeshDlazy // gossip target
params.HeartbeatInterval = gossipHeartbeat // interval of heartbeat
params.FanoutTTL = 24 * time.Second // ttl for fanout maps for topics we are not subscribed to but have published to
params.HistoryLength = 12 // number of windows to retain full messages in cache for IWANT responses
......@@ -120,12 +140,13 @@ func BuildGlobalGossipParams(cfg *rollup.Config) pubsub.GossipSubParams {
return params
}
func NewGossipSub(p2pCtx context.Context, h host.Host, cfg *rollup.Config, m GossipMetricer) (*pubsub.PubSub, error) {
func NewGossipSub(p2pCtx context.Context, h host.Host, cfg *rollup.Config, gossipConf GossipSetupConfigurables, m GossipMetricer) (*pubsub.PubSub, error) {
denyList, err := pubsub.NewTimeCachedBlacklist(30 * time.Second)
if err != nil {
return nil, err
}
return pubsub.NewGossipSub(p2pCtx, h,
params := BuildGlobalGossipParams(cfg)
gossipOpts := []pubsub.Option{
pubsub.WithMaxMessageSize(maxGossipSize),
pubsub.WithMessageIdFn(BuildMsgIdFn(cfg)),
pubsub.WithNoAuthor(),
......@@ -137,9 +158,11 @@ func NewGossipSub(p2pCtx context.Context, h host.Host, cfg *rollup.Config, m Gos
pubsub.WithSeenMessagesTTL(seenMessagesTTL),
pubsub.WithPeerExchange(false),
pubsub.WithBlacklist(denyList),
pubsub.WithGossipSubParams(BuildGlobalGossipParams(cfg)),
pubsub.WithGossipSubParams(params),
pubsub.WithEventTracer(&gossipTracer{m: m}),
)
}
gossipOpts = append(gossipOpts, gossipConf.ConfigureGossip(&params)...)
return pubsub.NewGossipSub(p2pCtx, h, gossipOpts...)
// TODO: pubsub.WithPeerScoreInspect(inspect, InspectInterval) to update peerstore scores with gossip scores
}
......
......@@ -13,6 +13,10 @@ import (
"github.com/libp2p/go-libp2p/core/peer"
basichost "github.com/libp2p/go-libp2p/p2p/host/basic"
"github.com/libp2p/go-libp2p/p2p/host/peerstore/pstoreds"
"github.com/libp2p/go-libp2p/p2p/muxer/mplex"
"github.com/libp2p/go-libp2p/p2p/muxer/yamux"
"github.com/libp2p/go-libp2p/p2p/security/noise"
tls "github.com/libp2p/go-libp2p/p2p/security/tls"
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
ma "github.com/multiformats/go-multiaddr"
madns "github.com/multiformats/go-multiaddr-dns"
......@@ -175,3 +179,35 @@ func addrFromIPAndPort(ip net.IP, port uint16) (ma.Multiaddr, error) {
}
return ma.NewMultiaddr(fmt.Sprintf("/%s/%s/tcp/%d", ipScheme, ip.String(), port))
}
func YamuxC() (lconf.MsMuxC, error) {
mtpt, err := lconf.MuxerConstructor(yamux.DefaultTransport)
if err != nil {
return lconf.MsMuxC{}, err
}
return lconf.MsMuxC{MuxC: mtpt, ID: "/yamux/1.0.0"}, nil
}
func MplexC() (lconf.MsMuxC, error) {
mtpt, err := lconf.MuxerConstructor(mplex.DefaultTransport)
if err != nil {
return lconf.MsMuxC{}, err
}
return lconf.MsMuxC{MuxC: mtpt, ID: "/mplex/6.7.0"}, nil
}
func NoiseC() (lconf.MsSecC, error) {
stpt, err := lconf.SecurityConstructor(noise.New)
if err != nil {
return lconf.MsSecC{}, err
}
return lconf.MsSecC{SecC: stpt, ID: noise.ID}, nil
}
func TlsC() (lconf.MsSecC, error) {
stpt, err := lconf.SecurityConstructor(tls.New)
if err != nil {
return lconf.MsSecC{}, err
}
return lconf.MsSecC{SecC: stpt, ID: tls.ID}, nil
}
......@@ -96,13 +96,13 @@ func TestP2PFull(t *testing.T) {
pB, _, err := crypto.GenerateSecp256k1Key(rand.Reader)
require.NoError(t, err, "failed to generate new p2p priv key")
mplexC, err := mplexC()
mplexC, err := MplexC()
require.NoError(t, err)
yamuxC, err := yamuxC()
yamuxC, err := YamuxC()
require.NoError(t, err)
noiseC, err := noiseC()
noiseC, err := NoiseC()
require.NoError(t, err)
tlsC, err := tlsC()
tlsC, err := TlsC()
require.NoError(t, err)
confA := Config{
......@@ -242,13 +242,13 @@ func TestDiscovery(t *testing.T) {
logB := testlog.Logger(t, log.LvlError).New("host", "B")
logC := testlog.Logger(t, log.LvlError).New("host", "C")
mplexC, err := mplexC()
mplexC, err := MplexC()
require.NoError(t, err)
yamuxC, err := yamuxC()
yamuxC, err := YamuxC()
require.NoError(t, err)
noiseC, err := noiseC()
noiseC, err := NoiseC()
require.NoError(t, err)
tlsC, err := tlsC()
tlsC, err := TlsC()
require.NoError(t, err)
discDBA, err := enode.OpenDB("") // "" = memory db
......
......@@ -75,7 +75,7 @@ func (n *NodeP2P) init(resourcesCtx context.Context, rollupCfg *rollup.Config, l
n.host.Network().Notify(NewNetworkNotifier(log, metrics))
// unregister identify-push handler. Only identifying on dial is fine, and more robust against spam
n.host.RemoveStreamHandler(identify.IDDelta)
n.gs, err = NewGossipSub(resourcesCtx, n.host, rollupCfg, metrics)
n.gs, err = NewGossipSub(resourcesCtx, n.host, rollupCfg, setup, metrics)
if err != nil {
return fmt.Errorf("failed to start gossipsub router: %w", err)
}
......
......@@ -4,6 +4,7 @@ import (
"errors"
"fmt"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/metrics"
......@@ -58,3 +59,7 @@ func (p *Prepared) Discovery(log log.Logger, rollupCfg *rollup.Config, tcpPort u
}
return p.LocalNode, p.UDPv5, nil
}
func (p *Prepared) ConfigureGossip(params *pubsub.GossipSubParams) []pubsub.Option {
return nil
}
......@@ -4,16 +4,13 @@ import (
"context"
"crypto/ecdsa"
"errors"
"fmt"
"io"
"math/big"
"github.com/urfave/cli"
"github.com/ethereum-optimism/optimism/op-node/flags"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum-optimism/optimism/op-node/rollup"
)
var SigningDomainBlocksV1 = [32]byte{}
......@@ -79,28 +76,6 @@ func (p *PreparedSigner) SetupSigner(ctx context.Context) (Signer, error) {
return p.Signer, nil
}
// TODO: implement remote signer setup (config to authenticated endpoint)
// and remote signer itself (e.g. a open http client to make signing requests)
type SignerSetup interface {
SetupSigner(ctx context.Context) (Signer, error)
}
// LoadSignerSetup loads a configuration for a Signer to be set up later
func LoadSignerSetup(ctx *cli.Context) (SignerSetup, error) {
key := ctx.GlobalString(flags.SequencerP2PKeyFlag.Name)
if key != "" {
// Mnemonics are bad because they leak *all* keys when they leak.
// Unencrypted keys from file are bad because they are easy to leak (and we are not checking file permissions).
priv, err := crypto.HexToECDSA(key)
if err != nil {
return nil, fmt.Errorf("failed to read batch submitter key: %w", err)
}
return &PreparedSigner{Signer: NewLocalSigner(priv)}, nil
}
// TODO: create remote signer
return nil, nil
}
......@@ -19,7 +19,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/flags"
"github.com/ethereum-optimism/optimism/op-node/node"
"github.com/ethereum-optimism/optimism/op-node/p2p"
p2pcli "github.com/ethereum-optimism/optimism/op-node/p2p/cli"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/driver"
)
......@@ -40,12 +40,12 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) {
return nil, err
}
p2pSignerSetup, err := p2p.LoadSignerSetup(ctx)
p2pSignerSetup, err := p2pcli.LoadSignerSetup(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load p2p signer: %w", err)
}
p2pConfig, err := p2p.NewConfig(ctx)
p2pConfig, err := p2pcli.NewConfig(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load p2p config: %w", err)
}
......
package version
var (
Version = "v0.10.9"
Version = "v0.10.10"
Meta = "dev"
)
......@@ -13,7 +13,7 @@ import (
)
var (
Version = "v0.10.9"
Version = "v0.10.10"
GitCommit = ""
GitDate = ""
)
......
......@@ -4,9 +4,9 @@ go 1.18
require (
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3
github.com/ethereum-optimism/optimism/op-bindings v0.10.9
github.com/ethereum-optimism/optimism/op-node v0.10.9
github.com/ethereum-optimism/optimism/op-service v0.10.9
github.com/ethereum-optimism/optimism/op-bindings v0.10.10
github.com/ethereum-optimism/optimism/op-node v0.10.10
github.com/ethereum-optimism/optimism/op-service v0.10.10
github.com/ethereum/go-ethereum v1.10.26
github.com/stretchr/testify v1.8.1
github.com/urfave/cli v1.22.9
......
......@@ -107,12 +107,12 @@ github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs=
github.com/ethereum-optimism/op-geth v0.0.0-20221216190603-60b51d600468 h1:7KgjBYDji5AKi42eRYI+n8Gs+ZJVilSASL3WBu82c3M=
github.com/ethereum-optimism/op-geth v0.0.0-20221216190603-60b51d600468/go.mod h1:p0Yox74PhYlq1HvijrCBCD9A3cI7rXco7hT6KrQr+rY=
github.com/ethereum-optimism/optimism/op-bindings v0.10.9 h1:FC+M7om33BYBTcdHyZwDX8H/igrZsxtdk+xZAnfIRJg=
github.com/ethereum-optimism/optimism/op-bindings v0.10.9/go.mod h1:9ZSUq/rjlzp3uYyBN4sZmhTc3oZgDVqJ4wrUja7vj6c=
github.com/ethereum-optimism/optimism/op-node v0.10.9 h1:93B8u5hGvXyyESYIMeCGfkZbwFt+gJBx44c1PUvEjrA=
github.com/ethereum-optimism/optimism/op-node v0.10.9/go.mod h1:rtMSVpV5++c/3y3ShyIxaDEm1UmS6iCibY20DFx9HPs=
github.com/ethereum-optimism/optimism/op-service v0.10.9 h1:B6cU47e5MqibqsPzATmNHvjvy04aa8yfgWe5Lv2VQCg=
github.com/ethereum-optimism/optimism/op-service v0.10.9/go.mod h1:wbtHqi1fv00B3agj7a2zdP3OFanEfGZ23zPgGgFCF/c=
github.com/ethereum-optimism/optimism/op-bindings v0.10.10 h1:Khi7m2IyNdB2JeMdW3Y1YibePTiAzuLMHe8hBE2WQzs=
github.com/ethereum-optimism/optimism/op-bindings v0.10.10/go.mod h1:9ZSUq/rjlzp3uYyBN4sZmhTc3oZgDVqJ4wrUja7vj6c=
github.com/ethereum-optimism/optimism/op-node v0.10.10 h1:edmxboiYSIk9n4A3paEF7I0m5qi+v+6FBFkqAfpFU7Y=
github.com/ethereum-optimism/optimism/op-node v0.10.10/go.mod h1:EEcHgMdKiWasJGO5uzspRN2xM1/OB+ehgVgMj4RgPas=
github.com/ethereum-optimism/optimism/op-service v0.10.10 h1:B5mGpATX6zPkDABoh6smCjh6Z5mA2KWh71MD1i6T5ww=
github.com/ethereum-optimism/optimism/op-service v0.10.10/go.mod h1:wbtHqi1fv00B3agj7a2zdP3OFanEfGZ23zPgGgFCF/c=
github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ=
github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
......
......@@ -16,7 +16,7 @@ WORKDIR /opt/foundry
# Only diff from upstream docker image is this clone instead
# of COPY. We select a specific commit to use.
RUN git clone https://github.com/foundry-rs/foundry.git . \
&& git checkout c06b53287dc23c4e5b1b3e57c937a90114bbe166
&& git checkout 2ff99025abade470a795724c10648c800a41025e
RUN source $HOME/.profile && \
cargo build --release && \
......
......@@ -9,7 +9,7 @@ WORKDIR /opt/foundry
# Only diff from upstream docker image is this clone instead
# of COPY. We select a specific commit to use.
RUN git clone https://github.com/foundry-rs/foundry.git . \
&& git checkout f540aa9ebde88dce720140b332412089c2ee85b6
&& git checkout 2ff99025abade470a795724c10648c800a41025e
RUN source $HOME/.profile && cargo build --release \
&& strip /opt/foundry/target/release/forge \
......
......@@ -57,7 +57,7 @@ We work on this repository with a combination of [Hardhat](https://hardhat.org)
1. Install Foundry by following [the instructions located here](https://getfoundry.sh/).
A specific version must be used.
```shell
foundryup -C c06b53287dc23c4e5b1b3e57c937a90114bbe166
foundryup -C 2ff99025abade470a795724c10648c800a41025e
```
2. Install node modules with yarn (v1) and Node.js (16+):
......
......@@ -188,6 +188,23 @@ contract SystemDictator is OwnableUpgradeable {
config.proxyAddressConfig.l1StandardBridgeProxy,
ProxyAdmin.ProxyType.CHUGSPLASH
);
// Upgrade and initialize the SystemConfig so the Sequencer can start up.
config.globalConfig.proxyAdmin.upgradeAndCall(
payable(config.proxyAddressConfig.systemConfigProxy),
address(config.implementationAddressConfig.systemConfigImpl),
abi.encodeCall(
SystemConfig.initialize,
(
config.systemConfigConfig.owner,
config.systemConfigConfig.overhead,
config.systemConfigConfig.scalar,
config.systemConfigConfig.batcherHash,
config.systemConfigConfig.gasLimit,
config.systemConfigConfig.unsafeBlockSigner
)
)
);
}
/**
......@@ -343,23 +360,6 @@ contract SystemDictator is OwnableUpgradeable {
address(config.implementationAddressConfig.l1ERC721BridgeImpl)
);
// Upgrade and initialize the SystemConfig.
config.globalConfig.proxyAdmin.upgradeAndCall(
payable(config.proxyAddressConfig.systemConfigProxy),
address(config.implementationAddressConfig.systemConfigImpl),
abi.encodeCall(
SystemConfig.initialize,
(
config.systemConfigConfig.owner,
config.systemConfigConfig.overhead,
config.systemConfigConfig.scalar,
config.systemConfigConfig.batcherHash,
config.systemConfigConfig.gasLimit,
config.systemConfigConfig.unsafeBlockSigner
)
)
);
// Pause the L1CrossDomainMessenger, chance to check that everything is OK.
L1CrossDomainMessenger(config.proxyAddressConfig.l1CrossDomainMessengerProxy).pause();
}
......
......@@ -18,7 +18,7 @@
"batchInboxAddress": "0xff00000000000000000000000000000000000420",
"batchSenderAddress": "0x7431310e026B69BFC676C0013E12A1A11411EEc9",
"l2OutputOracleSubmissionInterval": 12,
"l2OutputOracleSubmissionInterval": 120,
"l2OutputOracleStartingBlockNumber": 4061224,
"l2OutputOracleStartingTimestamp": 1673550516,
......
{
"finalSystemOwner": "0x858F0751ef8B4067f0d2668C076BDB50a8549fbF",
"controller": "0x2d30335B0b807bBa1682C487BaAFD2Ad6da5D675",
"l1StartingBlockTag": "0x5164297e1cfd0eb3e09f416269cfb04640180e12ff121b5fe815264620e4318d",
"l1ChainID": 5,
"l2ChainID": 999,
"l2BlockTime": 2,
"maxSequencerDrift": 1200,
"sequencerWindowSize": 3600,
"channelTimeout": 120,
"p2pSequencerAddress": "0xf1a4a22a65Ff01EBB23A580146a3ED49D70c8932",
"batchInboxAddress": "0xff00000000000000000000000000000000000999",
"batchSenderAddress": "0xE0Fa1Cc7a0FD5bD82b9A06b08FD6C4563E6635C2",
"l2OutputOracleSubmissionInterval": 20,
"l2OutputOracleStartingTimestamp": 1673246064,
"l2OutputOracleStartingBlockNumber": 1,
"l2OutputOracleProposer": "0xE06d39D4B8DC05E562353F060DED346AC4acC077",
"l2OutputOracleChallenger": "0xE06d39D4B8DC05E562353F060DED346AC4acC077",
"finalizationPeriodSeconds": 2,
"proxyAdminOwner": "0x858F0751ef8B4067f0d2668C076BDB50a8549fbF",
"baseFeeVaultRecipient": "0x858F0751ef8B4067f0d2668C076BDB50a8549fbF",
"l1FeeVaultRecipient": "0x858F0751ef8B4067f0d2668C076BDB50a8549fbF",
"sequencerFeeVaultRecipient": "0x858F0751ef8B4067f0d2668C076BDB50a8549fbF",
"governanceTokenName": "Optimism",
"governanceTokenSymbol": "OP",
"governanceTokenOwner": "0x858F0751ef8B4067f0d2668C076BDB50a8549fbF",
"l2GenesisBlockGasLimit": "0x17D7840",
"l2GenesisBlockBaseFeePerGas": "0x3b9aca00",
"gasPriceOracleOverhead": 2100,
"gasPriceOracleScalar": 1000000,
"eip1559Denominator": 50,
"eip1559Elasticity": 10
}
......@@ -28,6 +28,7 @@ const deployFn: DeployFunction = async (hre) => {
L1StandardBridgeProxyWithSigner,
L1ERC721BridgeProxy,
L1ERC721BridgeProxyWithSigner,
SystemConfigProxy,
] = await getContractsFromArtifacts(hre, [
{
name: 'SystemDictatorProxy',
......@@ -61,6 +62,11 @@ const deployFn: DeployFunction = async (hre) => {
name: 'L1ERC721BridgeProxy',
signerOrProvider: deployer,
},
{
name: 'SystemConfigProxy',
iface: 'SystemConfig',
signerOrProvider: deployer,
},
])
// If we have the key for the controller then we don't need to wait for external txns.
......@@ -251,6 +257,36 @@ const deployFn: DeployFunction = async (hre) => {
getDeploymentAddress(hre, 'Proxy__OVM_L1StandardBridge')
)) === 1
)
// Check the SystemConfig was initialized properly.
await assertContractVariable(
SystemConfigProxy,
'owner',
hre.deployConfig.finalSystemOwner
)
await assertContractVariable(
SystemConfigProxy,
'overhead',
hre.deployConfig.gasPriceOracleOverhead
)
await assertContractVariable(
SystemConfigProxy,
'scalar',
hre.deployConfig.gasPriceOracleScalar
)
await assertContractVariable(
SystemConfigProxy,
'batcherHash',
ethers.utils.hexZeroPad(
hre.deployConfig.batchSenderAddress.toLowerCase(),
32
)
)
await assertContractVariable(
SystemConfigProxy,
'gasLimit',
hre.deployConfig.l2GenesisBlockGasLimit
)
},
})
......
......@@ -30,7 +30,6 @@ const deployFn: DeployFunction = async (hre) => {
OptimismPortal,
OptimismMintableERC20Factory,
L1ERC721Bridge,
SystemConfigProxy,
] = await getContractsFromArtifacts(hre, [
{
name: 'SystemDictatorProxy',
......@@ -78,11 +77,6 @@ const deployFn: DeployFunction = async (hre) => {
iface: 'L1ERC721Bridge',
signerOrProvider: deployer,
},
{
name: 'SystemConfigProxy',
iface: 'SystemConfig',
signerOrProvider: deployer,
},
])
// If we have the key for the controller then we don't need to wait for external txns.
......@@ -286,40 +280,6 @@ const deployFn: DeployFunction = async (hre) => {
'messenger',
L1CrossDomainMessenger.address
)
// Check the SystemConfig was initialized properly.
await assertContractVariable(
SystemConfigProxy,
'owner',
hre.deployConfig.finalSystemOwner
)
await assertContractVariable(
SystemConfigProxy,
'overhead',
hre.deployConfig.gasPriceOracleOverhead
)
await assertContractVariable(
SystemConfigProxy,
'scalar',
hre.deployConfig.gasPriceOracleScalar
)
await assertContractVariable(
SystemConfigProxy,
'batcherHash',
ethers.utils.hexZeroPad(
hre.deployConfig.batchSenderAddress.toLowerCase(),
32
)
)
await assertContractVariable(
SystemConfigProxy,
'gasLimit',
hre.deployConfig.l2GenesisBlockGasLimit
)
},
})
......
{
"address": "0x2732AeA3D6c16A859690F5Eac178709e19A882a9",
"address": "0x6a92fa03ec7c67E18328e1fDe54131B4A48294E4",
"abi": [
{
"inputs": [
......@@ -413,37 +413,37 @@
"type": "function"
}
],
"transactionHash": "0x969c79bb17aa79599a0b79720b91820b97b17732b402af33e1b0bd7d12fca260",
"transactionHash": "0xb937cc4e8ca023312ceea9ac877d8be05168b09203e9fa5f25019d31cbdc900d",
"receipt": {
"to": null,
"from": "0x956a5152D0f498dBA0c5966577bb44262F8F7078",
"contractAddress": "0x2732AeA3D6c16A859690F5Eac178709e19A882a9",
"transactionIndex": 42,
"contractAddress": "0x6a92fa03ec7c67E18328e1fDe54131B4A48294E4",
"transactionIndex": 12,
"gasUsed": "1262021",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000004000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000",
"blockHash": "0x500d2f13e7cd9d486c81a2087e2c9acb8108962aa5fd40af9326736bb0ed6b98",
"transactionHash": "0x969c79bb17aa79599a0b79720b91820b97b17732b402af33e1b0bd7d12fca260",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000400000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"blockHash": "0xdc62f7894590a3c378beb503603f773026c96d1914a25445a19cd9e5d1e7c2f4",
"transactionHash": "0xb937cc4e8ca023312ceea9ac877d8be05168b09203e9fa5f25019d31cbdc900d",
"logs": [
{
"transactionIndex": 42,
"blockNumber": 8299691,
"transactionHash": "0x969c79bb17aa79599a0b79720b91820b97b17732b402af33e1b0bd7d12fca260",
"address": "0x2732AeA3D6c16A859690F5Eac178709e19A882a9",
"transactionIndex": 12,
"blockNumber": 8300998,
"transactionHash": "0xb937cc4e8ca023312ceea9ac877d8be05168b09203e9fa5f25019d31cbdc900d",
"address": "0x6a92fa03ec7c67E18328e1fDe54131B4A48294E4",
"topics": [
"0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"
],
"data": "0x0000000000000000000000000000000000000000000000000000000000000001",
"logIndex": 93,
"blockHash": "0x500d2f13e7cd9d486c81a2087e2c9acb8108962aa5fd40af9326736bb0ed6b98"
"logIndex": 15,
"blockHash": "0xdc62f7894590a3c378beb503603f773026c96d1914a25445a19cd9e5d1e7c2f4"
}
],
"blockNumber": 8299691,
"cumulativeGasUsed": "12589184",
"blockNumber": 8300998,
"cumulativeGasUsed": "7556149",
"status": 1,
"byzantium": true
},
"args": [
12,
120,
2,
0,
0,
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -78,6 +78,12 @@ const config: HardhatUserConfig = {
accounts: [process.env.PRIVATE_KEY_DEPLOYER || ethers.constants.HashZero],
live: true,
},
'internal-devnet': {
chainId: 5,
url: process.env.L1_RPC || '',
accounts: [process.env.PRIVATE_KEY_DEPLOYER || ethers.constants.HashZero],
live: true,
},
},
foundry: {
buildInfo: true,
......
......@@ -9,4 +9,4 @@ import './accounts'
import './check-l2'
import './update-dynamic-oracle-config'
import './wait-for-final-batch'
import './wait-for-final-deposit'
\ No newline at end of file
import './wait-for-final-deposit'
This diff is collapsed.
This diff is collapsed.
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