diff --git a/cannon/docs/README.md b/cannon/docs/README.md index 09c101590aef..336fd547622c 100644 --- a/cannon/docs/README.md +++ b/cannon/docs/README.md @@ -32,9 +32,8 @@ And as it executes each step, it can optionally produce the witness data for the The Cannon CLI is used to load a program into an initial state, transition it N steps quickly without witness generation, and 1 step while producing a witness. -`mipsevm` is backed by the Unicorn emulator, but instrumented for proof generation, -and handles delay-slots by isolating each individual instruction and tracking `nextPC` -to emulate the delayed `PC` changes after delay-slot execution. +`mipsevm` is instrumented for proof generation and handles delay-slots by isolating each individual instruction +and tracking `nextPC` to emulate the delayed `PC` changes after delay-slot execution. ## Witness Data diff --git a/cannon/mipsevm/evm_test.go b/cannon/mipsevm/evm_test.go index 219edb7b3586..de57d40aae10 100644 --- a/cannon/mipsevm/evm_test.go +++ b/cannon/mipsevm/evm_test.go @@ -108,7 +108,7 @@ func TestEVM(t *testing.T) { // TODO: maybe more readable to decode the evmPost state, and do attribute-wise comparison. uniPost := us.state.EncodeWitness() require.Equal(t, hexutil.Bytes(uniPost).String(), hexutil.Bytes(evmPost).String(), - "unicorn produced different state than EVM") + "mipsevm produced different state than EVM") } require.Equal(t, uint32(endAddr), state.PC, "must reach end") // inspect test result @@ -175,7 +175,7 @@ func TestHelloEVM(t *testing.T) { // TODO: maybe more readable to decode the evmPost state, and do attribute-wise comparison. uniPost := us.state.EncodeWitness() require.Equal(t, hexutil.Bytes(uniPost).String(), hexutil.Bytes(evmPost).String(), - "unicorn produced different state than EVM") + "mipsevm produced different state than EVM") } end := time.Now() delta := end.Sub(start) diff --git a/cannon/mipsevm/memory.go b/cannon/mipsevm/memory.go index e78544025dc1..600930bd4dce 100644 --- a/cannon/mipsevm/memory.go +++ b/cannon/mipsevm/memory.go @@ -11,8 +11,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" ) -// Note: 2**12 = 4 KiB, the minimum page-size in Unicorn for mmap -// as well as the Go runtime min phys page size. +// Note: 2**12 = 4 KiB, the min phys page size in the Go runtime. const ( PageAddrSize = 12 PageKeySize = 32 - PageAddrSize diff --git a/cannon/mipsevm/mips.go b/cannon/mipsevm/mips.go index 3413d7c02aeb..9752d53e8ec9 100644 --- a/cannon/mipsevm/mips.go +++ b/cannon/mipsevm/mips.go @@ -56,15 +56,6 @@ func (m *InstrumentedState) handleSyscall() error { v0 = a0 //fmt.Printf("mmap hint 0x%x size 0x%x\n", v0, sz) } - // Go does this thing where it first gets memory with PROT_NONE, - // and then mmaps with a hint with prot=3 (PROT_READ|WRITE). - // We can ignore the NONE case, to avoid duplicate/overlapping mmap calls to unicorn. - //prot := a2 - //if prot != 0 { - // if err := mu.MemMap(uint64(v0), uint64(sz)); err != nil { - // log.Fatalf("mmap fail: %v", err) - // } - //} case 4045: // brk v0 = 0x40000000 case 4120: // clone (not supported) diff --git a/endpoint-monitor/Dockerfile b/endpoint-monitor/Dockerfile index 61802123a2ed..bb35606ab3f8 100644 --- a/endpoint-monitor/Dockerfile +++ b/endpoint-monitor/Dockerfile @@ -1,18 +1,28 @@ -FROM golang:1.18.0-alpine3.15 as builder +FROM golang:1.19.9-alpine3.16 as builder -COPY ./endpoint-monitor /app - -WORKDIR /app RUN apk --no-cache add make jq bash git alpine-sdk + +COPY ./endpoint-monitor /app/endpoint-monitor +COPY ./op-service /app/op-service +COPY ./op-node /app/op-node +COPY ./go.mod /app/go.mod +COPY ./go.sum /app/go.sum + +COPY ./.git /app/.git + +WORKDIR /app/endpoint-monitor + +RUN go mod download + RUN make build -FROM alpine:3.15 +FROM alpine:3.16 RUN apk --no-cache add ca-certificates RUN addgroup -S app && adduser -S app -G app USER app WORKDIR /app -COPY --from=builder /app/bin/endpoint-monitor /app +COPY --from=builder /app/endpoint-monitor/bin/endpoint-monitor /app ENTRYPOINT ["/app/endpoint-monitor"] diff --git a/endpoint-monitor/README.md b/endpoint-monitor/README.md index 8e0b21969fe8..be02148f3c03 100644 --- a/endpoint-monitor/README.md +++ b/endpoint-monitor/README.md @@ -4,7 +4,7 @@ The endpoint-monitor runs websocket checks on edge-proxyd endpoints and downstre ## Setup -Install go1.18 +Install go1.19 ```bash make build diff --git a/endpoint-monitor/cmd/main.go b/endpoint-monitor/cmd/main.go index e6e01de4683b..b31ac9359c6e 100644 --- a/endpoint-monitor/cmd/main.go +++ b/endpoint-monitor/cmd/main.go @@ -6,7 +6,7 @@ import ( oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum/go-ethereum/log" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" endpointMonitor "github.com/ethereum-optimism/optimism/endpoint-monitor" ) diff --git a/endpoint-monitor/config.go b/endpoint-monitor/config.go index f741c72db78c..77fe6fd96ee4 100644 --- a/endpoint-monitor/config.go +++ b/endpoint-monitor/config.go @@ -9,7 +9,7 @@ import ( opservice "github.com/ethereum-optimism/optimism/op-service" oplog "github.com/ethereum-optimism/optimism/op-service/log" opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) type ProviderConfig struct { @@ -24,24 +24,27 @@ const ( ) func CLIFlags(envPrefix string) []cli.Flag { + prefixEnvVars := func(name string) []string { + return opservice.PrefixEnvVar(envPrefix, name) + } flags := []cli.Flag{ - cli.StringSliceFlag{ + &cli.StringSliceFlag{ Name: ProvidersFlagName, Usage: "List of providers", Required: true, - EnvVar: opservice.PrefixEnvVar(envPrefix, "PROVIDERS"), + EnvVars: prefixEnvVars("PROVIDERS"), }, - cli.DurationFlag{ - Name: CheckIntervalFlagName, - Usage: "Check interval duration", - Value: 5 * time.Minute, - EnvVar: opservice.PrefixEnvVar(envPrefix, "CHECK_INTERVAL"), + &cli.DurationFlag{ + Name: CheckIntervalFlagName, + Usage: "Check interval duration", + Value: 5 * time.Minute, + EnvVars: prefixEnvVars("CHECK_INTERVAL"), }, - cli.DurationFlag{ - Name: CheckDurationFlagName, - Usage: "Check duration", - Value: 4 * time.Minute, - EnvVar: opservice.PrefixEnvVar(envPrefix, "CHECK_DURATION"), + &cli.DurationFlag{ + Name: CheckDurationFlagName, + Usage: "Check duration", + Value: 4 * time.Minute, + EnvVars: prefixEnvVars("CHECK_DURATION"), }, } flags = append(flags, opmetrics.CLIFlags(envPrefix)...) @@ -73,9 +76,9 @@ func (c Config) Check() error { func NewConfig(ctx *cli.Context) Config { return Config{ - Providers: ctx.GlobalStringSlice(ProvidersFlagName), - CheckInterval: ctx.GlobalDuration(CheckIntervalFlagName), - CheckDuration: ctx.GlobalDuration(CheckDurationFlagName), + Providers: ctx.StringSlice(ProvidersFlagName), + CheckInterval: ctx.Duration(CheckIntervalFlagName), + CheckDuration: ctx.Duration(CheckDurationFlagName), LogConfig: oplog.ReadCLIConfig(ctx), MetricsConfig: opmetrics.ReadCLIConfig(ctx), } diff --git a/endpoint-monitor/endpoint_monitor.go b/endpoint-monitor/endpoint_monitor.go index 6f1aa63ebcb1..e7d1e669d2d8 100644 --- a/endpoint-monitor/endpoint_monitor.go +++ b/endpoint-monitor/endpoint_monitor.go @@ -11,10 +11,10 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" - "github.com/ethereum-optimism/optimism/l2geth/core/types" - "github.com/ethereum-optimism/optimism/l2geth/ethclient" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" ) var ( diff --git a/endpoint-monitor/go.mod b/endpoint-monitor/go.mod deleted file mode 100644 index 56be45bce299..000000000000 --- a/endpoint-monitor/go.mod +++ /dev/null @@ -1,42 +0,0 @@ -module github.com/ethereum-optimism/optimism/endpoint-monitor - -go 1.18 - -require ( - github.com/ethereum-optimism/optimism/l2geth v0.0.0-20220923210602-7121648c1f26 - github.com/ethereum-optimism/optimism/op-service v0.8.8 - github.com/ethereum/go-ethereum v1.10.26 - github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.13.0 - github.com/urfave/cli v1.22.9 -) - -replace github.com/ethereum-optimism/optimism/l2geth v0.0.0-20220923210602-7121648c1f26 => github.com/ethereum-optimism/optimism-legacy/l2geth v0.0.0-20220923210602-7121648c1f26 - -require ( - github.com/VictoriaMetrics/fastcache v1.9.0 // indirect - github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/btcsuite/btcd v0.22.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/deckarep/golang-set v1.8.0 // indirect - github.com/elastic/gosigar v0.12.0 // indirect - github.com/go-stack/stack v1.8.1 // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.37.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect - github.com/rs/cors v1.8.2 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect - github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect - golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect - golang.org/x/sys v0.0.0-20220701225701-179beb0bd1a1 // indirect - golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect - google.golang.org/protobuf v1.28.1 // indirect - gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect -) diff --git a/endpoint-monitor/go.sum b/endpoint-monitor/go.sum deleted file mode 100644 index 6d6960a835be..000000000000 --- a/endpoint-monitor/go.sum +++ /dev/null @@ -1,1063 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= -github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= -github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= -github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= -github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= -github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= -github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= -github.com/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= -github.com/VictoriaMetrics/fastcache v1.9.0/go.mod h1:otoTS3xu+6IzF/qByjqzjp3rTuzM3Qf0ScU1UTj97iU= -github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= -github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A= -github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= -github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= -github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.42.6/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo= -github.com/aws/aws-sdk-go-v2/config v1.1.1/go.mod h1:0XsVy9lBI/BCXm+2Tuvt39YmdHwS5unDQmxZOYe8F5Y= -github.com/aws/aws-sdk-go-v2/credentials v1.1.1/go.mod h1:mM2iIjwl7LULWtS6JCACyInboHirisUUdkBPoTHMOUo= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2/go.mod h1:3hGg3PpiEjHnrkrlasTfxFqUsZ2GCk/fMUn4CbKgSkM= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2/go.mod h1:45MfaXZ0cNbeuT0KQ1XJylq8A6+OpVV2E5kvY/Kq+u8= -github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7NkwbjlijluLsrIbu/iyl35RO4= -github.com/aws/aws-sdk-go-v2/service/sso v1.1.1/go.mod h1:SuZJxklHxLAXgLTc1iFXbEWkXs7QRTQpCLGaKIprQW0= -github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM= -github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= -github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= -github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= -github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= -github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ= -github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= -github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= -github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= -github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= -github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= -github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.10+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= -github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= -github.com/elastic/gosigar v0.12.0 h1:AsdhYCJlTudhfOYQyFNgx+fIVTfrDO0V1ST0vHgiapU= -github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum-optimism/optimism-legacy/l2geth v0.0.0-20220923210602-7121648c1f26 h1:znJULRia1IjB0OLUvy0ayXcZHXPSY10B1xEG7xKOpuk= -github.com/ethereum-optimism/optimism-legacy/l2geth v0.0.0-20220923210602-7121648c1f26/go.mod h1:Oj5A6Qs/Ao1SP17i3uKroyhz49q/ehagSXRAlvwaI5Y= -github.com/ethereum-optimism/optimism/op-service v0.8.8 h1:k5E78Zr2cGU0SwjoHpFXuC1eyfXhu3oKEOnDDaFi57I= -github.com/ethereum-optimism/optimism/op-service v0.8.8/go.mod h1:K0uybOhICTc2yfhrRj0cD1m7aPkOf5C9e6bUmvf4rGA= -github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= -github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y= -github.com/ethereum/go-ethereum v1.10.26 h1:i/7d9RBBwiXCEuyduBQzJw/mKmnvzsN14jqBmytw72s= -github.com/ethereum/go-ethereum v1.10.26/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= -github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= -github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= -github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-resty/resty/v2 v2.4.0/go.mod h1:B88+xCTEwvfD94NOuE6GS1wMlnoKNY8eEiNizfNwOwA= -github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= -github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -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= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= -github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= -github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo= -github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= -github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/flux v0.65.1/go.mod h1:J754/zds0vvpfwuq7Gc2wRdVwEodfpCFM7mYlOw2LqY= -github.com/influxdata/influxdb v1.8.3/go.mod h1:JugdFhsvvI8gadxOI6noqNeeBHvWNTbfYGtiAn+2jhI= -github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/influxdata/influxql v1.1.1-0.20200828144457-65d3ef77d385/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk= -github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE= -github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= -github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= -github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19ybifQhZoQNF5D8= -github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= -github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= -github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= -github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jarcoal/httpmock v1.0.8/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= -github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= -github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= -github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= -github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -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.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= -github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= -github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= -github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= -github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= -github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= -github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= -github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= -github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= -github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= -github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= -github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d/go.mod h1:97vT0Rym0wCnK4B++hNA3nCetr0Mh1KXaVxzSt1arjg= -github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= -github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= -github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= -github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= -github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= -github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= -github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.9 h1:cv3/KhXGBGjEXLC4bH0sLuJ9BewaAbpk5oyMOveu4pw= -github.com/urfave/cli v1.22.9/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220701225701-179beb0bd1a1 h1:+Lm8wRwJpsVpTHuM4tHTwgxjPzv/bjxsHt2cW5EY7XU= -golang.org/x/sys v0.0.0-20220701225701-179beb0bd1a1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= -gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= -gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/go.mod b/go.mod index 524e5803ddd7..00ea82efb8a2 100644 --- a/go.mod +++ b/go.mod @@ -26,11 +26,11 @@ require ( github.com/multiformats/go-multiaddr v0.8.0 github.com/multiformats/go-multiaddr-dns v0.3.1 github.com/olekukonko/tablewriter v0.0.5 + github.com/pkg/errors v0.9.1 github.com/pkg/profile v1.7.0 github.com/prometheus/client_golang v1.14.0 github.com/stretchr/testify v1.8.1 - github.com/urfave/cli v1.22.9 - github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa + github.com/urfave/cli/v2 v2.25.7 golang.org/x/crypto v0.6.0 golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb golang.org/x/sync v0.1.0 @@ -134,7 +134,6 @@ require ( github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.39.0 // indirect diff --git a/go.sum b/go.sum index 2f35293bc469..bbf384ec4639 100644 --- a/go.sum +++ b/go.sum @@ -10,7 +10,7 @@ git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGy github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= @@ -681,10 +681,8 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.9 h1:cv3/KhXGBGjEXLC4bH0sLuJ9BewaAbpk5oyMOveu4pw= -github.com/urfave/cli v1.22.9/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= +github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= +github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= diff --git a/op-batcher/batcher/batch_submitter.go b/op-batcher/batcher/batch_submitter.go index 2489188b23c7..5193c4f2ac38 100644 --- a/op-batcher/batcher/batch_submitter.go +++ b/op-batcher/batcher/batch_submitter.go @@ -6,7 +6,7 @@ import ( _ "net/http/pprof" gethrpc "github.com/ethereum/go-ethereum/rpc" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/op-batcher/flags" "github.com/ethereum-optimism/optimism/op-batcher/metrics" diff --git a/op-batcher/batcher/config.go b/op-batcher/batcher/config.go index ecd241b3fd87..3ac53bcf5d7b 100644 --- a/op-batcher/batcher/config.go +++ b/op-batcher/batcher/config.go @@ -5,7 +5,7 @@ import ( "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/op-batcher/compressor" "github.com/ethereum-optimism/optimism/op-batcher/flags" @@ -118,17 +118,17 @@ func (c CLIConfig) Check() error { func NewConfig(ctx *cli.Context) CLIConfig { return CLIConfig{ /* Required Flags */ - L1EthRpc: ctx.GlobalString(flags.L1EthRpcFlag.Name), - L2EthRpc: ctx.GlobalString(flags.L2EthRpcFlag.Name), - RollupRpc: ctx.GlobalString(flags.RollupRpcFlag.Name), - SubSafetyMargin: ctx.GlobalUint64(flags.SubSafetyMarginFlag.Name), - PollInterval: ctx.GlobalDuration(flags.PollIntervalFlag.Name), + L1EthRpc: ctx.String(flags.L1EthRpcFlag.Name), + L2EthRpc: ctx.String(flags.L2EthRpcFlag.Name), + RollupRpc: ctx.String(flags.RollupRpcFlag.Name), + SubSafetyMargin: ctx.Uint64(flags.SubSafetyMarginFlag.Name), + PollInterval: ctx.Duration(flags.PollIntervalFlag.Name), /* Optional Flags */ - MaxPendingTransactions: ctx.GlobalUint64(flags.MaxPendingTransactionsFlag.Name), - MaxChannelDuration: ctx.GlobalUint64(flags.MaxChannelDurationFlag.Name), - MaxL1TxSize: ctx.GlobalUint64(flags.MaxL1TxSizeBytesFlag.Name), - Stopped: ctx.GlobalBool(flags.StoppedFlag.Name), + MaxPendingTransactions: ctx.Uint64(flags.MaxPendingTransactionsFlag.Name), + MaxChannelDuration: ctx.Uint64(flags.MaxChannelDurationFlag.Name), + MaxL1TxSize: ctx.Uint64(flags.MaxL1TxSizeBytesFlag.Name), + Stopped: ctx.Bool(flags.StoppedFlag.Name), TxMgrConfig: txmgr.ReadCLIConfig(ctx), RPCConfig: rpc.ReadCLIConfig(ctx), LogConfig: oplog.ReadCLIConfig(ctx), diff --git a/op-batcher/cmd/doc/cmd.go b/op-batcher/cmd/doc/cmd.go index f5c8a6f5833c..92eb1de7aec4 100644 --- a/op-batcher/cmd/doc/cmd.go +++ b/op-batcher/cmd/doc/cmd.go @@ -8,7 +8,7 @@ import ( "github.com/ethereum-optimism/optimism/op-batcher/metrics" "github.com/olekukonko/tablewriter" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) var Subcommands = cli.Commands{ @@ -16,7 +16,7 @@ var Subcommands = cli.Commands{ Name: "metrics", Usage: "Dumps a list of supported metrics to stdout", Flags: []cli.Flag{ - cli.StringFlag{ + &cli.StringFlag{ Name: "format", Value: "markdown", Usage: "Output format (json|markdown)", diff --git a/op-batcher/cmd/main.go b/op-batcher/cmd/main.go index 69b5a494ac81..53ef513fbb60 100644 --- a/op-batcher/cmd/main.go +++ b/op-batcher/cmd/main.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/op-batcher/batcher" "github.com/ethereum-optimism/optimism/op-batcher/cmd/doc" @@ -29,7 +29,7 @@ func main() { app.Usage = "Batch Submitter Service" app.Description = "Service for generating and submitting L2 tx batches to L1" app.Action = curryMain(Version) - app.Commands = []cli.Command{ + app.Commands = []*cli.Command{ { Name: "doc", Subcommands: doc.Subcommands, diff --git a/op-batcher/compressor/cli.go b/op-batcher/compressor/cli.go index 177b2a013213..5da3cd164310 100644 --- a/op-batcher/compressor/cli.go +++ b/op-batcher/compressor/cli.go @@ -4,7 +4,7 @@ import ( "strings" opservice "github.com/ethereum-optimism/optimism/op-service" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) const ( @@ -16,29 +16,29 @@ const ( func CLIFlags(envPrefix string) []cli.Flag { return []cli.Flag{ - cli.Uint64Flag{ - Name: TargetL1TxSizeBytesFlagName, - Usage: "The target size of a batch tx submitted to L1.", - Value: 100_000, - EnvVar: opservice.PrefixEnvVar(envPrefix, "TARGET_L1_TX_SIZE_BYTES"), + &cli.Uint64Flag{ + Name: TargetL1TxSizeBytesFlagName, + Usage: "The target size of a batch tx submitted to L1.", + Value: 100_000, + EnvVars: opservice.PrefixEnvVar(envPrefix, "TARGET_L1_TX_SIZE_BYTES"), }, - cli.IntFlag{ - Name: TargetNumFramesFlagName, - Usage: "The target number of frames to create per channel", - Value: 1, - EnvVar: opservice.PrefixEnvVar(envPrefix, "TARGET_NUM_FRAMES"), + &cli.IntFlag{ + Name: TargetNumFramesFlagName, + Usage: "The target number of frames to create per channel", + Value: 1, + EnvVars: opservice.PrefixEnvVar(envPrefix, "TARGET_NUM_FRAMES"), }, - cli.Float64Flag{ - Name: ApproxComprRatioFlagName, - Usage: "The approximate compression ratio (<= 1.0)", - Value: 0.4, - EnvVar: opservice.PrefixEnvVar(envPrefix, "APPROX_COMPR_RATIO"), + &cli.Float64Flag{ + Name: ApproxComprRatioFlagName, + Usage: "The approximate compression ratio (<= 1.0)", + Value: 0.4, + EnvVars: opservice.PrefixEnvVar(envPrefix, "APPROX_COMPR_RATIO"), }, - cli.StringFlag{ - Name: KindFlagName, - Usage: "The type of compressor. Valid options: " + strings.Join(KindKeys, ", "), - EnvVar: opservice.PrefixEnvVar(envPrefix, "COMPRESSOR"), - Value: RatioKind, + &cli.StringFlag{ + Name: KindFlagName, + Usage: "The type of compressor. Valid options: " + strings.Join(KindKeys, ", "), + EnvVars: opservice.PrefixEnvVar(envPrefix, "COMPRESSOR"), + Value: RatioKind, }, } } @@ -70,9 +70,9 @@ func (c *CLIConfig) Config() Config { func ReadCLIConfig(ctx *cli.Context) CLIConfig { return CLIConfig{ - Kind: ctx.GlobalString(KindFlagName), - TargetL1TxSizeBytes: ctx.GlobalUint64(TargetL1TxSizeBytesFlagName), - TargetNumFrames: ctx.GlobalInt(TargetNumFramesFlagName), - ApproxComprRatio: ctx.GlobalFloat64(ApproxComprRatioFlagName), + Kind: ctx.String(KindFlagName), + TargetL1TxSizeBytes: ctx.Uint64(TargetL1TxSizeBytesFlagName), + TargetNumFrames: ctx.Int(TargetNumFramesFlagName), + ApproxComprRatio: ctx.Float64(ApproxComprRatioFlagName), } } diff --git a/op-batcher/flags/flags.go b/op-batcher/flags/flags.go index c82e26d096d0..6beb8d01ab9e 100644 --- a/op-batcher/flags/flags.go +++ b/op-batcher/flags/flags.go @@ -4,7 +4,7 @@ import ( "fmt" "time" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/op-batcher/compressor" "github.com/ethereum-optimism/optimism/op-batcher/rpc" @@ -18,60 +18,64 @@ import ( const EnvVarPrefix = "OP_BATCHER" +func prefixEnvVars(name string) []string { + return opservice.PrefixEnvVar(EnvVarPrefix, name) +} + var ( // Required flags - L1EthRpcFlag = cli.StringFlag{ - Name: "l1-eth-rpc", - Usage: "HTTP provider URL for L1", - EnvVar: opservice.PrefixEnvVar(EnvVarPrefix, "L1_ETH_RPC"), + L1EthRpcFlag = &cli.StringFlag{ + Name: "l1-eth-rpc", + Usage: "HTTP provider URL for L1", + EnvVars: prefixEnvVars("L1_ETH_RPC"), } - L2EthRpcFlag = cli.StringFlag{ - Name: "l2-eth-rpc", - Usage: "HTTP provider URL for L2 execution engine", - EnvVar: opservice.PrefixEnvVar(EnvVarPrefix, "L2_ETH_RPC"), + L2EthRpcFlag = &cli.StringFlag{ + Name: "l2-eth-rpc", + Usage: "HTTP provider URL for L2 execution engine", + EnvVars: prefixEnvVars("L2_ETH_RPC"), } - RollupRpcFlag = cli.StringFlag{ - Name: "rollup-rpc", - Usage: "HTTP provider URL for Rollup node", - EnvVar: opservice.PrefixEnvVar(EnvVarPrefix, "ROLLUP_RPC"), + RollupRpcFlag = &cli.StringFlag{ + Name: "rollup-rpc", + Usage: "HTTP provider URL for Rollup node", + EnvVars: prefixEnvVars("ROLLUP_RPC"), } // Optional flags - SubSafetyMarginFlag = cli.Uint64Flag{ + SubSafetyMarginFlag = &cli.Uint64Flag{ Name: "sub-safety-margin", Usage: "The batcher tx submission safety margin (in #L1-blocks) to subtract " + "from a channel's timeout and sequencing window, to guarantee safe inclusion " + "of a channel on L1.", - Value: 10, - EnvVar: opservice.PrefixEnvVar(EnvVarPrefix, "SUB_SAFETY_MARGIN"), + Value: 10, + EnvVars: prefixEnvVars("SUB_SAFETY_MARGIN"), } - PollIntervalFlag = cli.DurationFlag{ - Name: "poll-interval", - Usage: "How frequently to poll L2 for new blocks", - Value: 6 * time.Second, - EnvVar: opservice.PrefixEnvVar(EnvVarPrefix, "POLL_INTERVAL"), + PollIntervalFlag = &cli.DurationFlag{ + Name: "poll-interval", + Usage: "How frequently to poll L2 for new blocks", + Value: 6 * time.Second, + EnvVars: prefixEnvVars("POLL_INTERVAL"), } - MaxPendingTransactionsFlag = cli.Uint64Flag{ - Name: "max-pending-tx", - Usage: "The maximum number of pending transactions. 0 for no limit.", - Value: 1, - EnvVar: opservice.PrefixEnvVar(EnvVarPrefix, "MAX_PENDING_TX"), + MaxPendingTransactionsFlag = &cli.Uint64Flag{ + Name: "max-pending-tx", + Usage: "The maximum number of pending transactions. 0 for no limit.", + Value: 1, + EnvVars: prefixEnvVars("MAX_PENDING_TX"), } - MaxChannelDurationFlag = cli.Uint64Flag{ - Name: "max-channel-duration", - Usage: "The maximum duration of L1-blocks to keep a channel open. 0 to disable.", - Value: 0, - EnvVar: opservice.PrefixEnvVar(EnvVarPrefix, "MAX_CHANNEL_DURATION"), + MaxChannelDurationFlag = &cli.Uint64Flag{ + Name: "max-channel-duration", + Usage: "The maximum duration of L1-blocks to keep a channel open. 0 to disable.", + Value: 0, + EnvVars: prefixEnvVars("MAX_CHANNEL_DURATION"), } - MaxL1TxSizeBytesFlag = cli.Uint64Flag{ - Name: "max-l1-tx-size-bytes", - Usage: "The maximum size of a batch tx submitted to L1.", - Value: 120_000, - EnvVar: opservice.PrefixEnvVar(EnvVarPrefix, "MAX_L1_TX_SIZE_BYTES"), + MaxL1TxSizeBytesFlag = &cli.Uint64Flag{ + Name: "max-l1-tx-size-bytes", + Usage: "The maximum size of a batch tx submitted to L1.", + Value: 120_000, + EnvVars: prefixEnvVars("MAX_L1_TX_SIZE_BYTES"), } - StoppedFlag = cli.BoolFlag{ - Name: "stopped", - Usage: "Initialize the batcher in a stopped state. The batcher can be started using the admin_startBatcher RPC", - EnvVar: opservice.PrefixEnvVar(EnvVarPrefix, "STOPPED"), + StoppedFlag = &cli.BoolFlag{ + Name: "stopped", + Usage: "Initialize the batcher in a stopped state. The batcher can be started using the admin_startBatcher RPC", + EnvVars: prefixEnvVars("STOPPED"), } // Legacy Flags SequencerHDPathFlag = txmgr.SequencerHDPathFlag @@ -110,8 +114,8 @@ var Flags []cli.Flag func CheckRequired(ctx *cli.Context) error { for _, f := range requiredFlags { - if !ctx.GlobalIsSet(f.GetName()) { - return fmt.Errorf("flag %s is required", f.GetName()) + if !ctx.IsSet(f.Names()[0]) { + return fmt.Errorf("flag %s is required", f.Names()[0]) } } return nil diff --git a/op-batcher/rpc/config.go b/op-batcher/rpc/config.go index 2dc9f1c0141f..3aafdb649819 100644 --- a/op-batcher/rpc/config.go +++ b/op-batcher/rpc/config.go @@ -1,7 +1,7 @@ package rpc import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" opservice "github.com/ethereum-optimism/optimism/op-service" oprpc "github.com/ethereum-optimism/optimism/op-service/rpc" @@ -13,10 +13,10 @@ const ( func CLIFlags(envPrefix string) []cli.Flag { return []cli.Flag{ - cli.BoolFlag{ - Name: EnableAdminFlagName, - Usage: "Enable the admin API (experimental)", - EnvVar: opservice.PrefixEnvVar(envPrefix, "RPC_ENABLE_ADMIN"), + &cli.BoolFlag{ + Name: EnableAdminFlagName, + Usage: "Enable the admin API (experimental)", + EnvVars: opservice.PrefixEnvVar(envPrefix, "RPC_ENABLE_ADMIN"), }, } } @@ -29,6 +29,6 @@ type CLIConfig struct { func ReadCLIConfig(ctx *cli.Context) CLIConfig { return CLIConfig{ CLIConfig: oprpc.ReadCLIConfig(ctx), - EnableAdmin: ctx.GlobalBool(EnableAdminFlagName), + EnableAdmin: ctx.Bool(EnableAdminFlagName), } } diff --git a/op-bindings/bindings/l1crossdomainmessenger.go b/op-bindings/bindings/l1crossdomainmessenger.go index c5c48aabcc6c..74e9cbf3356c 100644 --- a/op-bindings/bindings/l1crossdomainmessenger.go +++ b/op-bindings/bindings/l1crossdomainmessenger.go @@ -31,7 +31,7 @@ var ( // L1CrossDomainMessengerMetaData contains all meta data concerning the L1CrossDomainMessenger contract. var L1CrossDomainMessengerMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"contractOptimismPortal\",\"name\":\"_portal\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\"}],\"name\":\"FailedRelayedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\"}],\"name\":\"RelayedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"messageNonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"name\":\"SentMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"SentMessageExtension1\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MESSAGE_VERSION\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_CALLDATA_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"OTHER_MESSENGER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PORTAL\",\"outputs\":[{\"internalType\":\"contractOptimismPortal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAY_CALL_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAY_CONSTANT_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAY_GAS_CHECK_BUFFER\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAY_RESERVED_GAS\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"name\":\"baseGas\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"failedMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messageNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"}],\"name\":\"relayMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"name\":\"sendMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"successfulMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"xDomainMessageSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b50604051620023183803806200231883398101604081905262000035916200025c565b734200000000000000000000000000000000000007608052600160a052600460c052600060e0526001600160a01b03811661010052620000746200007b565b506200028e565b600054600160a81b900460ff1615808015620000a457506000546001600160a01b90910460ff16105b80620000db5750620000c130620001c860201b620012f11760201c565b158015620000db5750600054600160a01b900460ff166001145b620001445760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff60a01b1916600160a01b179055801562000172576000805460ff60a81b1916600160a81b1790555b6200017c620001d7565b8015620001c5576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6001600160a01b03163b151590565b600054600160a81b900460ff16620002465760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200013b565b60cc80546001600160a01b03191661dead179055565b6000602082840312156200026f57600080fd5b81516001600160a01b03811681146200028757600080fd5b9392505050565b60805160a05160c05160e0516101005161201b620002fd600039600081816101a30152818161134a0152818161162c0152818161168d0152611759015260006106c40152600061069b015260006106720152600081816102dd0152818161040c0152611656015261201b6000f3fe6080604052600436106101445760003560e01c80636e296e45116100c0578063a4e7f8bd11610074578063b28ade2511610059578063b28ade251461036f578063d764ad0b1461038f578063ecc70428146103a257600080fd5b8063a4e7f8bd146102ff578063b1b1b2091461033f57600080fd5b806383a74074116100a557806383a74074146102b45780638cbeeef21461023c5780639fce812c146102cb57600080fd5b80636e296e451461028a5780638129fc1c1461029f57600080fd5b80633dbb202b116101175780634c1d6a69116100fc5780634c1d6a691461023c57806354fd4d50146102525780635644cfdf1461027457600080fd5b80633dbb202b146101ff5780633f827a5a1461021457600080fd5b8063028f85f7146101495780630c5684981461017c5780630ff754ea146101915780632828d7e8146101ea575b600080fd5b34801561015557600080fd5b5061015e601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061015e603f81565b34801561019d57600080fd5b506101c57f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610173565b3480156101f657600080fd5b5061015e604081565b61021261020d3660046119a1565b610407565b005b34801561022057600080fd5b50610229600181565b60405161ffff9091168152602001610173565b34801561024857600080fd5b5061015e619c4081565b34801561025e57600080fd5b5061026761066b565b6040516101739190611a82565b34801561028057600080fd5b5061015e61138881565b34801561029657600080fd5b506101c561070e565b3480156102ab57600080fd5b506102126107fa565b3480156102c057600080fd5b5061015e62030d4081565b3480156102d757600080fd5b506101c57f000000000000000000000000000000000000000000000000000000000000000081565b34801561030b57600080fd5b5061032f61031a366004611a9c565b60ce6020526000908152604090205460ff1681565b6040519015158152602001610173565b34801561034b57600080fd5b5061032f61035a366004611a9c565b60cb6020526000908152604090205460ff1681565b34801561037b57600080fd5b5061015e61038a366004611ab5565b6109f7565b61021261039d366004611b09565b610a65565b3480156103ae57600080fd5b506103f960cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b604051908152602001610173565b6105407f00000000000000000000000000000000000000000000000000000000000000006104368585856109f7565b347fd764ad0b000000000000000000000000000000000000000000000000000000006104a260cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016104be9796959493929190611bd8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261130d565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3385856105c560cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516105d7959493929190611c37565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60606106967f00000000000000000000000000000000000000000000000000000000000000006113c2565b6106bf7f00000000000000000000000000000000000000000000000000000000000000006113c2565b6106e87f00000000000000000000000000000000000000000000000000000000000000006113c2565b6040516020016106fa93929190611c85565b604051602081830303815290604052905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016107dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000547501000000000000000000000000000000000000000000900460ff1615808015610845575060005460017401000000000000000000000000000000000000000090910460ff16105b806108775750303b158015610877575060005474010000000000000000000000000000000000000000900460ff166001145b610903576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107d4565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055801561098957600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b6109916114f7565b80156109f457600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6000611388619c4080603f610a13604063ffffffff8816611d2a565b610a1d9190611d89565b610a28601088611d2a565b610a359062030d40611db0565b610a3f9190611db0565b610a499190611db0565b610a539190611db0565b610a5d9190611db0565b949350505050565b60f087901c60028110610b20576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016107d4565b8061ffff16600003610c15576000610b71878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506115d0915050565b600081815260cb602052604090205490915060ff1615610c13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016107d4565b505b6000610c5b898989898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115ef92505050565b9050610c65611612565b15610c9d57853414610c7957610c79611ddc565b600081815260ce602052604090205460ff1615610c9857610c98611ddc565b610def565b3415610d51576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016107d4565b600081815260ce602052604090205460ff16610def576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016107d4565b610df887611736565b15610eab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016107d4565b600081815260cb602052604090205460ff1615610f4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016107d4565b610f6b85610f5c611388619c40611db0565b67ffffffffffffffff166117ad565b1580610f91575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b156110aa57600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016110a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016107d4565b50506112e3565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a16179055600061113b88619c405a6110fe9190611e0b565b8988888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117cb92505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055905080156111d257600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26112df565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016112df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016107d4565b5050505b50505050505050565b905090565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e9e05c4290849061138a908890839089906000908990600401611e22565b6000604051808303818588803b1580156113a357600080fd5b505af11580156113b7573d6000803e3d6000fd5b505050505050505050565b60608160000361140557505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561142f578061141981611e7a565b91506114289050600a83611eb2565b9150611409565b60008167ffffffffffffffff81111561144a5761144a611ec6565b6040519080825280601f01601f191660200182016040528015611474576020820181803683370190505b5090505b8415610a5d57611489600183611e0b565b9150611496600a86611ef5565b6114a1906030611f09565b60f81b8183815181106114b6576114b6611f21565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506114f0600a86611eb2565b9450611478565b6000547501000000000000000000000000000000000000000000900460ff166115a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107d4565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055565b60006115de858585856117e5565b805190602001209050949350505050565b60006115ff87878787878761187e565b8051906020012090509695505050505050565b60003373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156112ec57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639bf62d826040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171a9190611f50565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff82163014806117a757507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b600080600080845160208601878a8af19695505050505050565b6060848484846040516024016117fe9493929190611f6d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b606086868686868660405160240161189b96959493929190611fb7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146109f457600080fd5b60008083601f84011261195157600080fd5b50813567ffffffffffffffff81111561196957600080fd5b60208301915083602082850101111561198157600080fd5b9250929050565b803563ffffffff8116811461199c57600080fd5b919050565b600080600080606085870312156119b757600080fd5b84356119c28161191d565b9350602085013567ffffffffffffffff8111156119de57600080fd5b6119ea8782880161193f565b90945092506119fd905060408601611988565b905092959194509250565b60005b83811015611a23578181015183820152602001611a0b565b83811115611a32576000848401525b50505050565b60008151808452611a50816020860160208601611a08565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611a956020830184611a38565b9392505050565b600060208284031215611aae57600080fd5b5035919050565b600080600060408486031215611aca57600080fd5b833567ffffffffffffffff811115611ae157600080fd5b611aed8682870161193f565b9094509250611b00905060208501611988565b90509250925092565b600080600080600080600060c0888a031215611b2457600080fd5b873596506020880135611b368161191d565b95506040880135611b468161191d565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611b7057600080fd5b611b7c8a828b0161193f565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611c2a60c083018486611b8f565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611c67608083018688611b8f565b905083604083015263ffffffff831660608301529695505050505050565b60008451611c97818460208901611a08565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611cd3816001850160208a01611a08565b60019201918201528351611cee816002840160208801611a08565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611d5157611d51611cfb565b02949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff80841680611da457611da4611d5a565b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611dd357611dd3611cfb565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082821015611e1d57611e1d611cfb565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611e6f60a0830184611a38565b979650505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611eab57611eab611cfb565b5060010190565b600082611ec157611ec1611d5a565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082611f0457611f04611d5a565b500690565b60008219821115611f1c57611f1c611cfb565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215611f6257600080fd5b8151611a958161191d565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152611fa66080830185611a38565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261200260c0830184611a38565b9897505050505050505056fea164736f6c634300080f000a", + Bin: "0x6101206040523480156200001257600080fd5b50604051620023183803806200231883398101604081905262000035916200025c565b734200000000000000000000000000000000000007608052600160a0819052600460c05260e0526001600160a01b03811661010052620000746200007b565b506200028e565b600054600160a81b900460ff1615808015620000a457506000546001600160a01b90910460ff16105b80620000db5750620000c130620001c860201b620012f11760201c565b158015620000db5750600054600160a01b900460ff166001145b620001445760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff60a01b1916600160a01b179055801562000172576000805460ff60a81b1916600160a81b1790555b6200017c620001d7565b8015620001c5576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6001600160a01b03163b151590565b600054600160a81b900460ff16620002465760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200013b565b60cc80546001600160a01b03191661dead179055565b6000602082840312156200026f57600080fd5b81516001600160a01b03811681146200028757600080fd5b9392505050565b60805160a05160c05160e0516101005161201b620002fd600039600081816101a30152818161134a0152818161162c0152818161168d0152611759015260006106c40152600061069b015260006106720152600081816102dd0152818161040c0152611656015261201b6000f3fe6080604052600436106101445760003560e01c80636e296e45116100c0578063a4e7f8bd11610074578063b28ade2511610059578063b28ade251461036f578063d764ad0b1461038f578063ecc70428146103a257600080fd5b8063a4e7f8bd146102ff578063b1b1b2091461033f57600080fd5b806383a74074116100a557806383a74074146102b45780638cbeeef21461023c5780639fce812c146102cb57600080fd5b80636e296e451461028a5780638129fc1c1461029f57600080fd5b80633dbb202b116101175780634c1d6a69116100fc5780634c1d6a691461023c57806354fd4d50146102525780635644cfdf1461027457600080fd5b80633dbb202b146101ff5780633f827a5a1461021457600080fd5b8063028f85f7146101495780630c5684981461017c5780630ff754ea146101915780632828d7e8146101ea575b600080fd5b34801561015557600080fd5b5061015e601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061015e603f81565b34801561019d57600080fd5b506101c57f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610173565b3480156101f657600080fd5b5061015e604081565b61021261020d3660046119a1565b610407565b005b34801561022057600080fd5b50610229600181565b60405161ffff9091168152602001610173565b34801561024857600080fd5b5061015e619c4081565b34801561025e57600080fd5b5061026761066b565b6040516101739190611a82565b34801561028057600080fd5b5061015e61138881565b34801561029657600080fd5b506101c561070e565b3480156102ab57600080fd5b506102126107fa565b3480156102c057600080fd5b5061015e62030d4081565b3480156102d757600080fd5b506101c57f000000000000000000000000000000000000000000000000000000000000000081565b34801561030b57600080fd5b5061032f61031a366004611a9c565b60ce6020526000908152604090205460ff1681565b6040519015158152602001610173565b34801561034b57600080fd5b5061032f61035a366004611a9c565b60cb6020526000908152604090205460ff1681565b34801561037b57600080fd5b5061015e61038a366004611ab5565b6109f7565b61021261039d366004611b09565b610a65565b3480156103ae57600080fd5b506103f960cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b604051908152602001610173565b6105407f00000000000000000000000000000000000000000000000000000000000000006104368585856109f7565b347fd764ad0b000000000000000000000000000000000000000000000000000000006104a260cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016104be9796959493929190611bd8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261130d565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3385856105c560cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516105d7959493929190611c37565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60606106967f00000000000000000000000000000000000000000000000000000000000000006113c2565b6106bf7f00000000000000000000000000000000000000000000000000000000000000006113c2565b6106e87f00000000000000000000000000000000000000000000000000000000000000006113c2565b6040516020016106fa93929190611c85565b604051602081830303815290604052905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016107dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000547501000000000000000000000000000000000000000000900460ff1615808015610845575060005460017401000000000000000000000000000000000000000090910460ff16105b806108775750303b158015610877575060005474010000000000000000000000000000000000000000900460ff166001145b610903576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107d4565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055801561098957600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b6109916114f7565b80156109f457600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6000611388619c4080603f610a13604063ffffffff8816611d2a565b610a1d9190611d89565b610a28601088611d2a565b610a359062030d40611db0565b610a3f9190611db0565b610a499190611db0565b610a539190611db0565b610a5d9190611db0565b949350505050565b60f087901c60028110610b20576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016107d4565b8061ffff16600003610c15576000610b71878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506115d0915050565b600081815260cb602052604090205490915060ff1615610c13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016107d4565b505b6000610c5b898989898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115ef92505050565b9050610c65611612565b15610c9d57853414610c7957610c79611ddc565b600081815260ce602052604090205460ff1615610c9857610c98611ddc565b610def565b3415610d51576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016107d4565b600081815260ce602052604090205460ff16610def576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016107d4565b610df887611736565b15610eab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016107d4565b600081815260cb602052604090205460ff1615610f4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016107d4565b610f6b85610f5c611388619c40611db0565b67ffffffffffffffff166117ad565b1580610f91575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b156110aa57600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016110a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016107d4565b50506112e3565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a16179055600061113b88619c405a6110fe9190611e0b565b8988888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117cb92505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055905080156111d257600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26112df565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016112df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016107d4565b5050505b50505050505050565b905090565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e9e05c4290849061138a908890839089906000908990600401611e22565b6000604051808303818588803b1580156113a357600080fd5b505af11580156113b7573d6000803e3d6000fd5b505050505050505050565b60608160000361140557505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561142f578061141981611e7a565b91506114289050600a83611eb2565b9150611409565b60008167ffffffffffffffff81111561144a5761144a611ec6565b6040519080825280601f01601f191660200182016040528015611474576020820181803683370190505b5090505b8415610a5d57611489600183611e0b565b9150611496600a86611ef5565b6114a1906030611f09565b60f81b8183815181106114b6576114b6611f21565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506114f0600a86611eb2565b9450611478565b6000547501000000000000000000000000000000000000000000900460ff166115a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107d4565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055565b60006115de858585856117e5565b805190602001209050949350505050565b60006115ff87878787878761187e565b8051906020012090509695505050505050565b60003373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156112ec57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639bf62d826040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171a9190611f50565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff82163014806117a757507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b600080600080845160208601878a8af19695505050505050565b6060848484846040516024016117fe9493929190611f6d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b606086868686868660405160240161189b96959493929190611fb7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146109f457600080fd5b60008083601f84011261195157600080fd5b50813567ffffffffffffffff81111561196957600080fd5b60208301915083602082850101111561198157600080fd5b9250929050565b803563ffffffff8116811461199c57600080fd5b919050565b600080600080606085870312156119b757600080fd5b84356119c28161191d565b9350602085013567ffffffffffffffff8111156119de57600080fd5b6119ea8782880161193f565b90945092506119fd905060408601611988565b905092959194509250565b60005b83811015611a23578181015183820152602001611a0b565b83811115611a32576000848401525b50505050565b60008151808452611a50816020860160208601611a08565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611a956020830184611a38565b9392505050565b600060208284031215611aae57600080fd5b5035919050565b600080600060408486031215611aca57600080fd5b833567ffffffffffffffff811115611ae157600080fd5b611aed8682870161193f565b9094509250611b00905060208501611988565b90509250925092565b600080600080600080600060c0888a031215611b2457600080fd5b873596506020880135611b368161191d565b95506040880135611b468161191d565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611b7057600080fd5b611b7c8a828b0161193f565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611c2a60c083018486611b8f565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611c67608083018688611b8f565b905083604083015263ffffffff831660608301529695505050505050565b60008451611c97818460208901611a08565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611cd3816001850160208a01611a08565b60019201918201528351611cee816002840160208801611a08565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611d5157611d51611cfb565b02949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff80841680611da457611da4611d5a565b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611dd357611dd3611cfb565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082821015611e1d57611e1d611cfb565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611e6f60a0830184611a38565b979650505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611eab57611eab611cfb565b5060010190565b600082611ec157611ec1611d5a565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082611f0457611f04611d5a565b500690565b60008219821115611f1c57611f1c611cfb565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215611f6257600080fd5b8151611a958161191d565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152611fa66080830185611a38565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261200260c0830184611a38565b9897505050505050505056fea164736f6c634300080f000a", } // L1CrossDomainMessengerABI is the input ABI used to generate the binding from. diff --git a/op-bindings/bindings/l1erc721bridge.go b/op-bindings/bindings/l1erc721bridge.go index 8bf59092a3c6..a12168bdd3c8 100644 --- a/op-bindings/bindings/l1erc721bridge.go +++ b/op-bindings/bindings/l1erc721bridge.go @@ -31,7 +31,7 @@ var ( // L1ERC721BridgeMetaData contains all meta data concerning the L1ERC721Bridge contract. var L1ERC721BridgeMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_messenger\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_otherBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC721BridgeFinalized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC721BridgeInitiated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MESSENGER\",\"outputs\":[{\"internalType\":\"contractCrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"OTHER_BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"bridgeERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"bridgeERC721To\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"finalizeBridgeERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"contractCrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"otherBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b506040516200154e3803806200154e833981016040819052620000359162000161565b6001808084846001600160a01b038216620000ac5760405162461bcd60e51b815260206004820152602c60248201527f4552433732314272696467653a206d657373656e6765722063616e6e6f74206260448201526b65206164647265737328302960a01b60648201526084015b60405180910390fd5b6001600160a01b0381166200011c5760405162461bcd60e51b815260206004820152602f60248201527f4552433732314272696467653a206f74686572206272696467652063616e6e6f60448201526e74206265206164647265737328302960881b6064820152608401620000a3565b6001600160a01b039182166080521660a05260c09290925260e0526101005250620001999050565b80516001600160a01b03811681146200015c57600080fd5b919050565b600080604083850312156200017557600080fd5b620001808362000144565b9150620001906020840162000144565b90509250929050565b60805160a05160c05160e051610100516113406200020e6000396000610301015260006102d8015260006102af01526000818161017a015281816101d80152818161038d0152610b1401526000818160bf015281816101a101528181610363015281816103c40152610ae501526113406000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c8063761f449311610076578063927ede2d1161005b578063927ede2d1461019c578063aa557452146101c3578063c89701a2146101d657600080fd5b8063761f4493146101625780637f46ddb21461017557600080fd5b80633687011a146100a85780633cb747bf146100bd57806354fd4d50146101095780635d93a3fc1461011e575b600080fd5b6100bb6100b6366004610dc3565b6101fc565b005b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101116102a8565b6040516101009190610ec0565b61015261012c366004610eda565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b6040519015158152602001610100565b6100bb610170366004610f1b565b61034b565b6100df7f000000000000000000000000000000000000000000000000000000000000000081565b6100df7f000000000000000000000000000000000000000000000000000000000000000081565b6100bb6101d1366004610fb3565b6107cc565b7f00000000000000000000000000000000000000000000000000000000000000006100df565b333b15610290576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102a08686333388888888610888565b505050505050565b60606102d37f0000000000000000000000000000000000000000000000000000000000000000610bff565b6102fc7f0000000000000000000000000000000000000000000000000000000000000000610bff565b6103257f0000000000000000000000000000000000000000000000000000000000000000610bff565b6040516020016103379392919061102a565b604051602081830303815290604052905090565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614801561046957507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa15801561042d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061045191906110a0565b73ffffffffffffffffffffffffffffffffffffffff16145b6104f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f7468657220627269646765006064820152608401610287565b3073ffffffffffffffffffffffffffffffffffffffff88160361059a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c66000000000000000000000000000000000000000000006064820152608401610287565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff161515600114610669576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c3120427269646765000000000000006064820152608401610287565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b15801561072957600080fd5b505af115801561073d573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac878787876040516107bb9493929190611106565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff851661086f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f742062652061646472657373283029000000000000000000000000000000006064820152608401610287565b61087f8787338888888888610888565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff871661092b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f7420626520616464726573732830290000000000000000000000000000006064820152608401610287565b600063761f449360e01b888a89898988886040516024016109529796959493929190611146565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610a9257600080fd5b505af1158015610aa6573d6000803e3d6000fd5b50506040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169250633dbb202b9150610b40907f000000000000000000000000000000000000000000000000000000000000000090859089906004016111a3565b600060405180830381600087803b158015610b5a57600080fd5b505af1158015610b6e573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610bec9493929190611106565b60405180910390a4505050505050505050565b606081600003610c4257505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610c6c5780610c5681611217565b9150610c659050600a8361127e565b9150610c46565b60008167ffffffffffffffff811115610c8757610c87611292565b6040519080825280601f01601f191660200182016040528015610cb1576020820181803683370190505b5090505b8415610d3457610cc66001836112c1565b9150610cd3600a866112d8565b610cde9060306112ec565b60f81b818381518110610cf357610cf3611304565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610d2d600a8661127e565b9450610cb5565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610d5e57600080fd5b50565b803563ffffffff81168114610d7557600080fd5b919050565b60008083601f840112610d8c57600080fd5b50813567ffffffffffffffff811115610da457600080fd5b602083019150836020828501011115610dbc57600080fd5b9250929050565b60008060008060008060a08789031215610ddc57600080fd5b8635610de781610d3c565b95506020870135610df781610d3c565b945060408701359350610e0c60608801610d61565b9250608087013567ffffffffffffffff811115610e2857600080fd5b610e3489828a01610d7a565b979a9699509497509295939492505050565b60005b83811015610e61578181015183820152602001610e49565b83811115610e70576000848401525b50505050565b60008151808452610e8e816020860160208601610e46565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610ed36020830184610e76565b9392505050565b600080600060608486031215610eef57600080fd5b8335610efa81610d3c565b92506020840135610f0a81610d3c565b929592945050506040919091013590565b600080600080600080600060c0888a031215610f3657600080fd5b8735610f4181610d3c565b96506020880135610f5181610d3c565b95506040880135610f6181610d3c565b94506060880135610f7181610d3c565b93506080880135925060a088013567ffffffffffffffff811115610f9457600080fd5b610fa08a828b01610d7a565b989b979a50959850939692959293505050565b600080600080600080600060c0888a031215610fce57600080fd5b8735610fd981610d3c565b96506020880135610fe981610d3c565b95506040880135610ff981610d3c565b94506060880135935061100e60808901610d61565b925060a088013567ffffffffffffffff811115610f9457600080fd5b6000845161103c818460208901610e46565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611078816001850160208a01610e46565b60019201918201528351611093816002840160208801610e46565b0160020195945050505050565b6000602082840312156110b257600080fd5b8151610ed381610d3c565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8516815283602082015260606040820152600061113c6060830184866110bd565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261119660c0830184866110bd565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006111d26060830185610e76565b905063ffffffff83166040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611248576112486111e8565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261128d5761128d61124f565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156112d3576112d36111e8565b500390565b6000826112e7576112e761124f565b500690565b600082198211156112ff576112ff6111e8565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a", + Bin: "0x6101206040523480156200001257600080fd5b506040516200154f3803806200154f833981016040819052620000359162000162565b600180600284846001600160a01b038216620000ad5760405162461bcd60e51b815260206004820152602c60248201527f4552433732314272696467653a206d657373656e6765722063616e6e6f74206260448201526b65206164647265737328302960a01b60648201526084015b60405180910390fd5b6001600160a01b0381166200011d5760405162461bcd60e51b815260206004820152602f60248201527f4552433732314272696467653a206f74686572206272696467652063616e6e6f60448201526e74206265206164647265737328302960881b6064820152608401620000a4565b6001600160a01b039182166080521660a05260c09290925260e05261010052506200019a9050565b80516001600160a01b03811681146200015d57600080fd5b919050565b600080604083850312156200017657600080fd5b620001818362000145565b9150620001916020840162000145565b90509250929050565b60805160a05160c05160e051610100516113406200020f6000396000610301015260006102d8015260006102af01526000818161017a015281816101d80152818161038d0152610b1401526000818160bf015281816101a101528181610363015281816103c40152610ae501526113406000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c8063761f449311610076578063927ede2d1161005b578063927ede2d1461019c578063aa557452146101c3578063c89701a2146101d657600080fd5b8063761f4493146101625780637f46ddb21461017557600080fd5b80633687011a146100a85780633cb747bf146100bd57806354fd4d50146101095780635d93a3fc1461011e575b600080fd5b6100bb6100b6366004610dc3565b6101fc565b005b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101116102a8565b6040516101009190610ec0565b61015261012c366004610eda565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b6040519015158152602001610100565b6100bb610170366004610f1b565b61034b565b6100df7f000000000000000000000000000000000000000000000000000000000000000081565b6100df7f000000000000000000000000000000000000000000000000000000000000000081565b6100bb6101d1366004610fb3565b6107cc565b7f00000000000000000000000000000000000000000000000000000000000000006100df565b333b15610290576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102a08686333388888888610888565b505050505050565b60606102d37f0000000000000000000000000000000000000000000000000000000000000000610bff565b6102fc7f0000000000000000000000000000000000000000000000000000000000000000610bff565b6103257f0000000000000000000000000000000000000000000000000000000000000000610bff565b6040516020016103379392919061102a565b604051602081830303815290604052905090565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614801561046957507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa15801561042d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061045191906110a0565b73ffffffffffffffffffffffffffffffffffffffff16145b6104f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f7468657220627269646765006064820152608401610287565b3073ffffffffffffffffffffffffffffffffffffffff88160361059a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c66000000000000000000000000000000000000000000006064820152608401610287565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff161515600114610669576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c3120427269646765000000000000006064820152608401610287565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b15801561072957600080fd5b505af115801561073d573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac878787876040516107bb9493929190611106565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff851661086f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f742062652061646472657373283029000000000000000000000000000000006064820152608401610287565b61087f8787338888888888610888565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff871661092b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f7420626520616464726573732830290000000000000000000000000000006064820152608401610287565b600063761f449360e01b888a89898988886040516024016109529796959493929190611146565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610a9257600080fd5b505af1158015610aa6573d6000803e3d6000fd5b50506040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169250633dbb202b9150610b40907f000000000000000000000000000000000000000000000000000000000000000090859089906004016111a3565b600060405180830381600087803b158015610b5a57600080fd5b505af1158015610b6e573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610bec9493929190611106565b60405180910390a4505050505050505050565b606081600003610c4257505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610c6c5780610c5681611217565b9150610c659050600a8361127e565b9150610c46565b60008167ffffffffffffffff811115610c8757610c87611292565b6040519080825280601f01601f191660200182016040528015610cb1576020820181803683370190505b5090505b8415610d3457610cc66001836112c1565b9150610cd3600a866112d8565b610cde9060306112ec565b60f81b818381518110610cf357610cf3611304565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610d2d600a8661127e565b9450610cb5565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610d5e57600080fd5b50565b803563ffffffff81168114610d7557600080fd5b919050565b60008083601f840112610d8c57600080fd5b50813567ffffffffffffffff811115610da457600080fd5b602083019150836020828501011115610dbc57600080fd5b9250929050565b60008060008060008060a08789031215610ddc57600080fd5b8635610de781610d3c565b95506020870135610df781610d3c565b945060408701359350610e0c60608801610d61565b9250608087013567ffffffffffffffff811115610e2857600080fd5b610e3489828a01610d7a565b979a9699509497509295939492505050565b60005b83811015610e61578181015183820152602001610e49565b83811115610e70576000848401525b50505050565b60008151808452610e8e816020860160208601610e46565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610ed36020830184610e76565b9392505050565b600080600060608486031215610eef57600080fd5b8335610efa81610d3c565b92506020840135610f0a81610d3c565b929592945050506040919091013590565b600080600080600080600060c0888a031215610f3657600080fd5b8735610f4181610d3c565b96506020880135610f5181610d3c565b95506040880135610f6181610d3c565b94506060880135610f7181610d3c565b93506080880135925060a088013567ffffffffffffffff811115610f9457600080fd5b610fa08a828b01610d7a565b989b979a50959850939692959293505050565b600080600080600080600060c0888a031215610fce57600080fd5b8735610fd981610d3c565b96506020880135610fe981610d3c565b95506040880135610ff981610d3c565b94506060880135935061100e60808901610d61565b925060a088013567ffffffffffffffff811115610f9457600080fd5b6000845161103c818460208901610e46565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611078816001850160208a01610e46565b60019201918201528351611093816002840160208801610e46565b0160020195945050505050565b6000602082840312156110b257600080fd5b8151610ed381610d3c565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8516815283602082015260606040820152600061113c6060830184866110bd565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261119660c0830184866110bd565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006111d26060830185610e76565b905063ffffffff83166040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611248576112486111e8565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261128d5761128d61124f565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156112d3576112d36111e8565b500390565b6000826112e7576112e761124f565b500690565b600082198211156112ff576112ff6111e8565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a", } // L1ERC721BridgeABI is the input ABI used to generate the binding from. diff --git a/op-bindings/bindings/l1standardbridge.go b/op-bindings/bindings/l1standardbridge.go index d13edbc5c0fa..3427d5d6360c 100644 --- a/op-bindings/bindings/l1standardbridge.go +++ b/op-bindings/bindings/l1standardbridge.go @@ -31,7 +31,7 @@ var ( // L1StandardBridgeMetaData contains all meta data concerning the L1StandardBridge contract. var L1StandardBridgeMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"_messenger\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC20BridgeFinalized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC20BridgeInitiated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC20DepositInitiated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC20WithdrawalFinalized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ETHBridgeFinalized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ETHBridgeInitiated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ETHDepositInitiated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ETHWithdrawalFinalized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MESSENGER\",\"outputs\":[{\"internalType\":\"contractCrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"OTHER_BRIDGE\",\"outputs\":[{\"internalType\":\"contractStandardBridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"bridgeERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"bridgeERC20To\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"bridgeETH\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"bridgeETHTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"depositERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"depositERC20To\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"depositETH\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"depositETHTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"finalizeBridgeERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"finalizeBridgeETH\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"finalizeERC20Withdrawal\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"finalizeETHWithdrawal\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2TokenBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"contractCrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x6101206040523480156200001257600080fd5b5060405162002c8738038062002c8783398101604081905262000035916200006f565b6001600160a01b031660805273420000000000000000000000000000000000001060a052600160c081905260e052600061010052620000a1565b6000602082840312156200008257600080fd5b81516001600160a01b03811681146200009a57600080fd5b9392505050565b60805160a05160c05160e05161010051612b46620001416000396000610ee001526000610eb701526000610e8e015260008181610311015281816103c8015281816104ce015281816109af015281816113560152611a08015260008181610253015281816103fe015281816104a40152818161050501528181610985015281816109e601528181610c730152818161131901526119cc0152612b466000f3fe60806040526004361061012d5760003560e01c8063838b2520116100a5578063927ede2d11610074578063a9f9e67511610059578063a9f9e67514610433578063b1a1a88214610453578063e11013dd1461046657600080fd5b8063927ede2d146103ec5780639a2ac6d51461042057600080fd5b8063838b25201461033357806387087623146103535780638f601f661461037357806391c49bf8146103b957600080fd5b80633cb747bf116100fc57806354fd4d50116100e157806354fd4d50146102bd57806358a997f6146102df5780637f46ddb2146102ff57600080fd5b80633cb747bf14610244578063540abf731461029d57600080fd5b80630166a07a146101eb57806309fc88431461020b5780631532ec341461021e5780631635f5fd1461023157600080fd5b366101e657333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101e4333362030d4060405180602001604052806000815250610479565b005b600080fd5b3480156101f757600080fd5b506101e4610206366004612447565b61048c565b6101e46102193660046124f8565b610882565b6101e461022c36600461254b565b610959565b6101e461023f36600461254b565b61096d565b34801561025057600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102a957600080fd5b506101e46102b83660046125be565b610e42565b3480156102c957600080fd5b506102d2610e87565b60405161029491906126ab565b3480156102eb57600080fd5b506101e46102fa3660046126be565b610f2a565b34801561030b57600080fd5b506102737f000000000000000000000000000000000000000000000000000000000000000081565b34801561033f57600080fd5b506101e461034e3660046125be565b610ffe565b34801561035f57600080fd5b506101e461036e3660046126be565b611043565b34801561037f57600080fd5b506103ab61038e366004612741565b600260209081526000928352604080842090915290825290205481565b604051908152602001610294565b3480156103c557600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610273565b3480156103f857600080fd5b506102737f000000000000000000000000000000000000000000000000000000000000000081565b6101e461042e36600461277a565b611117565b34801561043f57600080fd5b506101e461044e366004612447565b611159565b6101e46104613660046124f8565b611168565b6101e461047436600461277a565b611239565b610486848434858561127c565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156105aa57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa15801561056e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061059291906127dd565b73ffffffffffffffffffffffffffffffffffffffff16145b61065c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b61066587611460565b156107b35761067487876114c2565b610726576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561079657600080fd5b505af11580156107aa573d6000803e3d6000fd5b50505050610835565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a16835292905220546107f1908490612829565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108359085856115e2565b610879878787878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506116b692505050565b50505050505050565b333b15610911576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109543333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061127c92505050565b505050565b610966858585858561096d565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015610a8b57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7391906127dd565b73ffffffffffffffffffffffffffffffffffffffff16145b610b3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b823414610bcc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610c71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610d4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610d8e85858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061174492505050565b6000610dab855a86604051806020016040528060008152506117b7565b905080610e3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b505050505050565b61087987873388888888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d192505050565b6060610eb27f0000000000000000000000000000000000000000000000000000000000000000611b18565b610edb7f0000000000000000000000000000000000000000000000000000000000000000611b18565b610f047f0000000000000000000000000000000000000000000000000000000000000000611b18565b604051602001610f1693929190612840565b604051602081830303815290604052905090565b333b15610fb9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b610e3a86863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5592505050565b61087987873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5592505050565b333b156110d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b610e3a86863333888888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d192505050565b61048633858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047992505050565b6108798787878787878761048c565b333b156111f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61095433338585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047992505050565b6104863385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061127c92505050565b82341461130b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61131785858584611c64565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b847f0000000000000000000000000000000000000000000000000000000000000000631635f5fd60e01b8989898860405160240161139494939291906128b6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b9092168252611427929188906004016128ff565b6000604051808303818588803b15801561144057600080fd5b505af1158015611454573d6000803e3d6000fd5b50505050505050505050565b600061148c827f1d1d8b6300000000000000000000000000000000000000000000000000000000611cd7565b806114bc57506114bc827fec4fc8e300000000000000000000000000000000000000000000000000000000611cd7565b92915050565b60006114ee837f1d1d8b6300000000000000000000000000000000000000000000000000000000611cd7565b15611597578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa15801561153e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156291906127dd565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161490506114bc565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561153e573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109549084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611cfa565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b386868660405161172e93929190612944565b60405180910390a4610e3a868686868686611e06565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e63184846040516117a3929190612982565b60405180910390a361048684848484611e8e565b600080600080845160208601878a8af19695505050505050565b6117da87611460565b15611928576117e987876114c2565b61189b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b15801561190b57600080fd5b505af115801561191f573d6000803e3d6000fd5b505050506119bc565b61194a73ffffffffffffffffffffffffffffffffffffffff8816863086611efb565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461198890849061299b565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b6119ca878787878786611f59565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b7f0000000000000000000000000000000000000000000000000000000000000000630166a07a60e01b898b8a8a8a89604051602401611a4a969594939291906129b3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611add929187906004016128ff565b600060405180830381600087803b158015611af757600080fd5b505af1158015611b0b573d6000803e3d6000fd5b5050505050505050505050565b606081600003611b5b57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611b855780611b6f81612a0e565b9150611b7e9050600a83612a75565b9150611b5f565b60008167ffffffffffffffff811115611ba057611ba0612a89565b6040519080825280601f01601f191660200182016040528015611bca576020820181803683370190505b5090505b8415611c4d57611bdf600183612829565b9150611bec600a86612ab8565b611bf790603061299b565b60f81b818381518110611c0c57611c0c612acc565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611c46600a86612a75565b9450611bce565b949350505050565b610879878787878787876117d1565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051611cc3929190612982565b60405180910390a361048684848484611fe7565b6000611ce283612046565b8015611cf35750611cf383836120aa565b9392505050565b6000611d5c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166121799092919063ffffffff16565b8051909150156109545780806020019051810190611d7a9190612afb565b610954576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd868686604051611e7e93929190612944565b60405180910390a4505050505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d8484604051611eed929190612982565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526104869085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611634565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d0396868686604051611fd193929190612944565b60405180910390a4610e3a868686868686612188565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af58484604051611eed929190612982565b6000612072827f01ffc9a7000000000000000000000000000000000000000000000000000000006120aa565b80156114bc57506120a3827fffffffff000000000000000000000000000000000000000000000000000000006120aa565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612162575060208210155b801561216e5750600081115b979650505050505050565b6060611c4d8484600085612200565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf868686604051611e7e93929190612944565b606082471015612292576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612310576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516123399190612b1d565b60006040518083038185875af1925050503d8060008114612376576040519150601f19603f3d011682016040523d82523d6000602084013e61237b565b606091505b509150915061216e82828660608315612395575081611cf3565b8251156123a55782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd91906126ab565b73ffffffffffffffffffffffffffffffffffffffff811681146123fb57600080fd5b50565b60008083601f84011261241057600080fd5b50813567ffffffffffffffff81111561242857600080fd5b60208301915083602082850101111561244057600080fd5b9250929050565b600080600080600080600060c0888a03121561246257600080fd5b873561246d816123d9565b9650602088013561247d816123d9565b9550604088013561248d816123d9565b9450606088013561249d816123d9565b93506080880135925060a088013567ffffffffffffffff8111156124c057600080fd5b6124cc8a828b016123fe565b989b979a50959850939692959293505050565b803563ffffffff811681146124f357600080fd5b919050565b60008060006040848603121561250d57600080fd5b612516846124df565b9250602084013567ffffffffffffffff81111561253257600080fd5b61253e868287016123fe565b9497909650939450505050565b60008060008060006080868803121561256357600080fd5b853561256e816123d9565b9450602086013561257e816123d9565b935060408601359250606086013567ffffffffffffffff8111156125a157600080fd5b6125ad888289016123fe565b969995985093965092949392505050565b600080600080600080600060c0888a0312156125d957600080fd5b87356125e4816123d9565b965060208801356125f4816123d9565b95506040880135612604816123d9565b945060608801359350612619608089016124df565b925060a088013567ffffffffffffffff8111156124c057600080fd5b60005b83811015612650578181015183820152602001612638565b838111156104865750506000910152565b60008151808452612679816020860160208601612635565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611cf36020830184612661565b60008060008060008060a087890312156126d757600080fd5b86356126e2816123d9565b955060208701356126f2816123d9565b945060408701359350612707606088016124df565b9250608087013567ffffffffffffffff81111561272357600080fd5b61272f89828a016123fe565b979a9699509497509295939492505050565b6000806040838503121561275457600080fd5b823561275f816123d9565b9150602083013561276f816123d9565b809150509250929050565b6000806000806060858703121561279057600080fd5b843561279b816123d9565b93506127a9602086016124df565b9250604085013567ffffffffffffffff8111156127c557600080fd5b6127d1878288016123fe565b95989497509550505050565b6000602082840312156127ef57600080fd5b8151611cf3816123d9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561283b5761283b6127fa565b500390565b60008451612852818460208901612635565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161288e816001850160208a01612635565b600192019182015283516128a9816002840160208801612635565b0160020195945050505050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526128f56080830184612661565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600061292e6060830185612661565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff841681528260208201526060604082015260006129796060830184612661565b95945050505050565b828152604060208201526000611c4d6040830184612661565b600082198211156129ae576129ae6127fa565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612a0260c0830184612661565b98975050505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612a3f57612a3f6127fa565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082612a8457612a84612a46565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082612ac757612ac7612a46565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215612b0d57600080fd5b81518015158114611cf357600080fd5b60008251612b2f818460208701612635565b919091019291505056fea164736f6c634300080f000a", + Bin: "0x6101206040523480156200001257600080fd5b5060405162002c8738038062002c8783398101604081905262000035916200006f565b6001600160a01b031660805273420000000000000000000000000000000000001060a052600160c081905260e081905261010052620000a1565b6000602082840312156200008257600080fd5b81516001600160a01b03811681146200009a57600080fd5b9392505050565b60805160a05160c05160e05161010051612b46620001416000396000610ee001526000610eb701526000610e8e015260008181610311015281816103c8015281816104ce015281816109af015281816113560152611a08015260008181610253015281816103fe015281816104a40152818161050501528181610985015281816109e601528181610c730152818161131901526119cc0152612b466000f3fe60806040526004361061012d5760003560e01c8063838b2520116100a5578063927ede2d11610074578063a9f9e67511610059578063a9f9e67514610433578063b1a1a88214610453578063e11013dd1461046657600080fd5b8063927ede2d146103ec5780639a2ac6d51461042057600080fd5b8063838b25201461033357806387087623146103535780638f601f661461037357806391c49bf8146103b957600080fd5b80633cb747bf116100fc57806354fd4d50116100e157806354fd4d50146102bd57806358a997f6146102df5780637f46ddb2146102ff57600080fd5b80633cb747bf14610244578063540abf731461029d57600080fd5b80630166a07a146101eb57806309fc88431461020b5780631532ec341461021e5780631635f5fd1461023157600080fd5b366101e657333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101e4333362030d4060405180602001604052806000815250610479565b005b600080fd5b3480156101f757600080fd5b506101e4610206366004612447565b61048c565b6101e46102193660046124f8565b610882565b6101e461022c36600461254b565b610959565b6101e461023f36600461254b565b61096d565b34801561025057600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102a957600080fd5b506101e46102b83660046125be565b610e42565b3480156102c957600080fd5b506102d2610e87565b60405161029491906126ab565b3480156102eb57600080fd5b506101e46102fa3660046126be565b610f2a565b34801561030b57600080fd5b506102737f000000000000000000000000000000000000000000000000000000000000000081565b34801561033f57600080fd5b506101e461034e3660046125be565b610ffe565b34801561035f57600080fd5b506101e461036e3660046126be565b611043565b34801561037f57600080fd5b506103ab61038e366004612741565b600260209081526000928352604080842090915290825290205481565b604051908152602001610294565b3480156103c557600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610273565b3480156103f857600080fd5b506102737f000000000000000000000000000000000000000000000000000000000000000081565b6101e461042e36600461277a565b611117565b34801561043f57600080fd5b506101e461044e366004612447565b611159565b6101e46104613660046124f8565b611168565b6101e461047436600461277a565b611239565b610486848434858561127c565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156105aa57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa15801561056e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061059291906127dd565b73ffffffffffffffffffffffffffffffffffffffff16145b61065c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b61066587611460565b156107b35761067487876114c2565b610726576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561079657600080fd5b505af11580156107aa573d6000803e3d6000fd5b50505050610835565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a16835292905220546107f1908490612829565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108359085856115e2565b610879878787878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506116b692505050565b50505050505050565b333b15610911576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109543333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061127c92505050565b505050565b610966858585858561096d565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015610a8b57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7391906127dd565b73ffffffffffffffffffffffffffffffffffffffff16145b610b3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b823414610bcc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610c71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610d4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610d8e85858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061174492505050565b6000610dab855a86604051806020016040528060008152506117b7565b905080610e3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b505050505050565b61087987873388888888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d192505050565b6060610eb27f0000000000000000000000000000000000000000000000000000000000000000611b18565b610edb7f0000000000000000000000000000000000000000000000000000000000000000611b18565b610f047f0000000000000000000000000000000000000000000000000000000000000000611b18565b604051602001610f1693929190612840565b604051602081830303815290604052905090565b333b15610fb9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b610e3a86863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5592505050565b61087987873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5592505050565b333b156110d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b610e3a86863333888888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117d192505050565b61048633858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047992505050565b6108798787878787878761048c565b333b156111f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61095433338585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047992505050565b6104863385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061127c92505050565b82341461130b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61131785858584611c64565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b847f0000000000000000000000000000000000000000000000000000000000000000631635f5fd60e01b8989898860405160240161139494939291906128b6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b9092168252611427929188906004016128ff565b6000604051808303818588803b15801561144057600080fd5b505af1158015611454573d6000803e3d6000fd5b50505050505050505050565b600061148c827f1d1d8b6300000000000000000000000000000000000000000000000000000000611cd7565b806114bc57506114bc827fec4fc8e300000000000000000000000000000000000000000000000000000000611cd7565b92915050565b60006114ee837f1d1d8b6300000000000000000000000000000000000000000000000000000000611cd7565b15611597578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa15801561153e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156291906127dd565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161490506114bc565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561153e573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109549084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611cfa565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b386868660405161172e93929190612944565b60405180910390a4610e3a868686868686611e06565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e63184846040516117a3929190612982565b60405180910390a361048684848484611e8e565b600080600080845160208601878a8af19695505050505050565b6117da87611460565b15611928576117e987876114c2565b61189b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b15801561190b57600080fd5b505af115801561191f573d6000803e3d6000fd5b505050506119bc565b61194a73ffffffffffffffffffffffffffffffffffffffff8816863086611efb565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461198890849061299b565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b6119ca878787878786611f59565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b7f0000000000000000000000000000000000000000000000000000000000000000630166a07a60e01b898b8a8a8a89604051602401611a4a969594939291906129b3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611add929187906004016128ff565b600060405180830381600087803b158015611af757600080fd5b505af1158015611b0b573d6000803e3d6000fd5b5050505050505050505050565b606081600003611b5b57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611b855780611b6f81612a0e565b9150611b7e9050600a83612a75565b9150611b5f565b60008167ffffffffffffffff811115611ba057611ba0612a89565b6040519080825280601f01601f191660200182016040528015611bca576020820181803683370190505b5090505b8415611c4d57611bdf600183612829565b9150611bec600a86612ab8565b611bf790603061299b565b60f81b818381518110611c0c57611c0c612acc565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611c46600a86612a75565b9450611bce565b949350505050565b610879878787878787876117d1565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051611cc3929190612982565b60405180910390a361048684848484611fe7565b6000611ce283612046565b8015611cf35750611cf383836120aa565b9392505050565b6000611d5c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166121799092919063ffffffff16565b8051909150156109545780806020019051810190611d7a9190612afb565b610954576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd868686604051611e7e93929190612944565b60405180910390a4505050505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d8484604051611eed929190612982565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526104869085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611634565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d0396868686604051611fd193929190612944565b60405180910390a4610e3a868686868686612188565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af58484604051611eed929190612982565b6000612072827f01ffc9a7000000000000000000000000000000000000000000000000000000006120aa565b80156114bc57506120a3827fffffffff000000000000000000000000000000000000000000000000000000006120aa565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612162575060208210155b801561216e5750600081115b979650505050505050565b6060611c4d8484600085612200565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf868686604051611e7e93929190612944565b606082471015612292576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612310576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516123399190612b1d565b60006040518083038185875af1925050503d8060008114612376576040519150601f19603f3d011682016040523d82523d6000602084013e61237b565b606091505b509150915061216e82828660608315612395575081611cf3565b8251156123a55782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd91906126ab565b73ffffffffffffffffffffffffffffffffffffffff811681146123fb57600080fd5b50565b60008083601f84011261241057600080fd5b50813567ffffffffffffffff81111561242857600080fd5b60208301915083602082850101111561244057600080fd5b9250929050565b600080600080600080600060c0888a03121561246257600080fd5b873561246d816123d9565b9650602088013561247d816123d9565b9550604088013561248d816123d9565b9450606088013561249d816123d9565b93506080880135925060a088013567ffffffffffffffff8111156124c057600080fd5b6124cc8a828b016123fe565b989b979a50959850939692959293505050565b803563ffffffff811681146124f357600080fd5b919050565b60008060006040848603121561250d57600080fd5b612516846124df565b9250602084013567ffffffffffffffff81111561253257600080fd5b61253e868287016123fe565b9497909650939450505050565b60008060008060006080868803121561256357600080fd5b853561256e816123d9565b9450602086013561257e816123d9565b935060408601359250606086013567ffffffffffffffff8111156125a157600080fd5b6125ad888289016123fe565b969995985093965092949392505050565b600080600080600080600060c0888a0312156125d957600080fd5b87356125e4816123d9565b965060208801356125f4816123d9565b95506040880135612604816123d9565b945060608801359350612619608089016124df565b925060a088013567ffffffffffffffff8111156124c057600080fd5b60005b83811015612650578181015183820152602001612638565b838111156104865750506000910152565b60008151808452612679816020860160208601612635565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611cf36020830184612661565b60008060008060008060a087890312156126d757600080fd5b86356126e2816123d9565b955060208701356126f2816123d9565b945060408701359350612707606088016124df565b9250608087013567ffffffffffffffff81111561272357600080fd5b61272f89828a016123fe565b979a9699509497509295939492505050565b6000806040838503121561275457600080fd5b823561275f816123d9565b9150602083013561276f816123d9565b809150509250929050565b6000806000806060858703121561279057600080fd5b843561279b816123d9565b93506127a9602086016124df565b9250604085013567ffffffffffffffff8111156127c557600080fd5b6127d1878288016123fe565b95989497509550505050565b6000602082840312156127ef57600080fd5b8151611cf3816123d9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561283b5761283b6127fa565b500390565b60008451612852818460208901612635565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161288e816001850160208a01612635565b600192019182015283516128a9816002840160208801612635565b0160020195945050505050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526128f56080830184612661565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600061292e6060830185612661565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff841681528260208201526060604082015260006129796060830184612661565b95945050505050565b828152604060208201526000611c4d6040830184612661565b600082198211156129ae576129ae6127fa565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612a0260c0830184612661565b98975050505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612a3f57612a3f6127fa565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082612a8457612a84612a46565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082612ac757612ac7612a46565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215612b0d57600080fd5b81518015158114611cf357600080fd5b60008251612b2f818460208701612635565b919091019291505056fea164736f6c634300080f000a", } // L1StandardBridgeABI is the input ABI used to generate the binding from. diff --git a/op-bindings/bindings/l2outputoracle.go b/op-bindings/bindings/l2outputoracle.go index 9f74ca8c0d26..0cd7507855ec 100644 --- a/op-bindings/bindings/l2outputoracle.go +++ b/op-bindings/bindings/l2outputoracle.go @@ -38,7 +38,7 @@ type TypesOutputProposal struct { // L2OutputOracleMetaData contains all meta data concerning the L2OutputOracle contract. var L2OutputOracleMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_proposer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_challenger\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriodSeconds\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"l2OutputIndex\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"l2BlockNumber\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"l1Timestamp\",\"type\":\"uint256\"}],\"name\":\"OutputProposed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"prevNextOutputIndex\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newNextOutputIndex\",\"type\":\"uint256\"}],\"name\":\"OutputsDeleted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CHALLENGER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD_SECONDS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_BLOCK_TIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROPOSER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SUBMISSION_INTERVAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"computeL2Timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"}],\"name\":\"deleteL2Outputs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2BlockNumber\",\"type\":\"uint128\"}],\"internalType\":\"structTypes.OutputProposal\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"getL2OutputAfter\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2BlockNumber\",\"type\":\"uint128\"}],\"internalType\":\"structTypes.OutputProposal\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"getL2OutputIndexAfter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_startingBlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingTimestamp\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestOutputIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextOutputIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1BlockHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1BlockNumber\",\"type\":\"uint256\"}],\"name\":\"proposeL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startingBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startingTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101806040523480156200001257600080fd5b5060405162001b0238038062001b02833981016040819052620000359162000356565b6001608052600360a052600060c05285620000bd5760405162461bcd60e51b815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e203000000000000000000000000060648201526084015b60405180910390fd5b60008711620001355760405162461bcd60e51b815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e20300000000000006064820152608401620000b4565b60e08790526101008690526001600160a01b038084166101405282166101205261016081905262000167858562000174565b50505050505050620003be565b600054610100900460ff1615808015620001955750600054600160ff909116105b80620001c55750620001b2306200032a60201b620012691760201c565b158015620001c5575060005460ff166001145b6200022a5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620000b4565b6000805460ff1916600117905580156200024e576000805461ff0019166101001790555b42821115620002d45760405162461bcd60e51b8152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201526374696d6560e01b608482015260a401620000b4565b60028290556001839055801562000325576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b80516001600160a01b03811681146200035157600080fd5b919050565b600080600080600080600060e0888a0312156200037257600080fd5b87519650602088015195506040880151945060608801519350620003996080890162000339565b9250620003a960a0890162000339565b915060c0880151905092959891949750929550565b60805160a05160c05160e051610100516101205161014051610160516116bb620004476000396000818161041501526108f601526000818161036c0152610a66015260008181610236015261079001526000818161015a0152610f9d0152600081816101b60152610feb01526000610503015260006104da015260006104b101526116bb6000f3fe6080604052600436106101435760003560e01c806388786272116100c0578063cf8e5cf011610074578063dcec334811610059578063dcec3348146103ce578063e4a30116146103e3578063f4daa2911461040357600080fd5b8063cf8e5cf01461038e578063d1de856c146103ae57600080fd5b80639aaab648116100a55780639aaab648146102eb578063a25ae557146102fe578063bffa7f0f1461035a57600080fd5b806388786272146102b357806389c44cbb146102c957600080fd5b806369f16eec116101175780636b4d98dd116100fc5780636b4d98dd1461022457806370872aa51461027d5780637f0064201461029357600080fd5b806369f16eec146101fa5780636abcf5631461020f57600080fd5b80622134cc146101485780634599c7881461018f578063529933df146101a457806354fd4d50146101d8575b600080fd5b34801561015457600080fd5b5061017c7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b34801561019b57600080fd5b5061017c610437565b3480156101b057600080fd5b5061017c7f000000000000000000000000000000000000000000000000000000000000000081565b3480156101e457600080fd5b506101ed6104aa565b60405161018691906113f2565b34801561020657600080fd5b5061017c61054d565b34801561021b57600080fd5b5060035461017c565b34801561023057600080fd5b506102587f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610186565b34801561028957600080fd5b5061017c60015481565b34801561029f57600080fd5b5061017c6102ae366004611443565b61055f565b3480156102bf57600080fd5b5061017c60025481565b3480156102d557600080fd5b506102e96102e4366004611443565b610778565b005b6102e96102f936600461145c565b610a4e565b34801561030a57600080fd5b5061031e610319366004611443565b610ecd565b60408051825181526020808401516fffffffffffffffffffffffffffffffff908116918301919091529282015190921690820152606001610186565b34801561036657600080fd5b506102587f000000000000000000000000000000000000000000000000000000000000000081565b34801561039a57600080fd5b5061031e6103a9366004611443565b610f61565b3480156103ba57600080fd5b5061017c6103c9366004611443565b610f99565b3480156103da57600080fd5b5061017c610fe7565b3480156103ef57600080fd5b506102e96103fe36600461148e565b61101c565b34801561040f57600080fd5b5061017c7f000000000000000000000000000000000000000000000000000000000000000081565b600354600090156104a15760038054610452906001906114df565b81548110610462576104626114f6565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b60606104d57f0000000000000000000000000000000000000000000000000000000000000000611285565b6104fe7f0000000000000000000000000000000000000000000000000000000000000000611285565b6105277f0000000000000000000000000000000000000000000000000000000000000000611285565b60405160200161053993929190611525565b604051602081830303815290604052905090565b6003546000906104a5906001906114df565b6000610569610437565b821115610623576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6003546106d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161061a565b6003546000905b8082101561077157600060026106f5838561159b565b6106ff91906115e2565b90508460038281548110610715576107156114f6565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1610156107675761076081600161159b565b925061076b565b8091505b506106df565b5092915050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461083d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161061a565b60035481106108f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161061a565b7f000000000000000000000000000000000000000000000000000000000000000060038281548110610928576109286114f6565b6000918252602090912060016002909202010154610958906fffffffffffffffffffffffffffffffff16426114df565b10610a0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161061a565b6000610a1660035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610b39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161061a565b610b41610fe7565b8314610bf5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161061a565b42610bff84610f99565b10610c8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161061a565b83610d19576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161061a565b8115610dd55781814014610dd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161061a565b82610ddf60035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e242604051610e1191815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b604080516060810182526000808252602082018190529181019190915260038281548110610efd57610efd6114f6565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b60408051606081018252600080825260208201819052918101919091526003610f898361055f565b81548110610efd57610efd6114f6565b60007f000000000000000000000000000000000000000000000000000000000000000060015483610fca91906114df565b610fd491906115f6565b600254610fe1919061159b565b92915050565b60007f0000000000000000000000000000000000000000000000000000000000000000611012610437565b6104a5919061159b565b600054610100900460ff161580801561103c5750600054600160ff909116105b806110565750303b158015611056575060005460ff166001145b6110e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161061a565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561114057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b428211156111f7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161061a565b60028290556001839055801561126457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6060816000036112c857505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156112f257806112dc81611633565b91506112eb9050600a836115e2565b91506112cc565b60008167ffffffffffffffff81111561130d5761130d61166b565b6040519080825280601f01601f191660200182016040528015611337576020820181803683370190505b5090505b84156113ba5761134c6001836114df565b9150611359600a8661169a565b61136490603061159b565b60f81b818381518110611379576113796114f6565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506113b3600a866115e2565b945061133b565b949350505050565b60005b838110156113dd5781810151838201526020016113c5565b838111156113ec576000848401525b50505050565b60208152600082518060208401526114118160408501602087016113c2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60006020828403121561145557600080fd5b5035919050565b6000806000806080858703121561147257600080fd5b5050823594602084013594506040840135936060013592509050565b600080604083850312156114a157600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156114f1576114f16114b0565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600084516115378184602089016113c2565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611573816001850160208a016113c2565b6001920191820152835161158e8160028401602088016113c2565b0160020195945050505050565b600082198211156115ae576115ae6114b0565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826115f1576115f16115b3565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561162e5761162e6114b0565b500290565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611664576116646114b0565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000826116a9576116a96115b3565b50069056fea164736f6c634300080f000a", + Bin: "0x6101806040523480156200001257600080fd5b5060405162001b0238038062001b02833981016040819052620000359162000356565b60016080819052600360a05260c05285620000bd5760405162461bcd60e51b815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e203000000000000000000000000060648201526084015b60405180910390fd5b60008711620001355760405162461bcd60e51b815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e20300000000000006064820152608401620000b4565b60e08790526101008690526001600160a01b038084166101405282166101205261016081905262000167858562000174565b50505050505050620003be565b600054610100900460ff1615808015620001955750600054600160ff909116105b80620001c55750620001b2306200032a60201b620012691760201c565b158015620001c5575060005460ff166001145b6200022a5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620000b4565b6000805460ff1916600117905580156200024e576000805461ff0019166101001790555b42821115620002d45760405162461bcd60e51b8152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201526374696d6560e01b608482015260a401620000b4565b60028290556001839055801562000325576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b80516001600160a01b03811681146200035157600080fd5b919050565b600080600080600080600060e0888a0312156200037257600080fd5b87519650602088015195506040880151945060608801519350620003996080890162000339565b9250620003a960a0890162000339565b915060c0880151905092959891949750929550565b60805160a05160c05160e051610100516101205161014051610160516116bb620004476000396000818161041501526108f601526000818161036c0152610a66015260008181610236015261079001526000818161015a0152610f9d0152600081816101b60152610feb01526000610503015260006104da015260006104b101526116bb6000f3fe6080604052600436106101435760003560e01c806388786272116100c0578063cf8e5cf011610074578063dcec334811610059578063dcec3348146103ce578063e4a30116146103e3578063f4daa2911461040357600080fd5b8063cf8e5cf01461038e578063d1de856c146103ae57600080fd5b80639aaab648116100a55780639aaab648146102eb578063a25ae557146102fe578063bffa7f0f1461035a57600080fd5b806388786272146102b357806389c44cbb146102c957600080fd5b806369f16eec116101175780636b4d98dd116100fc5780636b4d98dd1461022457806370872aa51461027d5780637f0064201461029357600080fd5b806369f16eec146101fa5780636abcf5631461020f57600080fd5b80622134cc146101485780634599c7881461018f578063529933df146101a457806354fd4d50146101d8575b600080fd5b34801561015457600080fd5b5061017c7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b34801561019b57600080fd5b5061017c610437565b3480156101b057600080fd5b5061017c7f000000000000000000000000000000000000000000000000000000000000000081565b3480156101e457600080fd5b506101ed6104aa565b60405161018691906113f2565b34801561020657600080fd5b5061017c61054d565b34801561021b57600080fd5b5060035461017c565b34801561023057600080fd5b506102587f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610186565b34801561028957600080fd5b5061017c60015481565b34801561029f57600080fd5b5061017c6102ae366004611443565b61055f565b3480156102bf57600080fd5b5061017c60025481565b3480156102d557600080fd5b506102e96102e4366004611443565b610778565b005b6102e96102f936600461145c565b610a4e565b34801561030a57600080fd5b5061031e610319366004611443565b610ecd565b60408051825181526020808401516fffffffffffffffffffffffffffffffff908116918301919091529282015190921690820152606001610186565b34801561036657600080fd5b506102587f000000000000000000000000000000000000000000000000000000000000000081565b34801561039a57600080fd5b5061031e6103a9366004611443565b610f61565b3480156103ba57600080fd5b5061017c6103c9366004611443565b610f99565b3480156103da57600080fd5b5061017c610fe7565b3480156103ef57600080fd5b506102e96103fe36600461148e565b61101c565b34801561040f57600080fd5b5061017c7f000000000000000000000000000000000000000000000000000000000000000081565b600354600090156104a15760038054610452906001906114df565b81548110610462576104626114f6565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b60606104d57f0000000000000000000000000000000000000000000000000000000000000000611285565b6104fe7f0000000000000000000000000000000000000000000000000000000000000000611285565b6105277f0000000000000000000000000000000000000000000000000000000000000000611285565b60405160200161053993929190611525565b604051602081830303815290604052905090565b6003546000906104a5906001906114df565b6000610569610437565b821115610623576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6003546106d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161061a565b6003546000905b8082101561077157600060026106f5838561159b565b6106ff91906115e2565b90508460038281548110610715576107156114f6565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1610156107675761076081600161159b565b925061076b565b8091505b506106df565b5092915050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461083d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161061a565b60035481106108f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161061a565b7f000000000000000000000000000000000000000000000000000000000000000060038281548110610928576109286114f6565b6000918252602090912060016002909202010154610958906fffffffffffffffffffffffffffffffff16426114df565b10610a0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161061a565b6000610a1660035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610b39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161061a565b610b41610fe7565b8314610bf5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161061a565b42610bff84610f99565b10610c8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161061a565b83610d19576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161061a565b8115610dd55781814014610dd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161061a565b82610ddf60035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e242604051610e1191815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b604080516060810182526000808252602082018190529181019190915260038281548110610efd57610efd6114f6565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b60408051606081018252600080825260208201819052918101919091526003610f898361055f565b81548110610efd57610efd6114f6565b60007f000000000000000000000000000000000000000000000000000000000000000060015483610fca91906114df565b610fd491906115f6565b600254610fe1919061159b565b92915050565b60007f0000000000000000000000000000000000000000000000000000000000000000611012610437565b6104a5919061159b565b600054610100900460ff161580801561103c5750600054600160ff909116105b806110565750303b158015611056575060005460ff166001145b6110e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161061a565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561114057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b428211156111f7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161061a565b60028290556001839055801561126457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6060816000036112c857505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156112f257806112dc81611633565b91506112eb9050600a836115e2565b91506112cc565b60008167ffffffffffffffff81111561130d5761130d61166b565b6040519080825280601f01601f191660200182016040528015611337576020820181803683370190505b5090505b84156113ba5761134c6001836114df565b9150611359600a8661169a565b61136490603061159b565b60f81b818381518110611379576113796114f6565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506113b3600a866115e2565b945061133b565b949350505050565b60005b838110156113dd5781810151838201526020016113c5565b838111156113ec576000848401525b50505050565b60208152600082518060208401526114118160408501602087016113c2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60006020828403121561145557600080fd5b5035919050565b6000806000806080858703121561147257600080fd5b5050823594602084013594506040840135936060013592509050565b600080604083850312156114a157600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156114f1576114f16114b0565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600084516115378184602089016113c2565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611573816001850160208a016113c2565b6001920191820152835161158e8160028401602088016113c2565b0160020195945050505050565b600082198211156115ae576115ae6114b0565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826115f1576115f16115b3565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561162e5761162e6114b0565b500290565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611664576116646114b0565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000826116a9576116a96115b3565b50069056fea164736f6c634300080f000a", } // L2OutputOracleABI is the input ABI used to generate the binding from. diff --git a/op-bindings/bindings/optimismportal.go b/op-bindings/bindings/optimismportal.go index da1a5de34129..a1980ea687bf 100644 --- a/op-bindings/bindings/optimismportal.go +++ b/op-bindings/bindings/optimismportal.go @@ -49,7 +49,7 @@ type TypesWithdrawalTransaction struct { // OptimismPortalMetaData contains all meta data concerning the OptimismPortal contract. var OptimismPortalMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_guardian\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_paused\",\"type\":\"bool\"},{\"internalType\":\"contractSystemConfig\",\"name\":\"_config\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"opaqueData\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"WithdrawalProven\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"GUARDIAN\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SYSTEM_CONFIG\",\"outputs\":[{\"internalType\":\"contractSystemConfig\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"donateETH\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structTypes.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_paused\",\"type\":\"bool\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"}],\"name\":\"isOutputFinalized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_byteCount\",\"type\":\"uint64\"}],\"name\":\"minimumGasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"params\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"prevBaseFee\",\"type\":\"uint128\"},{\"internalType\":\"uint64\",\"name\":\"prevBoughtGas\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"prevBlockNum\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structTypes.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"messagePasserStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structTypes.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"_withdrawalProof\",\"type\":\"bytes[]\"}],\"name\":\"proveWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"provenWithdrawals\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2OutputIndex\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x6101406040523480156200001257600080fd5b50604051620059c8380380620059c8833981016040819052620000359162000296565b6001608052600760a052600060c0526001600160a01b0380851660e052838116610120528116610100526200006a8262000074565b5050505062000302565b600054610100900460ff1615808015620000955750600054600160ff909116105b80620000c55750620000b230620001cb60201b62001c891760201c565b158015620000c5575060005460ff166001145b6200012e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000152576000805461ff0019166101001790555b603280546001600160a01b03191661dead1790556035805483151560ff1990911617905562000180620001da565b8015620001c7576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620002475760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000125565b60408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b0217600155565b6001600160a01b03811681146200029357600080fd5b50565b60008060008060808587031215620002ad57600080fd5b8451620002ba816200027d565b6020860151909450620002cd816200027d565b60408601519093508015158114620002e457600080fd5b6060860151909250620002f7816200027d565b939692955090935050565b60805160a05160c05160e051610100516101205161563762000391600039600081816102690152818161079d01526110a00152600081816104c801526123d701526000818161016a01528181610a0601528181610be701528181610ffc015281816113b60152818161162801526121c301526000610f6701526000610f3e01526000610f1501526156376000f3fe60806040526004361061012c5760003560e01c80638c3152e9116100a5578063cff0ab9611610074578063e965084c11610059578063e965084c14610417578063e9e05c42146104a3578063f0498750146104b657600080fd5b8063cff0ab9614610356578063d53a822f146103f757600080fd5b80638c3152e9146102a05780639bf62d82146102c0578063a14238e7146102ed578063a35d99df1461031d57600080fd5b80635c975abb116100fc578063724c184c116100e1578063724c184c146102575780638456cb591461028b5780638b4c40b01461015157600080fd5b80635c975abb1461020d5780636dbffb781461023757600080fd5b80621c2ff6146101585780633f4ba83a146101b65780634870496f146101cb57806354fd4d50146101eb57600080fd5b36610153576101513334620186a06000604051806020016040528060008152506104ea565b005b600080fd5b34801561016457600080fd5b5061018c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101c257600080fd5b50610151610785565b3480156101d757600080fd5b506101516101e6366004614be9565b6108a8565b3480156101f757600080fd5b50610200610f0e565b6040516101ad9190614d3f565b34801561021957600080fd5b506035546102279060ff1681565b60405190151581526020016101ad565b34801561024357600080fd5b50610227610252366004614d52565b610fb1565b34801561026357600080fd5b5061018c7f000000000000000000000000000000000000000000000000000000000000000081565b34801561029757600080fd5b50610151611088565b3480156102ac57600080fd5b506101516102bb366004614d6b565b6111a8565b3480156102cc57600080fd5b5060325461018c9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102f957600080fd5b50610227610308366004614d52565b60336020526000908152604090205460ff1681565b34801561032957600080fd5b5061033d610338366004614db8565b611a83565b60405167ffffffffffffffff90911681526020016101ad565b34801561036257600080fd5b506001546103be906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101ad565b34801561040357600080fd5b50610151610412366004614de3565b611a9c565b34801561042357600080fd5b50610475610432366004614d52565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101ad565b6101516104b1366004614dfe565b6104ea565b3480156104c257600080fd5b5061018c7f000000000000000000000000000000000000000000000000000000000000000081565b8260005a905083156105a15773ffffffffffffffffffffffffffffffffffffffff8716156105a157604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b6105ab8351611a83565b67ffffffffffffffff168567ffffffffffffffff16101561064e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4f7074696d69736d506f7274616c3a20676173206c696d697420746f6f20736d60448201527f616c6c00000000000000000000000000000000000000000000000000000000006064820152608401610598565b6201d4c0835111156106bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4f7074696d69736d506f7274616c3a206461746120746f6f206c6172676500006044820152606401610598565b333281146106dd575033731111000000000000000000000000000000001111015b600034888888886040516020016106f8959493929190614e77565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516107689190614d3f565b60405180910390a4505061077c8282611ca5565b50505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461084a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a206f6e6c7920677561726469616e20636160448201527f6e20756e706175736500000000000000000000000000000000000000000000006064820152608401610598565b603580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60355460ff1615610915576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610598565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036109d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e7472616374006064820152608401610598565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610a62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a869190614efc565b519050610aa0610a9b36869003860186614f61565b611fd2565b8114610b2e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f6600000000000000000000000000000000000000000000006064820152608401610598565b6000610b398761202e565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610c6b5750805160408083015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c679190614efc565b5114155b610cf7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610598565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610dc09101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610db6888a614fc7565b8a6040013561205e565b610e4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610598565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6060610f397f0000000000000000000000000000000000000000000000000000000000000000612082565b610f627f0000000000000000000000000000000000000000000000000000000000000000612082565b610f8b7f0000000000000000000000000000000000000000000000000000000000000000612082565b604051602001610f9d9392919061504b565b604051602081830303815290604052905090565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018290526000906110829073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae55790602401606060405180830381865afa158015611043573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110679190614efc565b602001516fffffffffffffffffffffffffffffffff166121bf565b92915050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461114d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4f7074696d69736d506f7274616c3a206f6e6c7920677561726469616e20636160448201527f6e207061757365000000000000000000000000000000000000000000000000006064820152608401610598565b603580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200161089e565b60355460ff1615611215576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610598565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead146112be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e006064820152608401610598565b60006112c98261202e565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff808216948301859052700100000000000000000000000000000000909104169181019190915292935090036113b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610598565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa15801561141f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144391906150c1565b81602001516fffffffffffffffffffffffffffffffff16101561150e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610598565b61152d81602001516fffffffffffffffffffffffffffffffff166121bf565b6115df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610598565b60408181015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a89190614efc565b8251815191925014611762576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610598565b61178181602001516fffffffffffffffffffffffffffffffff166121bf565b611833576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610598565b60008381526033602052604090205460ff16156118d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610598565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a088015161197493929190612262565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b906119d990841515815260200190565b60405180910390a2801580156119ef5750326001145b15611a7c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a207769746864726177616c206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610598565b5050505050565b6000611a90826010615109565b61108290615208615139565b600054610100900460ff1615808015611abc5750600054600160ff909116105b80611ad65750303b158015611ad6575060005460ff166001145b611b62576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610598565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611bc057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055603580548315157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116179055611c226122c0565b8015611c8557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090611cdb907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643615165565b90506000611ce76123a3565b90506000816020015160ff16826000015163ffffffff16611d0891906151ab565b90508215611e3f57600154600090611d3f908390700100000000000000000000000000000000900467ffffffffffffffff16615213565b90506000836040015160ff1683611d569190615287565b600154611d769084906fffffffffffffffffffffffffffffffff16615287565b611d8091906151ab565b600154909150600090611dd190611daa9084906fffffffffffffffffffffffffffffffff16615343565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612469565b90506001861115611e0057611dfd611daa82876040015160ff1660018a611df89190615165565b612488565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090611e72908490700100000000000000000000000000000000900467ffffffffffffffff16615139565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611f55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d697400006064820152608401610598565b600154600090611f81906fffffffffffffffffffffffffffffffff1667ffffffffffffffff88166153b7565b90506000611f9348633b9aca006124dd565b611f9d90836153f4565b905060005a611fac9088615165565b905080821115611fc857611fc8611fc38284615165565b6124f4565b5050505050505050565b60008160000151826020015183604001518460600151604051602001612011949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097612011979096959101615408565b60008061206a86612522565b905061207881868686612554565b9695505050505050565b6060816000036120c557505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156120ef57806120d98161545f565b91506120e89050600a836153f4565b91506120c9565b60008167ffffffffffffffff81111561210a5761210a614a0f565b6040519080825280601f01601f191660200182016040528015612134576020820181803683370190505b5090505b84156121b757612149600183615165565b9150612156600a86615497565b6121619060306154ab565b60f81b818381518110612176576121766154c3565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506121b0600a866153f4565b9450612138565b949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f4daa2916040518163ffffffff1660e01b8152600401602060405180830381865afa15801561222c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225091906150c1565b61225a90836154ab565b421192915050565b6000806000612272866000612584565b9050806122a8576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b600054610100900460ff16612357576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610598565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663cc731b026040518163ffffffff1660e01b815260040160c060405180830381865afa158015612440573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124649190615517565b905090565b600061247e61247885856125a2565b836125b2565b90505b9392505050565b6000670de0b6b3a76400006124c96124a085836151ab565b6124b290670de0b6b3a7640000615213565b6124c485670de0b6b3a7640000615287565b6125c1565b6124d39086615287565b61247e91906151ab565b6000818310156124ed5781612481565b5090919050565b6000805a90505b825a6125079083615165565b101561251d576125168261545f565b91506124fb565b505050565b6060818051906020012060405160200161253e91815260200190565b6040516020818303038152906040529050919050565b600061257b846125658786866125f2565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156124ed5781612481565b60008183126124ed5781612481565b6000612481670de0b6b3a7640000836125d98661307a565b6125e39190615287565b6125ed91906151ab565b6132be565b6060600084511161265f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610598565b600061266a846134fd565b90506000612677866135ec565b905060008460405160200161268e91815260200190565b60405160208183030381529060405290506000805b8451811015612ff15760008582815181106126c0576126c06154c3565b60200260200101519050845183111561275b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610598565b8260000361281457805180516020918201206040516127a99261278392910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b61280f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610598565b61296b565b8051516020116128ca578051805160209182012060405161283e9261278392910190815260200190565b61280f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610598565b80518451602080870191909120825191909201201461296b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610598565b612977601060016154ab565b81602001515103612b585784518303612af05760006129b382602001516010815181106129a6576129a66154c3565b602002602001015161364f565b90506000815111612a46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610598565b60018751612a549190615165565b8314612ae2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610598565b965061248195505050505050565b6000858481518110612b0457612b046154c3565b602001015160f81c60f81b60f81c9050600082602001518260ff1681518110612b2f57612b2f6154c3565b60200260200101519050612b42816137af565b9550612b4f6001866154ab565b94505050612fde565b600281602001515103612f56576000612b70826137d4565b9050600081600081518110612b8757612b876154c3565b016020015160f81c90506000612b9e6002836155b6565b612ba99060026155d8565b90506000612bba848360ff166137f8565b90506000612bc88a896137f8565b90506000612bd6838361382e565b905080835114612c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610598565b60ff851660021480612c7d575060ff85166003145b15612e715780825114612d12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610598565b6000612d2e88602001516001815181106129a6576129a66154c3565b90506000815111612dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610598565b60018d51612dcf9190615165565b8914612e5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610598565b9c506124819b505050505050505050505050565b60ff85161580612e84575060ff85166001145b15612ec357612eb08760200151600181518110612ea357612ea36154c3565b60200260200101516137af565b9950612ebc818a6154ab565b9850612f4b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610598565b505050505050612fde565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610598565b5080612fe98161545f565b9150506126a3565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610598565b60008082136130e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610598565b600060606130f2846138dd565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136132ef57506000919050565b680755bf798b4a1bf1e58212613361576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610598565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b805160609060008167ffffffffffffffff81111561351d5761351d614a0f565b60405190808252806020026020018201604052801561356257816020015b604080518082019091526060808252602082015281526020019060019003908161353b5790505b50905060005b828110156135e457604051806040016040528086838151811061358d5761358d6154c3565b602002602001015181526020016135bc8784815181106135af576135af6154c3565b60200260200101516139b3565b8152508282815181106135d1576135d16154c3565b6020908102919091010152600101613568565b509392505050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613644578060011b82018184015160001a8060041c8253600f811660018301535050600101613616565b509295945050505050565b6060600080600061365f856139c6565b91945092509050600081600181111561367a5761367a6155fb565b14613707576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d000000000000006064820152608401610598565b61371182846154ab565b8551146137a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e6465720000000000000000000000006064820152608401610598565b61257b85602001518484614433565b606060208260000151106137cb576137c68261364f565b611082565b611082826144d4565b60606110826137f383602001516000815181106129a6576129a66154c3565b6135ec565b6060825182106138175750604080516020810190915260008152611082565b61248183838486516138299190615165565b6144ea565b60008060008351855110613843578351613846565b84515b90505b80821080156138cd5750838281518110613865576138656154c3565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168583815181106138a4576138a46154c3565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156135e457816001019150613849565b6000808211613948576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610598565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60606110826139c1836146c2565b6147ab565b600080600080846000015111613a84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610598565b6020840151805160001a607f8111613aa957600060016000945094509450505061442c565b60b78111613cb7576000613abe608083615165565b905080876000015111613b79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a401610598565b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082141580613bf257507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b613ca4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a401610598565b506001955093506000925061442c915050565b60bf8111614005576000613ccc60b783615165565b905080876000015111613d87576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a401610598565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613e65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a401610598565b600184015160088302610100031c60378111613f29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a401610598565b613f3381846154ab565b895111613fe8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a401610598565b613ff38360016154ab565b975095506000945061442c9350505050565b60f781116140e657600061401a60c083615165565b9050808760000151116140d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a401610598565b60019550935084925061442c915050565b60006140f360f783615165565b9050808760000151116141ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a401610598565b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361428c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a401610598565b600184015160088302610100031c60378111614350576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a401610598565b61435a81846154ab565b89511161440f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a401610598565b61441a8360016154ab565b975095506001945061442c9350505050565b9193909250565b606060008267ffffffffffffffff81111561445057614450614a0f565b6040519080825280601f01601f19166020018201604052801561447a576020820181803683370190505b5090508260000361448c579050612481565b600061449885876154ab565b90506020820160005b858110156144b95782810151828201526020016144a1565b858111156144c8576000868301525b50919695505050505050565b6060611082826020015160008460000151614433565b60608182601f011015614559576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610598565b8282840110156145c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610598565b81830184511015614632576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610598565b60608215801561465157604051915060008252602082016040526146b9565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561468a578051835260209283019201614672565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6040805180820190915260008082526020820152600082511161478d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610598565b50604080518082019091528151815260209182019181019190915290565b606060008060006147bb856139c6565b9194509250905060018160018111156147d6576147d66155fb565b14614863576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d00000000000000006064820152608401610598565b845161486f83856154ab565b146148fc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e64657200000000000000000000000000006064820152608401610598565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816149155790505090506000845b8751811015614a03576000806149886040518060400160405280858d6000015161496c9190615165565b8152602001858d6020015161498191906154ab565b90526139c6565b5091509150604051806040016040528083836149a491906154ab565b8152602001848c602001516149b991906154ab565b8152508585815181106149ce576149ce6154c3565b60209081029190910101526149e46001856154ab565b93506149f081836154ab565b6149fa90846154ab565b92505050614942565b50815295945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614a8557614a85614a0f565b604052919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114614ab157600080fd5b919050565b600082601f830112614ac757600080fd5b813567ffffffffffffffff811115614ae157614ae1614a0f565b614b1260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614a3e565b818152846020838601011115614b2757600080fd5b816020850160208301376000918101602001919091529392505050565b600060c08284031215614b5657600080fd5b60405160c0810167ffffffffffffffff8282108183111715614b7a57614b7a614a0f565b8160405282935084358352614b9160208601614a8d565b6020840152614ba260408601614a8d565b6040840152606085013560608401526080850135608084015260a0850135915080821115614bcf57600080fd5b50614bdc85828601614ab6565b60a0830152505092915050565b600080600080600085870360e0811215614c0257600080fd5b863567ffffffffffffffff80821115614c1a57600080fd5b614c268a838b01614b44565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614c5f57600080fd5b60408901955060c0890135925080831115614c7957600080fd5b828901925089601f840112614c8d57600080fd5b8235915080821115614c9e57600080fd5b508860208260051b8401011115614cb457600080fd5b959894975092955050506020019190565b60005b83811015614ce0578181015183820152602001614cc8565b83811115614cef576000848401525b50505050565b60008151808452614d0d816020860160208601614cc5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006124816020830184614cf5565b600060208284031215614d6457600080fd5b5035919050565b600060208284031215614d7d57600080fd5b813567ffffffffffffffff811115614d9457600080fd5b6121b784828501614b44565b803567ffffffffffffffff81168114614ab157600080fd5b600060208284031215614dca57600080fd5b61248182614da0565b80358015158114614ab157600080fd5b600060208284031215614df557600080fd5b61248182614dd3565b600080600080600060a08688031215614e1657600080fd5b614e1f86614a8d565b945060208601359350614e3460408701614da0565b9250614e4260608701614dd3565b9150608086013567ffffffffffffffff811115614e5e57600080fd5b614e6a88828901614ab6565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251614ecb816049850160208701614cc5565b919091016049019695505050505050565b80516fffffffffffffffffffffffffffffffff81168114614ab157600080fd5b600060608284031215614f0e57600080fd5b6040516060810181811067ffffffffffffffff82111715614f3157614f31614a0f565b60405282518152614f4460208401614edc565b6020820152614f5560408401614edc565b60408201529392505050565b600060808284031215614f7357600080fd5b6040516080810181811067ffffffffffffffff82111715614f9657614f96614a0f565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff80841115614fe257614fe2614a0f565b8360051b6020614ff3818301614a3e565b86815291850191818101903684111561500b57600080fd5b865b8481101561503f578035868111156150255760008081fd5b61503136828b01614ab6565b84525091830191830161500d565b50979650505050505050565b6000845161505d818460208901614cc5565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551615099816001850160208a01614cc5565b600192019182015283516150b4816002840160208801614cc5565b0160020195945050505050565b6000602082840312156150d357600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615615130576151306150da565b02949350505050565b600067ffffffffffffffff80831681851680830382111561515c5761515c6150da565b01949350505050565b600082821015615177576151776150da565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826151ba576151ba61517c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561520e5761520e6150da565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561524d5761524d6150da565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018313811615615281576152816150da565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156152c8576152c86150da565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615303576153036150da565b6000871292508782058712848416161561531f5761531f6150da565b87850587128184161615615335576153356150da565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561537d5761537d6150da565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156153b1576153b16150da565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156153ef576153ef6150da565b500290565b6000826154035761540361517c565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261545360c0830184614cf5565b98975050505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615490576154906150da565b5060010190565b6000826154a6576154a661517c565b500690565b600082198211156154be576154be6150da565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b805163ffffffff81168114614ab157600080fd5b805160ff81168114614ab157600080fd5b600060c0828403121561552957600080fd5b60405160c0810181811067ffffffffffffffff8211171561554c5761554c614a0f565b604052615558836154f2565b815261556660208401615506565b602082015261557760408401615506565b6040820152615588606084016154f2565b6060820152615599608084016154f2565b60808201526155aa60a08401614edc565b60a08201529392505050565b600060ff8316806155c9576155c961517c565b8060ff84160691505092915050565b600060ff821660ff8416808210156155f2576155f26150da565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", + Bin: "0x6101406040523480156200001257600080fd5b50604051620059c8380380620059c8833981016040819052620000359162000296565b60016080819052600760a05260c0526001600160a01b0380851660e052838116610120528116610100526200006a8262000074565b5050505062000302565b600054610100900460ff1615808015620000955750600054600160ff909116105b80620000c55750620000b230620001cb60201b62001c891760201c565b158015620000c5575060005460ff166001145b6200012e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000152576000805461ff0019166101001790555b603280546001600160a01b03191661dead1790556035805483151560ff1990911617905562000180620001da565b8015620001c7576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620002475760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000125565b60408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b0217600155565b6001600160a01b03811681146200029357600080fd5b50565b60008060008060808587031215620002ad57600080fd5b8451620002ba816200027d565b6020860151909450620002cd816200027d565b60408601519093508015158114620002e457600080fd5b6060860151909250620002f7816200027d565b939692955090935050565b60805160a05160c05160e051610100516101205161563762000391600039600081816102690152818161079d01526110a00152600081816104c801526123d701526000818161016a01528181610a0601528181610be701528181610ffc015281816113b60152818161162801526121c301526000610f6701526000610f3e01526000610f1501526156376000f3fe60806040526004361061012c5760003560e01c80638c3152e9116100a5578063cff0ab9611610074578063e965084c11610059578063e965084c14610417578063e9e05c42146104a3578063f0498750146104b657600080fd5b8063cff0ab9614610356578063d53a822f146103f757600080fd5b80638c3152e9146102a05780639bf62d82146102c0578063a14238e7146102ed578063a35d99df1461031d57600080fd5b80635c975abb116100fc578063724c184c116100e1578063724c184c146102575780638456cb591461028b5780638b4c40b01461015157600080fd5b80635c975abb1461020d5780636dbffb781461023757600080fd5b80621c2ff6146101585780633f4ba83a146101b65780634870496f146101cb57806354fd4d50146101eb57600080fd5b36610153576101513334620186a06000604051806020016040528060008152506104ea565b005b600080fd5b34801561016457600080fd5b5061018c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101c257600080fd5b50610151610785565b3480156101d757600080fd5b506101516101e6366004614be9565b6108a8565b3480156101f757600080fd5b50610200610f0e565b6040516101ad9190614d3f565b34801561021957600080fd5b506035546102279060ff1681565b60405190151581526020016101ad565b34801561024357600080fd5b50610227610252366004614d52565b610fb1565b34801561026357600080fd5b5061018c7f000000000000000000000000000000000000000000000000000000000000000081565b34801561029757600080fd5b50610151611088565b3480156102ac57600080fd5b506101516102bb366004614d6b565b6111a8565b3480156102cc57600080fd5b5060325461018c9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102f957600080fd5b50610227610308366004614d52565b60336020526000908152604090205460ff1681565b34801561032957600080fd5b5061033d610338366004614db8565b611a83565b60405167ffffffffffffffff90911681526020016101ad565b34801561036257600080fd5b506001546103be906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101ad565b34801561040357600080fd5b50610151610412366004614de3565b611a9c565b34801561042357600080fd5b50610475610432366004614d52565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101ad565b6101516104b1366004614dfe565b6104ea565b3480156104c257600080fd5b5061018c7f000000000000000000000000000000000000000000000000000000000000000081565b8260005a905083156105a15773ffffffffffffffffffffffffffffffffffffffff8716156105a157604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b6105ab8351611a83565b67ffffffffffffffff168567ffffffffffffffff16101561064e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4f7074696d69736d506f7274616c3a20676173206c696d697420746f6f20736d60448201527f616c6c00000000000000000000000000000000000000000000000000000000006064820152608401610598565b6201d4c0835111156106bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4f7074696d69736d506f7274616c3a206461746120746f6f206c6172676500006044820152606401610598565b333281146106dd575033731111000000000000000000000000000000001111015b600034888888886040516020016106f8959493929190614e77565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516107689190614d3f565b60405180910390a4505061077c8282611ca5565b50505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461084a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a206f6e6c7920677561726469616e20636160448201527f6e20756e706175736500000000000000000000000000000000000000000000006064820152608401610598565b603580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60355460ff1615610915576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610598565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036109d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e7472616374006064820152608401610598565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610a62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a869190614efc565b519050610aa0610a9b36869003860186614f61565b611fd2565b8114610b2e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f6600000000000000000000000000000000000000000000006064820152608401610598565b6000610b398761202e565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610c6b5750805160408083015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c679190614efc565b5114155b610cf7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610598565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610dc09101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610db6888a614fc7565b8a6040013561205e565b610e4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610598565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6060610f397f0000000000000000000000000000000000000000000000000000000000000000612082565b610f627f0000000000000000000000000000000000000000000000000000000000000000612082565b610f8b7f0000000000000000000000000000000000000000000000000000000000000000612082565b604051602001610f9d9392919061504b565b604051602081830303815290604052905090565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018290526000906110829073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae55790602401606060405180830381865afa158015611043573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110679190614efc565b602001516fffffffffffffffffffffffffffffffff166121bf565b92915050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461114d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4f7074696d69736d506f7274616c3a206f6e6c7920677561726469616e20636160448201527f6e207061757365000000000000000000000000000000000000000000000000006064820152608401610598565b603580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200161089e565b60355460ff1615611215576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610598565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead146112be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e006064820152608401610598565b60006112c98261202e565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff808216948301859052700100000000000000000000000000000000909104169181019190915292935090036113b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610598565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa15801561141f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144391906150c1565b81602001516fffffffffffffffffffffffffffffffff16101561150e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610598565b61152d81602001516fffffffffffffffffffffffffffffffff166121bf565b6115df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610598565b60408181015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a89190614efc565b8251815191925014611762576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610598565b61178181602001516fffffffffffffffffffffffffffffffff166121bf565b611833576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610598565b60008381526033602052604090205460ff16156118d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610598565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a088015161197493929190612262565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b906119d990841515815260200190565b60405180910390a2801580156119ef5750326001145b15611a7c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a207769746864726177616c206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610598565b5050505050565b6000611a90826010615109565b61108290615208615139565b600054610100900460ff1615808015611abc5750600054600160ff909116105b80611ad65750303b158015611ad6575060005460ff166001145b611b62576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610598565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611bc057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055603580548315157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116179055611c226122c0565b8015611c8557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090611cdb907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643615165565b90506000611ce76123a3565b90506000816020015160ff16826000015163ffffffff16611d0891906151ab565b90508215611e3f57600154600090611d3f908390700100000000000000000000000000000000900467ffffffffffffffff16615213565b90506000836040015160ff1683611d569190615287565b600154611d769084906fffffffffffffffffffffffffffffffff16615287565b611d8091906151ab565b600154909150600090611dd190611daa9084906fffffffffffffffffffffffffffffffff16615343565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612469565b90506001861115611e0057611dfd611daa82876040015160ff1660018a611df89190615165565b612488565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090611e72908490700100000000000000000000000000000000900467ffffffffffffffff16615139565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611f55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d697400006064820152608401610598565b600154600090611f81906fffffffffffffffffffffffffffffffff1667ffffffffffffffff88166153b7565b90506000611f9348633b9aca006124dd565b611f9d90836153f4565b905060005a611fac9088615165565b905080821115611fc857611fc8611fc38284615165565b6124f4565b5050505050505050565b60008160000151826020015183604001518460600151604051602001612011949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097612011979096959101615408565b60008061206a86612522565b905061207881868686612554565b9695505050505050565b6060816000036120c557505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156120ef57806120d98161545f565b91506120e89050600a836153f4565b91506120c9565b60008167ffffffffffffffff81111561210a5761210a614a0f565b6040519080825280601f01601f191660200182016040528015612134576020820181803683370190505b5090505b84156121b757612149600183615165565b9150612156600a86615497565b6121619060306154ab565b60f81b818381518110612176576121766154c3565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506121b0600a866153f4565b9450612138565b949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f4daa2916040518163ffffffff1660e01b8152600401602060405180830381865afa15801561222c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225091906150c1565b61225a90836154ab565b421192915050565b6000806000612272866000612584565b9050806122a8576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b600054610100900460ff16612357576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610598565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663cc731b026040518163ffffffff1660e01b815260040160c060405180830381865afa158015612440573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124649190615517565b905090565b600061247e61247885856125a2565b836125b2565b90505b9392505050565b6000670de0b6b3a76400006124c96124a085836151ab565b6124b290670de0b6b3a7640000615213565b6124c485670de0b6b3a7640000615287565b6125c1565b6124d39086615287565b61247e91906151ab565b6000818310156124ed5781612481565b5090919050565b6000805a90505b825a6125079083615165565b101561251d576125168261545f565b91506124fb565b505050565b6060818051906020012060405160200161253e91815260200190565b6040516020818303038152906040529050919050565b600061257b846125658786866125f2565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156124ed5781612481565b60008183126124ed5781612481565b6000612481670de0b6b3a7640000836125d98661307a565b6125e39190615287565b6125ed91906151ab565b6132be565b6060600084511161265f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610598565b600061266a846134fd565b90506000612677866135ec565b905060008460405160200161268e91815260200190565b60405160208183030381529060405290506000805b8451811015612ff15760008582815181106126c0576126c06154c3565b60200260200101519050845183111561275b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610598565b8260000361281457805180516020918201206040516127a99261278392910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b61280f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610598565b61296b565b8051516020116128ca578051805160209182012060405161283e9261278392910190815260200190565b61280f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610598565b80518451602080870191909120825191909201201461296b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610598565b612977601060016154ab565b81602001515103612b585784518303612af05760006129b382602001516010815181106129a6576129a66154c3565b602002602001015161364f565b90506000815111612a46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610598565b60018751612a549190615165565b8314612ae2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610598565b965061248195505050505050565b6000858481518110612b0457612b046154c3565b602001015160f81c60f81b60f81c9050600082602001518260ff1681518110612b2f57612b2f6154c3565b60200260200101519050612b42816137af565b9550612b4f6001866154ab565b94505050612fde565b600281602001515103612f56576000612b70826137d4565b9050600081600081518110612b8757612b876154c3565b016020015160f81c90506000612b9e6002836155b6565b612ba99060026155d8565b90506000612bba848360ff166137f8565b90506000612bc88a896137f8565b90506000612bd6838361382e565b905080835114612c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610598565b60ff851660021480612c7d575060ff85166003145b15612e715780825114612d12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610598565b6000612d2e88602001516001815181106129a6576129a66154c3565b90506000815111612dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610598565b60018d51612dcf9190615165565b8914612e5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610598565b9c506124819b505050505050505050505050565b60ff85161580612e84575060ff85166001145b15612ec357612eb08760200151600181518110612ea357612ea36154c3565b60200260200101516137af565b9950612ebc818a6154ab565b9850612f4b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610598565b505050505050612fde565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610598565b5080612fe98161545f565b9150506126a3565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610598565b60008082136130e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610598565b600060606130f2846138dd565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136132ef57506000919050565b680755bf798b4a1bf1e58212613361576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610598565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b805160609060008167ffffffffffffffff81111561351d5761351d614a0f565b60405190808252806020026020018201604052801561356257816020015b604080518082019091526060808252602082015281526020019060019003908161353b5790505b50905060005b828110156135e457604051806040016040528086838151811061358d5761358d6154c3565b602002602001015181526020016135bc8784815181106135af576135af6154c3565b60200260200101516139b3565b8152508282815181106135d1576135d16154c3565b6020908102919091010152600101613568565b509392505050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613644578060011b82018184015160001a8060041c8253600f811660018301535050600101613616565b509295945050505050565b6060600080600061365f856139c6565b91945092509050600081600181111561367a5761367a6155fb565b14613707576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d000000000000006064820152608401610598565b61371182846154ab565b8551146137a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e6465720000000000000000000000006064820152608401610598565b61257b85602001518484614433565b606060208260000151106137cb576137c68261364f565b611082565b611082826144d4565b60606110826137f383602001516000815181106129a6576129a66154c3565b6135ec565b6060825182106138175750604080516020810190915260008152611082565b61248183838486516138299190615165565b6144ea565b60008060008351855110613843578351613846565b84515b90505b80821080156138cd5750838281518110613865576138656154c3565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168583815181106138a4576138a46154c3565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156135e457816001019150613849565b6000808211613948576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610598565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60606110826139c1836146c2565b6147ab565b600080600080846000015111613a84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610598565b6020840151805160001a607f8111613aa957600060016000945094509450505061442c565b60b78111613cb7576000613abe608083615165565b905080876000015111613b79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a401610598565b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082141580613bf257507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b613ca4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a401610598565b506001955093506000925061442c915050565b60bf8111614005576000613ccc60b783615165565b905080876000015111613d87576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a401610598565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613e65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a401610598565b600184015160088302610100031c60378111613f29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a401610598565b613f3381846154ab565b895111613fe8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a401610598565b613ff38360016154ab565b975095506000945061442c9350505050565b60f781116140e657600061401a60c083615165565b9050808760000151116140d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a401610598565b60019550935084925061442c915050565b60006140f360f783615165565b9050808760000151116141ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a401610598565b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361428c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a401610598565b600184015160088302610100031c60378111614350576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a401610598565b61435a81846154ab565b89511161440f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a401610598565b61441a8360016154ab565b975095506001945061442c9350505050565b9193909250565b606060008267ffffffffffffffff81111561445057614450614a0f565b6040519080825280601f01601f19166020018201604052801561447a576020820181803683370190505b5090508260000361448c579050612481565b600061449885876154ab565b90506020820160005b858110156144b95782810151828201526020016144a1565b858111156144c8576000868301525b50919695505050505050565b6060611082826020015160008460000151614433565b60608182601f011015614559576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610598565b8282840110156145c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610598565b81830184511015614632576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610598565b60608215801561465157604051915060008252602082016040526146b9565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561468a578051835260209283019201614672565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6040805180820190915260008082526020820152600082511161478d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610598565b50604080518082019091528151815260209182019181019190915290565b606060008060006147bb856139c6565b9194509250905060018160018111156147d6576147d66155fb565b14614863576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d00000000000000006064820152608401610598565b845161486f83856154ab565b146148fc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e64657200000000000000000000000000006064820152608401610598565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816149155790505090506000845b8751811015614a03576000806149886040518060400160405280858d6000015161496c9190615165565b8152602001858d6020015161498191906154ab565b90526139c6565b5091509150604051806040016040528083836149a491906154ab565b8152602001848c602001516149b991906154ab565b8152508585815181106149ce576149ce6154c3565b60209081029190910101526149e46001856154ab565b93506149f081836154ab565b6149fa90846154ab565b92505050614942565b50815295945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614a8557614a85614a0f565b604052919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114614ab157600080fd5b919050565b600082601f830112614ac757600080fd5b813567ffffffffffffffff811115614ae157614ae1614a0f565b614b1260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614a3e565b818152846020838601011115614b2757600080fd5b816020850160208301376000918101602001919091529392505050565b600060c08284031215614b5657600080fd5b60405160c0810167ffffffffffffffff8282108183111715614b7a57614b7a614a0f565b8160405282935084358352614b9160208601614a8d565b6020840152614ba260408601614a8d565b6040840152606085013560608401526080850135608084015260a0850135915080821115614bcf57600080fd5b50614bdc85828601614ab6565b60a0830152505092915050565b600080600080600085870360e0811215614c0257600080fd5b863567ffffffffffffffff80821115614c1a57600080fd5b614c268a838b01614b44565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614c5f57600080fd5b60408901955060c0890135925080831115614c7957600080fd5b828901925089601f840112614c8d57600080fd5b8235915080821115614c9e57600080fd5b508860208260051b8401011115614cb457600080fd5b959894975092955050506020019190565b60005b83811015614ce0578181015183820152602001614cc8565b83811115614cef576000848401525b50505050565b60008151808452614d0d816020860160208601614cc5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006124816020830184614cf5565b600060208284031215614d6457600080fd5b5035919050565b600060208284031215614d7d57600080fd5b813567ffffffffffffffff811115614d9457600080fd5b6121b784828501614b44565b803567ffffffffffffffff81168114614ab157600080fd5b600060208284031215614dca57600080fd5b61248182614da0565b80358015158114614ab157600080fd5b600060208284031215614df557600080fd5b61248182614dd3565b600080600080600060a08688031215614e1657600080fd5b614e1f86614a8d565b945060208601359350614e3460408701614da0565b9250614e4260608701614dd3565b9150608086013567ffffffffffffffff811115614e5e57600080fd5b614e6a88828901614ab6565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251614ecb816049850160208701614cc5565b919091016049019695505050505050565b80516fffffffffffffffffffffffffffffffff81168114614ab157600080fd5b600060608284031215614f0e57600080fd5b6040516060810181811067ffffffffffffffff82111715614f3157614f31614a0f565b60405282518152614f4460208401614edc565b6020820152614f5560408401614edc565b60408201529392505050565b600060808284031215614f7357600080fd5b6040516080810181811067ffffffffffffffff82111715614f9657614f96614a0f565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff80841115614fe257614fe2614a0f565b8360051b6020614ff3818301614a3e565b86815291850191818101903684111561500b57600080fd5b865b8481101561503f578035868111156150255760008081fd5b61503136828b01614ab6565b84525091830191830161500d565b50979650505050505050565b6000845161505d818460208901614cc5565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551615099816001850160208a01614cc5565b600192019182015283516150b4816002840160208801614cc5565b0160020195945050505050565b6000602082840312156150d357600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615615130576151306150da565b02949350505050565b600067ffffffffffffffff80831681851680830382111561515c5761515c6150da565b01949350505050565b600082821015615177576151776150da565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826151ba576151ba61517c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561520e5761520e6150da565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561524d5761524d6150da565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018313811615615281576152816150da565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156152c8576152c86150da565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615303576153036150da565b6000871292508782058712848416161561531f5761531f6150da565b87850587128184161615615335576153356150da565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561537d5761537d6150da565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156153b1576153b16150da565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156153ef576153ef6150da565b500290565b6000826154035761540361517c565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261545360c0830184614cf5565b98975050505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615490576154906150da565b5060010190565b6000826154a6576154a661517c565b500690565b600082198211156154be576154be6150da565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b805163ffffffff81168114614ab157600080fd5b805160ff81168114614ab157600080fd5b600060c0828403121561552957600080fd5b60405160c0810181811067ffffffffffffffff8211171561554c5761554c614a0f565b604052615558836154f2565b815261556660208401615506565b602082015261557760408401615506565b6040820152615588606084016154f2565b6060820152615599608084016154f2565b60808201526155aa60a08401614edc565b60a08201529392505050565b600060ff8316806155c9576155c961517c565b8060ff84160691505092915050565b600060ff821660ff8416808210156155f2576155f26150da565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", } // OptimismPortalABI is the input ABI used to generate the binding from. diff --git a/op-bindings/bindings/systemconfig.go b/op-bindings/bindings/systemconfig.go index 332797afa12c..9598cd419a41 100644 --- a/op-bindings/bindings/systemconfig.go +++ b/op-bindings/bindings/systemconfig.go @@ -41,7 +41,7 @@ type ResourceMeteringResourceConfig struct { // SystemConfigMetaData contains all meta data concerning the SystemConfig contract. var SystemConfigMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}],\"internalType\":\"structResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"enumSystemConfig.UpdateType\",\"name\":\"updateType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"ConfigUpdate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"UNSAFE_BLOCK_SIGNER_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"batcherHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}],\"internalType\":\"structResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minimumGasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"overhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resourceConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}],\"internalType\":\"structResourceMetering.ResourceConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"scalar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"}],\"name\":\"setBatcherHash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"}],\"name\":\"setGasConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"}],\"name\":\"setGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}],\"internalType\":\"structResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\"}],\"name\":\"setResourceConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"}],\"name\":\"setUnsafeBlockSigner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unsafeBlockSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b50604051620022d2380380620022d2833981016040819052620000349162000859565b6001608052600360a052600060c052620000548787878787878762000061565b5050505050505062000a59565b600054610100900460ff1615808015620000825750600054600160ff909116105b80620000b257506200009f306200027060201b62000adf1760201c565b158015620000b2575060005460ff166001145b6200011b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200013f576000805461ff0019166101001790555b620001496200027f565b6200015488620002e7565b606587905560668690556067859055606880546001600160401b0319166001600160401b038616179055620001a7837f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0855565b620001b28262000366565b620001bc620006bb565b6001600160401b0316846001600160401b031610156200021f5760405162461bcd60e51b815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640162000112565b801562000266576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6001600160a01b03163b151590565b600054610100900460ff16620002db5760405162461bcd60e51b815260206004820152602b6024820152600080516020620022b283398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000112565b620002e5620006e8565b565b620002f16200074f565b6001600160a01b038116620003585760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000112565b6200036381620007ab565b50565b8060a001516001600160801b0316816060015163ffffffff161115620003f55760405162461bcd60e51b815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d617820626173650000000000000000000000606482015260840162000112565b6001816040015160ff1611620004665760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201526e65206c6172676572207468616e203160881b606482015260840162000112565b606854608082015182516001600160401b0390921691620004889190620009a8565b63ffffffff161115620004de5760405162461bcd60e51b815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640162000112565b6000816020015160ff16116200054f5760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201526e06965722063616e6e6f74206265203608c1b606482015260840162000112565b8051602082015163ffffffff82169160ff9091169062000571908290620009d3565b6200057d919062000a05565b63ffffffff1614620005f85760405162461bcd60e51b815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d6974000000000000000000606482015260840162000112565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff96871664ffffffffff199095169490941764010000000060ff948516021764ffffffffff60281b191665010000000000939092169290920263ffffffff60301b19161766010000000000009185169190910217600160501b600160f01b0319166a01000000000000000000009390941692909202600160701b600160f01b03191692909217600160701b6001600160801b0390921691909102179055565b606954600090620006e39063ffffffff6a010000000000000000000082048116911662000a34565b905090565b600054610100900460ff16620007445760405162461bcd60e51b815260206004820152602b6024820152600080516020620022b283398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000112565b620002e533620007ab565b6033546001600160a01b03163314620002e55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000112565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200081557600080fd5b919050565b805163ffffffff811681146200081557600080fd5b805160ff811681146200081557600080fd5b80516001600160801b03811681146200081557600080fd5b60008060008060008060008789036101808112156200087757600080fd5b6200088289620007fd565b60208a015160408b015160608c015160808d0151939b50919950975095506001600160401b038082168214620008b757600080fd5b819550620008c860a08c01620007fd565b945060c060bf1984011215620008dd57600080fd5b604051925060c08301915082821081831117156200090b57634e487b7160e01b600052604160045260246000fd5b506040526200091d60c08a016200081a565b81526200092d60e08a016200082f565b6020820152620009416101008a016200082f565b6040820152620009556101208a016200081a565b6060820152620009696101408a016200081a565b60808201526200097d6101608a0162000841565b60a08201528091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b600063ffffffff808316818516808303821115620009ca57620009ca62000992565b01949350505050565b600063ffffffff80841680620009f957634e487b7160e01b600052601260045260246000fd5b92169190910492915050565b600063ffffffff8083168185168183048111821515161562000a2b5762000a2b62000992565b02949350505050565b60006001600160401b03828116848216808303821115620009ca57620009ca62000992565b60805160a05160c05161182962000a89600039600061056e015260006105450152600061051c01526118296000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c8063b40a817c116100cd578063f2fde38b11610081578063f68016b711610066578063f68016b7146103f7578063f975e9251461040b578063ffa1ad741461041e57600080fd5b8063f2fde38b146103db578063f45e65d8146103ee57600080fd5b8063c9b26f61116100b2578063c9b26f611461028b578063cc731b021461029e578063e81b2c6d146103d257600080fd5b8063b40a817c14610265578063c71973f61461027857600080fd5b80634f16540b11610124578063715018a611610109578063715018a61461022c5780638da5cb5b14610234578063935f029e1461025257600080fd5b80634f16540b146101f057806354fd4d501461021757600080fd5b80630c18c1621461015657806318d13918146101725780631fd19ee1146101875780634add321d146101cf575b600080fd5b61015f60655481565b6040519081526020015b60405180910390f35b610185610180366004611307565b610426565b005b7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08545b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610169565b6101d76104ea565b60405167ffffffffffffffff9091168152602001610169565b61015f7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b61021f610515565b60405161016991906113a3565b6101856105b8565b60335473ffffffffffffffffffffffffffffffffffffffff166101aa565b6101856102603660046113b6565b6105cc565b6101856102733660046113f0565b610665565b610185610286366004611548565b610750565b610185610299366004611564565b610764565b6103626040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516101699190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61015f60675481565b6101856103e9366004611307565b610794565b61015f60665481565b6068546101d79067ffffffffffffffff1681565b61018561041936600461157d565b610848565b61015f600081565b61042e610afb565b610456817f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0855565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516104de91906113a3565b60405180910390a35050565b6069546000906105109063ffffffff6a010000000000000000000082048116911661161f565b905090565b60606105407f0000000000000000000000000000000000000000000000000000000000000000610b7c565b6105697f0000000000000000000000000000000000000000000000000000000000000000610b7c565b6105927f0000000000000000000000000000000000000000000000000000000000000000610b7c565b6040516020016105a49392919061164b565b604051602081830303815290604052905090565b6105c0610afb565b6105ca6000610cb9565b565b6105d4610afb565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161065891906113a3565b60405180910390a3505050565b61066d610afb565b6106756104ea565b67ffffffffffffffff168167ffffffffffffffff1610156106f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064015b60405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff831690811790915560408051602080820193909352815180820390930183528101905260026104ad565b610758610afb565b61076181610d30565b50565b61076c610afb565b60678190556040805160208082018490528251808303909101815290820190915260006104ad565b61079c610afb565b73ffffffffffffffffffffffffffffffffffffffff811661083f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106ee565b61076181610cb9565b600054610100900460ff16158080156108685750600054600160ff909116105b806108825750303b158015610882575060005460ff166001145b61090e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106ee565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561096c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6109746111a4565b61097d88610794565b606587905560668690556067859055606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff86161790557f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c088390556109ed82610d30565b6109f56104ea565b67ffffffffffffffff168467ffffffffffffffff161015610a72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016106ee565b8015610ad557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff1633146105ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106ee565b606081600003610bbf57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610be95780610bd3816116c1565b9150610be29050600a83611728565b9150610bc3565b60008167ffffffffffffffff811115610c0457610c0461140b565b6040519080825280601f01601f191660200182016040528015610c2e576020820181803683370190505b5090505b8415610cb157610c4360018361173c565b9150610c50600a86611753565b610c5b906030611767565b60f81b818381518110610c7057610c7061177f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610caa600a86611728565b9450610c32565b949350505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115610de0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d61782062617365000000000000000000000060648201526084016106ee565b6001816040015160ff1611610e77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e2031000000000000000000000000000000000060648201526084016106ee565b6068546080820151825167ffffffffffffffff90921691610e9891906117ae565b63ffffffff161115610f06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016106ee565b6000816020015160ff1611610f9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f742062652030000000000000000000000000000000000060648201526084016106ee565b8051602082015163ffffffff82169160ff90911690610fbd9082906117cd565b610fc791906117f0565b63ffffffff161461105a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d697400000000000000000060648201526084016106ee565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b600054610100900460ff1661123b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106ee565b6105ca600054610100900460ff166112d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106ee565b6105ca33610cb9565b803573ffffffffffffffffffffffffffffffffffffffff8116811461130257600080fd5b919050565b60006020828403121561131957600080fd5b611322826112de565b9392505050565b60005b8381101561134457818101518382015260200161132c565b83811115611353576000848401525b50505050565b60008151808452611371816020860160208601611329565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006113226020830184611359565b600080604083850312156113c957600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461130257600080fd5b60006020828403121561140257600080fd5b611322826113d8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b803563ffffffff8116811461130257600080fd5b803560ff8116811461130257600080fd5b80356fffffffffffffffffffffffffffffffff8116811461130257600080fd5b600060c0828403121561149157600080fd5b60405160c0810181811067ffffffffffffffff821117156114db577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040529050806114ea8361143a565b81526114f86020840161144e565b60208201526115096040840161144e565b604082015261151a6060840161143a565b606082015261152b6080840161143a565b608082015261153c60a0840161145f565b60a08201525092915050565b600060c0828403121561155a57600080fd5b611322838361147f565b60006020828403121561157657600080fd5b5035919050565b6000806000806000806000610180888a03121561159957600080fd5b6115a2886112de565b96506020880135955060408801359450606088013593506115c5608089016113d8565b92506115d360a089016112de565b91506115e28960c08a0161147f565b905092959891949750929550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff808316818516808303821115611642576116426115f0565b01949350505050565b6000845161165d818460208901611329565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611699816001850160208a01611329565b600192019182015283516116b4816002840160208801611329565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036116f2576116f26115f0565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611737576117376116f9565b500490565b60008282101561174e5761174e6115f0565b500390565b600082611762576117626116f9565b500690565b6000821982111561177a5761177a6115f0565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff808316818516808303821115611642576116426115f0565b600063ffffffff808416806117e4576117e46116f9565b92169190910492915050565b600063ffffffff80831681851681830481118215151615611813576118136115f0565b0294935050505056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", + Bin: "0x60e06040523480156200001157600080fd5b50604051620022d2380380620022d2833981016040819052620000349162000859565b60016080819052600360a05260c052620000548787878787878762000061565b5050505050505062000a59565b600054610100900460ff1615808015620000825750600054600160ff909116105b80620000b257506200009f306200027060201b62000adf1760201c565b158015620000b2575060005460ff166001145b6200011b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200013f576000805461ff0019166101001790555b620001496200027f565b6200015488620002e7565b606587905560668690556067859055606880546001600160401b0319166001600160401b038616179055620001a7837f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0855565b620001b28262000366565b620001bc620006bb565b6001600160401b0316846001600160401b031610156200021f5760405162461bcd60e51b815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640162000112565b801562000266576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6001600160a01b03163b151590565b600054610100900460ff16620002db5760405162461bcd60e51b815260206004820152602b6024820152600080516020620022b283398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000112565b620002e5620006e8565b565b620002f16200074f565b6001600160a01b038116620003585760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000112565b6200036381620007ab565b50565b8060a001516001600160801b0316816060015163ffffffff161115620003f55760405162461bcd60e51b815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d617820626173650000000000000000000000606482015260840162000112565b6001816040015160ff1611620004665760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201526e65206c6172676572207468616e203160881b606482015260840162000112565b606854608082015182516001600160401b0390921691620004889190620009a8565b63ffffffff161115620004de5760405162461bcd60e51b815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640162000112565b6000816020015160ff16116200054f5760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201526e06965722063616e6e6f74206265203608c1b606482015260840162000112565b8051602082015163ffffffff82169160ff9091169062000571908290620009d3565b6200057d919062000a05565b63ffffffff1614620005f85760405162461bcd60e51b815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d6974000000000000000000606482015260840162000112565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff96871664ffffffffff199095169490941764010000000060ff948516021764ffffffffff60281b191665010000000000939092169290920263ffffffff60301b19161766010000000000009185169190910217600160501b600160f01b0319166a01000000000000000000009390941692909202600160701b600160f01b03191692909217600160701b6001600160801b0390921691909102179055565b606954600090620006e39063ffffffff6a010000000000000000000082048116911662000a34565b905090565b600054610100900460ff16620007445760405162461bcd60e51b815260206004820152602b6024820152600080516020620022b283398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000112565b620002e533620007ab565b6033546001600160a01b03163314620002e55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000112565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200081557600080fd5b919050565b805163ffffffff811681146200081557600080fd5b805160ff811681146200081557600080fd5b80516001600160801b03811681146200081557600080fd5b60008060008060008060008789036101808112156200087757600080fd5b6200088289620007fd565b60208a015160408b015160608c015160808d0151939b50919950975095506001600160401b038082168214620008b757600080fd5b819550620008c860a08c01620007fd565b945060c060bf1984011215620008dd57600080fd5b604051925060c08301915082821081831117156200090b57634e487b7160e01b600052604160045260246000fd5b506040526200091d60c08a016200081a565b81526200092d60e08a016200082f565b6020820152620009416101008a016200082f565b6040820152620009556101208a016200081a565b6060820152620009696101408a016200081a565b60808201526200097d6101608a0162000841565b60a08201528091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b600063ffffffff808316818516808303821115620009ca57620009ca62000992565b01949350505050565b600063ffffffff80841680620009f957634e487b7160e01b600052601260045260246000fd5b92169190910492915050565b600063ffffffff8083168185168183048111821515161562000a2b5762000a2b62000992565b02949350505050565b60006001600160401b03828116848216808303821115620009ca57620009ca62000992565b60805160a05160c05161182962000a89600039600061056e015260006105450152600061051c01526118296000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c8063b40a817c116100cd578063f2fde38b11610081578063f68016b711610066578063f68016b7146103f7578063f975e9251461040b578063ffa1ad741461041e57600080fd5b8063f2fde38b146103db578063f45e65d8146103ee57600080fd5b8063c9b26f61116100b2578063c9b26f611461028b578063cc731b021461029e578063e81b2c6d146103d257600080fd5b8063b40a817c14610265578063c71973f61461027857600080fd5b80634f16540b11610124578063715018a611610109578063715018a61461022c5780638da5cb5b14610234578063935f029e1461025257600080fd5b80634f16540b146101f057806354fd4d501461021757600080fd5b80630c18c1621461015657806318d13918146101725780631fd19ee1146101875780634add321d146101cf575b600080fd5b61015f60655481565b6040519081526020015b60405180910390f35b610185610180366004611307565b610426565b005b7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08545b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610169565b6101d76104ea565b60405167ffffffffffffffff9091168152602001610169565b61015f7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b61021f610515565b60405161016991906113a3565b6101856105b8565b60335473ffffffffffffffffffffffffffffffffffffffff166101aa565b6101856102603660046113b6565b6105cc565b6101856102733660046113f0565b610665565b610185610286366004611548565b610750565b610185610299366004611564565b610764565b6103626040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516101699190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61015f60675481565b6101856103e9366004611307565b610794565b61015f60665481565b6068546101d79067ffffffffffffffff1681565b61018561041936600461157d565b610848565b61015f600081565b61042e610afb565b610456817f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0855565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516104de91906113a3565b60405180910390a35050565b6069546000906105109063ffffffff6a010000000000000000000082048116911661161f565b905090565b60606105407f0000000000000000000000000000000000000000000000000000000000000000610b7c565b6105697f0000000000000000000000000000000000000000000000000000000000000000610b7c565b6105927f0000000000000000000000000000000000000000000000000000000000000000610b7c565b6040516020016105a49392919061164b565b604051602081830303815290604052905090565b6105c0610afb565b6105ca6000610cb9565b565b6105d4610afb565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161065891906113a3565b60405180910390a3505050565b61066d610afb565b6106756104ea565b67ffffffffffffffff168167ffffffffffffffff1610156106f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064015b60405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff831690811790915560408051602080820193909352815180820390930183528101905260026104ad565b610758610afb565b61076181610d30565b50565b61076c610afb565b60678190556040805160208082018490528251808303909101815290820190915260006104ad565b61079c610afb565b73ffffffffffffffffffffffffffffffffffffffff811661083f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106ee565b61076181610cb9565b600054610100900460ff16158080156108685750600054600160ff909116105b806108825750303b158015610882575060005460ff166001145b61090e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106ee565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561096c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6109746111a4565b61097d88610794565b606587905560668690556067859055606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff86161790557f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c088390556109ed82610d30565b6109f56104ea565b67ffffffffffffffff168467ffffffffffffffff161015610a72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016106ee565b8015610ad557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff1633146105ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106ee565b606081600003610bbf57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610be95780610bd3816116c1565b9150610be29050600a83611728565b9150610bc3565b60008167ffffffffffffffff811115610c0457610c0461140b565b6040519080825280601f01601f191660200182016040528015610c2e576020820181803683370190505b5090505b8415610cb157610c4360018361173c565b9150610c50600a86611753565b610c5b906030611767565b60f81b818381518110610c7057610c7061177f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610caa600a86611728565b9450610c32565b949350505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115610de0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d61782062617365000000000000000000000060648201526084016106ee565b6001816040015160ff1611610e77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e2031000000000000000000000000000000000060648201526084016106ee565b6068546080820151825167ffffffffffffffff90921691610e9891906117ae565b63ffffffff161115610f06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016106ee565b6000816020015160ff1611610f9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f742062652030000000000000000000000000000000000060648201526084016106ee565b8051602082015163ffffffff82169160ff90911690610fbd9082906117cd565b610fc791906117f0565b63ffffffff161461105a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d697400000000000000000060648201526084016106ee565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b600054610100900460ff1661123b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106ee565b6105ca600054610100900460ff166112d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106ee565b6105ca33610cb9565b803573ffffffffffffffffffffffffffffffffffffffff8116811461130257600080fd5b919050565b60006020828403121561131957600080fd5b611322826112de565b9392505050565b60005b8381101561134457818101518382015260200161132c565b83811115611353576000848401525b50505050565b60008151808452611371816020860160208601611329565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006113226020830184611359565b600080604083850312156113c957600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461130257600080fd5b60006020828403121561140257600080fd5b611322826113d8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b803563ffffffff8116811461130257600080fd5b803560ff8116811461130257600080fd5b80356fffffffffffffffffffffffffffffffff8116811461130257600080fd5b600060c0828403121561149157600080fd5b60405160c0810181811067ffffffffffffffff821117156114db577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040529050806114ea8361143a565b81526114f86020840161144e565b60208201526115096040840161144e565b604082015261151a6060840161143a565b606082015261152b6080840161143a565b608082015261153c60a0840161145f565b60a08201525092915050565b600060c0828403121561155a57600080fd5b611322838361147f565b60006020828403121561157657600080fd5b5035919050565b6000806000806000806000610180888a03121561159957600080fd5b6115a2886112de565b96506020880135955060408801359450606088013593506115c5608089016113d8565b92506115d360a089016112de565b91506115e28960c08a0161147f565b905092959891949750929550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff808316818516808303821115611642576116426115f0565b01949350505050565b6000845161165d818460208901611329565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611699816001850160208a01611329565b600192019182015283516116b4816002840160208801611329565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036116f2576116f26115f0565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611737576117376116f9565b500490565b60008282101561174e5761174e6115f0565b500390565b600082611762576117626116f9565b500690565b6000821982111561177a5761177a6115f0565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff808316818516808303821115611642576116426115f0565b600063ffffffff808416806117e4576117e46116f9565b92169190910492915050565b600063ffffffff80831681851681830481118215151615611813576118136115f0565b0294935050505056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", } // SystemConfigABI is the input ABI used to generate the binding from. diff --git a/op-bootnode/bootnode/entrypoint.go b/op-bootnode/bootnode/entrypoint.go index ed7a9c0e0486..1fd4be0a5b61 100644 --- a/op-bootnode/bootnode/entrypoint.go +++ b/op-bootnode/bootnode/entrypoint.go @@ -16,7 +16,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/libp2p/go-libp2p/core/peer" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) type gossipNoop struct{} diff --git a/op-bootnode/cmd/main.go b/op-bootnode/cmd/main.go index 4ddcf528d599..f50df72208cf 100644 --- a/op-bootnode/cmd/main.go +++ b/op-bootnode/cmd/main.go @@ -6,7 +6,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bootnode/bootnode" "github.com/ethereum-optimism/optimism/op-bootnode/flags" "github.com/ethereum/go-ethereum/log" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) func main() { diff --git a/op-bootnode/flags/flags.go b/op-bootnode/flags/flags.go index 9a794ae03544..eaf02530f93c 100644 --- a/op-bootnode/flags/flags.go +++ b/op-bootnode/flags/flags.go @@ -8,21 +8,25 @@ import ( "github.com/ethereum-optimism/optimism/op-node/flags" opservice "github.com/ethereum-optimism/optimism/op-service" oplog "github.com/ethereum-optimism/optimism/op-service/log" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) const envVarPrefix = "OP_BOOTNODE" +func prefixEnvVars(name string) []string { + return opservice.PrefixEnvVar(envVarPrefix, name) +} + var ( - RollupConfig = cli.StringFlag{ - Name: flags.RollupConfig.Name, - Usage: "Rollup chain parameters", - EnvVar: opservice.PrefixEnvVar(envVarPrefix, "ROLLUP_CONFIG"), + RollupConfig = &cli.StringFlag{ + Name: flags.RollupConfig.Name, + Usage: "Rollup chain parameters", + EnvVars: prefixEnvVars("ROLLUP_CONFIG"), } - Network = cli.StringFlag{ - Name: flags.Network.Name, - Usage: fmt.Sprintf("Predefined network selection. Available networks: %s", strings.Join(chaincfg.AvailableNetworks(), ", ")), - EnvVar: opservice.PrefixEnvVar(envVarPrefix, "NETWORK"), + Network = &cli.StringFlag{ + Name: flags.Network.Name, + Usage: fmt.Sprintf("Predefined network selection. Available networks: %s", strings.Join(chaincfg.AvailableNetworks(), ", ")), + EnvVars: prefixEnvVars("NETWORK"), } ) diff --git a/op-challenger/cmd/main.go b/op-challenger/cmd/main.go index 12d86a451422..8f17980c8190 100644 --- a/op-challenger/cmd/main.go +++ b/op-challenger/cmd/main.go @@ -4,7 +4,7 @@ import ( "os" log "github.com/ethereum/go-ethereum/log" - cli "github.com/urfave/cli" + cli "github.com/urfave/cli/v2" watch "github.com/ethereum-optimism/optimism/op-challenger/cmd/watch" config "github.com/ethereum-optimism/optimism/op-challenger/config" @@ -70,7 +70,7 @@ func run(args []string, action ConfigAction) error { } return action(logger, VersionWithMeta, cfg) } - app.Commands = []cli.Command{ + app.Commands = []*cli.Command{ { Name: "watch", Subcommands: watch.Subcommands, diff --git a/op-challenger/cmd/watch/cmd.go b/op-challenger/cmd/watch/cmd.go index 788a4c18089d..c095f4e5d7d2 100644 --- a/op-challenger/cmd/watch/cmd.go +++ b/op-challenger/cmd/watch/cmd.go @@ -1,7 +1,7 @@ package watch import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/op-challenger/config" ) diff --git a/op-challenger/config/config.go b/op-challenger/config/config.go index dd069ed8a734..1a70202721ba 100644 --- a/op-challenger/config/config.go +++ b/op-challenger/config/config.go @@ -5,7 +5,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" flags "github.com/ethereum-optimism/optimism/op-challenger/flags" @@ -141,19 +141,19 @@ func NewConfigFromCLI(ctx *cli.Context) (*Config, error) { if err := flags.CheckRequired(ctx); err != nil { return nil, err } - l1EthRpc := ctx.GlobalString(flags.L1EthRpcFlag.Name) + l1EthRpc := ctx.String(flags.L1EthRpcFlag.Name) if l1EthRpc == "" { return nil, ErrMissingL1EthRPC } - rollupRpc := ctx.GlobalString(flags.RollupRpcFlag.Name) + rollupRpc := ctx.String(flags.RollupRpcFlag.Name) if rollupRpc == "" { return nil, ErrMissingRollupRpc } - l2ooAddress, err := opservice.ParseAddress(ctx.GlobalString(flags.L2OOAddressFlag.Name)) + l2ooAddress, err := opservice.ParseAddress(ctx.String(flags.L2OOAddressFlag.Name)) if err != nil { return nil, ErrMissingL2OOAddress } - dgfAddress, err := opservice.ParseAddress(ctx.GlobalString(flags.DGFAddressFlag.Name)) + dgfAddress, err := opservice.ParseAddress(ctx.String(flags.DGFAddressFlag.Name)) if err != nil { return nil, ErrMissingDGFAddress } diff --git a/op-challenger/config/logging.go b/op-challenger/config/logging.go index 1df856c118d1..54d869b2df8e 100644 --- a/op-challenger/config/logging.go +++ b/op-challenger/config/logging.go @@ -4,7 +4,7 @@ import ( "fmt" log "github.com/ethereum/go-ethereum/log" - cli "github.com/urfave/cli" + cli "github.com/urfave/cli/v2" oplog "github.com/ethereum-optimism/optimism/op-service/log" ) diff --git a/op-challenger/fault/alphabet_provider_test.go b/op-challenger/fault/alphabet_provider_test.go index 7af521abbe03..abc36ca28850 100644 --- a/op-challenger/fault/alphabet_provider_test.go +++ b/op-challenger/fault/alphabet_provider_test.go @@ -8,6 +8,38 @@ import ( "github.com/stretchr/testify/require" ) +// TestAlphabetProvider_Get_ClaimsByTraceIndex tests the [fault.AlphabetProvider] Get function. +func TestAlphabetProvider_Get_ClaimsByTraceIndex(t *testing.T) { + // Create a new alphabet provider. + canonicalProvider := NewAlphabetProvider("abcdefgh", uint64(3)) + + // Build a list of traces. + traces := []struct { + traceIndex uint64 + expectedHash common.Hash + }{ + { + 7, + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000768"), + }, + { + 3, + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000364"), + }, + { + 5, + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000566"), + }, + } + + // Execute each trace and check the alphabet provider returns the expected hash. + for _, trace := range traces { + expectedHash, err := canonicalProvider.Get(trace.traceIndex) + require.NoError(t, err) + require.Equal(t, trace.expectedHash, expectedHash) + } +} + // FuzzIndexToBytes tests the IndexToBytes function. func FuzzIndexToBytes(f *testing.F) { f.Fuzz(func(t *testing.T, index uint64) { diff --git a/op-challenger/fault/cmd/examples/position.go b/op-challenger/fault/cmd/examples/position.go new file mode 100644 index 000000000000..cb40c86a9167 --- /dev/null +++ b/op-challenger/fault/cmd/examples/position.go @@ -0,0 +1,35 @@ +package examples + +import ( + "github.com/ethereum-optimism/optimism/op-challenger/fault" +) + +func PositionExampleOne() { + // Example 1 + // abcdefgh + // abcdexyz + // go left to d, then right to f, then left to e + p := fault.Position{} + p.Print(3) + p = p.Attack() + p.Print(3) + p = p.Defend() + p.Print(3) + p = p.Attack() + p.Print(3) +} + +func PositionExampleTwo() { + // Example 2 + // abcdefgh + // abqrstuv + // go left r, then left to b, then right to q + p := fault.Position{} + p.Print(3) + p = p.Attack() + p.Print(3) + p = p.Attack() + p.Print(3) + p = p.Defend() + p.Print(3) +} diff --git a/op-challenger/fault/cmd/examples/solver.go b/op-challenger/fault/cmd/examples/solver.go new file mode 100644 index 000000000000..80f5208d0b8b --- /dev/null +++ b/op-challenger/fault/cmd/examples/solver.go @@ -0,0 +1,83 @@ +package examples + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/ethereum-optimism/optimism/op-challenger/fault" +) + +// SolverExampleOne uses the [fault.Solver] with a [fault.AlphabetProvider] +// to print out fault game traces for the "abcdexyz" counter-state. +func SolverExampleOne() { + fmt.Println() + fmt.Println("Solver: Example 1") + fmt.Println() + + // Construct the fault position. + canonical := "abcdefgh" + disputed := "abcdexyz" + maxDepth := 3 + parent := fault.Claim{ + Value: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000768"), + Position: fault.NewPosition(0, 0), + } + canonicalProvider := fault.NewAlphabetProvider(canonical, uint64(maxDepth)) + disputedProvider := fault.NewAlphabetProvider(disputed, uint64(maxDepth)) + + // Create a solver with the canonical provider. + solver := fault.NewSolver(maxDepth, canonicalProvider) + + // Print the initial state. + fmt.Println("Canonical state: ", canonical) + fmt.Println("Disputed state: ", disputed) + fmt.Println() + fmt.Println("Proceeding with the following moves:") + fmt.Println("go left to d, then right to f, then left to e") + fmt.Println() + + // Get the claim from the disputed provider. + claim, err := disputedProvider.Get(3) + if err != nil { + fmt.Printf("error getting claim from disputed provider: %v", err) + } + firstDisputedClaim := fault.Claim{ + Value: claim, + Position: fault.NewPosition(1, 0), + } + res, err := solver.NextMove(firstDisputedClaim, parent) + if err != nil { + fmt.Printf("error getting next move: %v", err) + } + fmt.Printf("Disputed claim: %s\n", claim) + fmt.Printf("Expected claim: %s\n", parent.Value) + fmt.Printf("Response: [Attack: %v, Value: %s]\n", res.Attack, res.Value) + fmt.Println() + + // Get the next claim from the disputed provider. + claim, err = disputedProvider.Get(5) + if err != nil { + fmt.Printf("error getting claim from disputed provider: %v", err) + } + firstDisputedClaim = fault.Claim{ + Value: claim, + Position: fault.NewPosition(2, 2), + } + res, err = solver.NextMove(firstDisputedClaim, parent) + if err != nil { + fmt.Printf("error getting next move: %v", err) + } + fmt.Printf("Disputed claim: %s\n", claim) + fmt.Printf("Expected claim: %s\n", parent.Value) + fmt.Printf("Response: [Attack: %v, Value: %s]\n", res.Attack, res.Value) + fmt.Println() + + // This marks the end of the game! + if res.Attack { + fmt.Println("Game successfully completed!") + } else { + fmt.Println("Game failed!") + } + fmt.Println() +} diff --git a/op-challenger/fault/cmd/main.go b/op-challenger/fault/cmd/main.go index f2b91dac14ed..49683641e82e 100644 --- a/op-challenger/fault/cmd/main.go +++ b/op-challenger/fault/cmd/main.go @@ -1,43 +1,12 @@ package main import ( - "github.com/ethereum-optimism/optimism/op-challenger/fault" + "github.com/ethereum-optimism/optimism/op-challenger/fault/cmd/examples" ) func main() { - // Example 1 - // abcdefgh - // abcdexyz - // go left to d, then right to f, then left to e - p := fault.Position{} - p.Print(3) - p.Attack() - p.Print(3) - p.Defend() - p.Print(3) - p.Attack() - p.Print(3) + examples.SolverExampleOne() - // Trace Position is 0000 Trace Depth is: 0 Trace Index is: 8 - // Trace Position is 0000 Trace Depth is: 1 Trace Index is: 4 - // Trace Position is 0010 Trace Depth is: 2 Trace Index is: 6 - // Trace Position is 0100 Trace Depth is: 3 Trace Index is: 5 - - // Example 2 - // abcdefgh - // abqrstuv - // go left r, then left to b, then right to q - p = fault.Position{} - p.Print(3) - p.Attack() - p.Print(3) - p.Attack() - p.Print(3) - p.Defend() - p.Print(3) - - // Trace Position is 0000 Trace Depth is: 0 Trace Index is: 8 - // Trace Position is 0000 Trace Depth is: 1 Trace Index is: 4 - // Trace Position is 0000 Trace Depth is: 2 Trace Index is: 2 - // Trace Position is 0010 Trace Depth is: 3 Trace Index is: 3 + // examples.PositionExampleOne() + // examples.PositionExampleTwo() } diff --git a/op-challenger/fault/game.go b/op-challenger/fault/game.go new file mode 100644 index 000000000000..710399a5742b --- /dev/null +++ b/op-challenger/fault/game.go @@ -0,0 +1,13 @@ +package fault + +// Game is an interface that represents the state of a dispute game. +type Game interface { + // Put adds a claim into the game state and returns its parent claim. + Put(claim Claim) (Claim, error) + + // ClaimPairs returns a list of claim pairs. + ClaimPairs() []struct { + claim Claim + parent Claim + } +} diff --git a/op-challenger/fault/position.go b/op-challenger/fault/position.go index 24348f406134..b734b1cadccf 100644 --- a/op-challenger/fault/position.go +++ b/op-challenger/fault/position.go @@ -3,36 +3,42 @@ package fault import "fmt" // Position is a golang wrapper around the dispute game Position type. -// Depth refers to how many bisection steps have occurred. -// IndexAtDepth refers to the path that the bisection has taken -// where 1 = goes right & 0 = goes left. type Position struct { - Depth int - IndexAtDepth int -} - -// TraceIndex calculates the what the index of the claim value -// would be inside the trace. -func (p *Position) TraceIndex(maxDepth int) int { - lo := 0 - hi := 1 << maxDepth - mid := hi - path := p.IndexAtDepth - for i := p.Depth - 1; i >= 0; i-- { - mid = (lo + hi) / 2 - mask := 1 << i - if path&mask == mask { - lo = mid - } else { - hi = mid - } - } - return mid + depth int + indexAtDepth int +} + +func NewPosition(depth, indexAtDepth int) Position { + return Position{depth, indexAtDepth} +} + +func NewPositionFromGIndex(x uint64) Position { + depth := MSBIndex(x) + indexAtDepth := ^(1 << depth) & x + return NewPosition(depth, int(indexAtDepth)) +} + +func (p *Position) Depth() int { + return p.depth +} + +func (p *Position) IndexAtDepth() int { + return p.indexAtDepth } +// TraceIndex calculates the what the index of the claim value would be inside the trace. +// It is equivalent to going right until the final depth has been reached. +func (p *Position) TraceIndex(maxDepth int) uint64 { + // When we go right, we do a shift left and set the bottom bit to be 1. + // To do this in a single step, do all the shifts at once & or in all 1s for the bottom bits. + rd := maxDepth - p.depth + return uint64(p.indexAtDepth<> 1 + p.depth-- + p.indexAtDepth = p.indexAtDepth >> 1 } -func (p *Position) Attack() { - p.move(false) +// Attack creates a new position which is the attack position of this one. +func (p *Position) Attack() Position { + p2 := NewPosition(p.depth, p.indexAtDepth) + p2.move(false) + return p2 } -func (p *Position) Defend() { - p.parent() - p.move(true) - p.move(false) +// Defend creates a new position which is the defend position of this one. +func (p *Position) Defend() Position { + p2 := NewPosition(p.depth, p.indexAtDepth) + p2.parent() + p2.move(true) + p2.move(false) + return p2 } func (p *Position) Print(maxDepth int) { - fmt.Printf("Trace Position is %04b\tTrace Depth is: %d\tTrace Index is: %d\n", p.IndexAtDepth, p.Depth, p.TraceIndex(maxDepth)) + fmt.Printf("GIN: %4b\tTrace Position is %4b\tTrace Depth is: %d\tTrace Index is: %d\n", p.ToGIndex(), p.indexAtDepth, p.depth, p.TraceIndex(maxDepth)) +} + +func (p *Position) ToGIndex() uint64 { + return uint64(1<> 1 + } + return out - 1 } diff --git a/op-challenger/fault/position_test.go b/op-challenger/fault/position_test.go index d271179e16db..dba505f92c0e 100644 --- a/op-challenger/fault/position_test.go +++ b/op-challenger/fault/position_test.go @@ -1 +1,97 @@ package fault + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestMSBIndex(t *testing.T) { + tests := []struct { + input uint64 + expected int + }{ + {0, 0}, + {1, 0}, + {2, 1}, + {4, 2}, + {8, 3}, + {16, 4}, + {255, 7}, + {1024, 10}, + {18446744073709551615, 63}, + } + + for _, test := range tests { + result := MSBIndex(test.input) + if result != test.expected { + t.Errorf("MSBIndex(%d) expected %d, but got %d", test.input, test.expected, result) + } + } + +} + +type testNodeInfo struct { + GIndex uint64 + Depth int + IndexAtDepth int + TraceIndex uint64 +} + +var treeNodesMaxDepth4 = []testNodeInfo{ + {GIndex: 1, Depth: 0, IndexAtDepth: 0, TraceIndex: 15}, + + {GIndex: 2, Depth: 1, IndexAtDepth: 0, TraceIndex: 7}, + {GIndex: 3, Depth: 1, IndexAtDepth: 1, TraceIndex: 15}, + + {GIndex: 4, Depth: 2, IndexAtDepth: 0, TraceIndex: 3}, + {GIndex: 5, Depth: 2, IndexAtDepth: 1, TraceIndex: 7}, + {GIndex: 6, Depth: 2, IndexAtDepth: 2, TraceIndex: 11}, + {GIndex: 7, Depth: 2, IndexAtDepth: 3, TraceIndex: 15}, + + {GIndex: 8, Depth: 3, IndexAtDepth: 0, TraceIndex: 1}, + {GIndex: 9, Depth: 3, IndexAtDepth: 1, TraceIndex: 3}, + {GIndex: 10, Depth: 3, IndexAtDepth: 2, TraceIndex: 5}, + {GIndex: 11, Depth: 3, IndexAtDepth: 3, TraceIndex: 7}, + {GIndex: 12, Depth: 3, IndexAtDepth: 4, TraceIndex: 9}, + {GIndex: 13, Depth: 3, IndexAtDepth: 5, TraceIndex: 11}, + {GIndex: 14, Depth: 3, IndexAtDepth: 6, TraceIndex: 13}, + {GIndex: 15, Depth: 3, IndexAtDepth: 7, TraceIndex: 15}, + + {GIndex: 16, Depth: 4, IndexAtDepth: 0, TraceIndex: 0}, + {GIndex: 17, Depth: 4, IndexAtDepth: 1, TraceIndex: 1}, + {GIndex: 18, Depth: 4, IndexAtDepth: 2, TraceIndex: 2}, + {GIndex: 19, Depth: 4, IndexAtDepth: 3, TraceIndex: 3}, + {GIndex: 20, Depth: 4, IndexAtDepth: 4, TraceIndex: 4}, + {GIndex: 21, Depth: 4, IndexAtDepth: 5, TraceIndex: 5}, + {GIndex: 22, Depth: 4, IndexAtDepth: 6, TraceIndex: 6}, + {GIndex: 23, Depth: 4, IndexAtDepth: 7, TraceIndex: 7}, + {GIndex: 24, Depth: 4, IndexAtDepth: 8, TraceIndex: 8}, + {GIndex: 25, Depth: 4, IndexAtDepth: 9, TraceIndex: 9}, + {GIndex: 26, Depth: 4, IndexAtDepth: 10, TraceIndex: 10}, + {GIndex: 27, Depth: 4, IndexAtDepth: 11, TraceIndex: 11}, + {GIndex: 28, Depth: 4, IndexAtDepth: 12, TraceIndex: 12}, + {GIndex: 29, Depth: 4, IndexAtDepth: 13, TraceIndex: 13}, + {GIndex: 30, Depth: 4, IndexAtDepth: 14, TraceIndex: 14}, + {GIndex: 31, Depth: 4, IndexAtDepth: 15, TraceIndex: 15}, +} + +// TestGINConversions does To & From the generalized index on the treeNodesMaxDepth4 data +func TestGINConversions(t *testing.T) { + for _, test := range treeNodesMaxDepth4 { + from := NewPositionFromGIndex(test.GIndex) + pos := NewPosition(test.Depth, test.IndexAtDepth) + require.Equal(t, pos, from) + to := pos.ToGIndex() + require.Equal(t, test.GIndex, to) + } +} + +// TestTraceIndex creates the position & then tests the trace index function on the treeNodesMaxDepth4 data +func TestTraceIndex(t *testing.T) { + for _, test := range treeNodesMaxDepth4 { + pos := NewPosition(test.Depth, test.IndexAtDepth) + result := pos.TraceIndex(4) + require.Equal(t, test.TraceIndex, result) + } +} diff --git a/op-challenger/fault/solver.go b/op-challenger/fault/solver.go new file mode 100644 index 000000000000..b3543910a6eb --- /dev/null +++ b/op-challenger/fault/solver.go @@ -0,0 +1,88 @@ +package fault + +import ( + "errors" + + "github.com/ethereum/go-ethereum/common" +) + +// Solver uses a [TraceProvider] to determine the moves to make in a dispute game. +type Solver struct { + TraceProvider + + gameDepth int +} + +// NewSolver creates a new [Solver] using the provided [TraceProvider]. +func NewSolver(gameDepth int, traceProvider TraceProvider) *Solver { + return &Solver{ + traceProvider, + gameDepth, + } +} + +// NextMove returns the next move to make given the current state of the game. +func (s *Solver) NextMove(claim Claim, parent Claim) (*Response, error) { + parentCorrect, err := s.agreeWithClaim(parent) + if err != nil { + return nil, err + } + claimCorrect, err := s.agreeWithClaim(claim) + if err != nil { + return nil, err + } + if parentCorrect && claimCorrect { + // We agree with the parent, but the claim is disagreeing with it. + // Since we agree with the claim, the difference must be to the right of the claim + return s.defend(claim) + } else if parentCorrect && !claimCorrect { + // We agree with the parent, but the claim disagrees with it. + // Since we disagree with the claim, the difference must be to the left of the claim + return s.attack(claim) + } else if !parentCorrect && claimCorrect { + // Do nothing, we disagree with the parent, but this claim has correctly countered it + return s.doNothing() + } else if !parentCorrect && !claimCorrect { + // We disagree with the parent so want to counter it (which the claim is doing) + // but we also disagree with the claim so there must be a difference to the left of claim + // Note that we will create the correct counter-claim for parent when it is evaluated, no need to do it here + return s.attack(claim) + } + // This should not be reached + return nil, errors.New("no next move") +} + +func (s *Solver) doNothing() (*Response, error) { + return nil, nil +} + +// attack returns a response that attacks the claim. +func (s *Solver) attack(claim Claim) (*Response, error) { + value, err := s.traceAtPosition(claim.Attack()) + if err != nil { + return nil, err + } + return &Response{Attack: true, Value: value}, nil +} + +// defend returns a response that defends the claim. +func (s *Solver) defend(claim Claim) (*Response, error) { + value, err := s.traceAtPosition(claim.Defend()) + if err != nil { + return nil, err + } + return &Response{Attack: false, Value: value}, nil +} + +// agreeWithClaim returns true if the [Claim] is correct according to the internal [TraceProvider]. +func (s *Solver) agreeWithClaim(claim Claim) (bool, error) { + ourValue, err := s.traceAtPosition(claim.Position) + return ourValue == claim.Value, err +} + +// traceAtPosition returns the [common.Hash] from internal [TraceProvider] at the given [Position]. +func (s *Solver) traceAtPosition(p Position) (common.Hash, error) { + index := p.TraceIndex(s.gameDepth) + hash, err := s.Get(index) + return hash, err +} diff --git a/op-challenger/fault/solver_test.go b/op-challenger/fault/solver_test.go new file mode 100644 index 000000000000..614711fdb801 --- /dev/null +++ b/op-challenger/fault/solver_test.go @@ -0,0 +1,63 @@ +package fault + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +// TestSolver_NextMove_Opponent tests the [Solver] NextMove function +// with an [fault.AlphabetProvider] as the [TraceProvider]. +func TestSolver_NextMove_Opponent(t *testing.T) { + // Construct the solver. + maxDepth := 3 + canonicalProvider := NewAlphabetProvider("abcdefgh", uint64(maxDepth)) + solver := NewSolver(maxDepth, canonicalProvider) + + // The following claims are created using the state: "abcdexyz". + // The responses are the responses we expect from the solver. + indices := []struct { + traceIndex int + claim Claim + parent Claim + response *Response + }{ + { + 3, + Claim{ + Value: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000364"), + Position: NewPosition(1, 0), + }, + Claim{ + Value: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000768"), + Position: NewPosition(0, 0), + }, + &Response{ + Attack: false, + Value: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000566"), + }, + }, + { + 5, + Claim{ + Value: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000578"), + Position: NewPosition(2, 2), + }, + Claim{ + Value: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000768"), + Position: NewPosition(1, 1), + }, + &Response{ + Attack: true, + Value: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000465"), + }, + }, + } + + for _, test := range indices { + res, err := solver.NextMove(test.claim, test.parent) + require.NoError(t, err) + require.Equal(t, test.response, res) + } +} diff --git a/op-challenger/fault/types.go b/op-challenger/fault/types.go index 2f2c52061470..374f09d09f40 100644 --- a/op-challenger/fault/types.go +++ b/op-challenger/fault/types.go @@ -1,6 +1,7 @@ package fault import ( + "context" "errors" "github.com/ethereum/go-ethereum/common" @@ -26,4 +27,11 @@ type Claim struct { type Response struct { Attack bool // note: can we flip this to true == going right / defending?? Value common.Hash + Parent Claim +} + +// Responder takes a response action & executes. +// For full op-challenger this means executing the transaction on chain. +type Responder interface { + Respond(ctx context.Context, response Response) error } diff --git a/op-challenger/flags/flags.go b/op-challenger/flags/flags.go index e8edcb4e41f1..1d95d0f0dc6d 100644 --- a/op-challenger/flags/flags.go +++ b/op-challenger/flags/flags.go @@ -3,7 +3,7 @@ package flags import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" opservice "github.com/ethereum-optimism/optimism/op-service" oplog "github.com/ethereum-optimism/optimism/op-service/log" @@ -15,27 +15,31 @@ import ( const envVarPrefix = "OP_CHALLENGER" +func prefixEnvVars(name string) []string { + return opservice.PrefixEnvVar(envVarPrefix, name) +} + var ( // Required Flags - L1EthRpcFlag = cli.StringFlag{ - Name: "l1-eth-rpc", - Usage: "HTTP provider URL for L1.", - EnvVar: opservice.PrefixEnvVar(envVarPrefix, "L1_ETH_RPC"), + L1EthRpcFlag = &cli.StringFlag{ + Name: "l1-eth-rpc", + Usage: "HTTP provider URL for L1.", + EnvVars: prefixEnvVars("L1_ETH_RPC"), } - RollupRpcFlag = cli.StringFlag{ - Name: "rollup-rpc", - Usage: "HTTP provider URL for the rollup node.", - EnvVar: opservice.PrefixEnvVar(envVarPrefix, "ROLLUP_RPC"), + RollupRpcFlag = &cli.StringFlag{ + Name: "rollup-rpc", + Usage: "HTTP provider URL for the rollup node.", + EnvVars: prefixEnvVars("ROLLUP_RPC"), } - L2OOAddressFlag = cli.StringFlag{ - Name: "l2oo-address", - Usage: "Address of the L2OutputOracle contract.", - EnvVar: opservice.PrefixEnvVar(envVarPrefix, "L2OO_ADDRESS"), + L2OOAddressFlag = &cli.StringFlag{ + Name: "l2oo-address", + Usage: "Address of the L2OutputOracle contract.", + EnvVars: prefixEnvVars("L2OO_ADDRESS"), } - DGFAddressFlag = cli.StringFlag{ - Name: "dgf-address", - Usage: "Address of the DisputeGameFactory contract.", - EnvVar: opservice.PrefixEnvVar(envVarPrefix, "DGF_ADDRESS"), + DGFAddressFlag = &cli.StringFlag{ + Name: "dgf-address", + Usage: "Address of the DisputeGameFactory contract.", + EnvVars: prefixEnvVars("DGF_ADDRESS"), } ) @@ -65,8 +69,8 @@ var Flags []cli.Flag func CheckRequired(ctx *cli.Context) error { for _, f := range requiredFlags { - if !ctx.GlobalIsSet(f.GetName()) { - return fmt.Errorf("flag %s is required", f.GetName()) + if !ctx.IsSet(f.Names()[0]) { + return fmt.Errorf("flag %s is required", f.Names()[0]) } } return nil diff --git a/op-challenger/flags/flags_test.go b/op-challenger/flags/flags_test.go index 0152e033b893..60294bfefb0b 100644 --- a/op-challenger/flags/flags_test.go +++ b/op-challenger/flags/flags_test.go @@ -5,14 +5,14 @@ import ( "strings" "testing" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) // TestUniqueFlags asserts that all flag names are unique, to avoid accidental conflicts between the many flags. func TestUniqueFlags(t *testing.T) { seenCLI := make(map[string]struct{}) for _, flag := range Flags { - name := flag.GetName() + name := flag.Names()[0] if _, ok := seenCLI[name]; ok { t.Errorf("duplicate flag %s", name) continue @@ -38,22 +38,22 @@ func TestCorrectEnvVarPrefix(t *testing.T) { for _, flag := range Flags { envVar := envVarForFlag(flag) if envVar == "" { - t.Errorf("Failed to find EnvVar for flag %v", flag.GetName()) + t.Errorf("Failed to find EnvVar for flag %v", flag.Names()[0]) } if !strings.HasPrefix(envVar, "OP_CHALLENGER_") { - t.Errorf("Flag %v env var (%v) does not start with OP_CHALLENGER_", flag.GetName(), envVar) + t.Errorf("Flag %v env var (%v) does not start with OP_CHALLENGER_", flag.Names()[0], envVar) } if strings.Contains(envVar, "__") { - t.Errorf("Flag %v env var (%v) has duplicate underscores", flag.GetName(), envVar) + t.Errorf("Flag %v env var (%v) has duplicate underscores", flag.Names()[0], envVar) } } } func envVarForFlag(flag cli.Flag) string { values := reflect.ValueOf(flag) - envVarValue := values.FieldByName("EnvVar") - if envVarValue == (reflect.Value{}) { + envVarValue := values.Elem().FieldByName("EnvVars") + if envVarValue == (reflect.Value{}) || envVarValue.Len() == 0 { return "" } - return envVarValue.String() + return envVarValue.Index(0).String() } diff --git a/op-heartbeat/Dockerfile b/op-heartbeat/Dockerfile index 1303efd80d26..86c43c57f066 100644 --- a/op-heartbeat/Dockerfile +++ b/op-heartbeat/Dockerfile @@ -1,18 +1,21 @@ -FROM golang:1.18.0-alpine3.15 as builder +FROM golang:1.19.9-alpine3.16 as builder RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash # build op-heartbeat with local monorepo go modules COPY ./op-heartbeat /app/op-heartbeat +COPY ./op-node /app/op-node +COPY ./op-service /app/op-service +COPY ./go.mod /app/go.mod +COPY ./go.sum /app/go.sum + COPY ./.git /app/.git -COPY ./op-heartbeat/go.mod /app/go.mod -COPY ./op-heartbeat/go.sum /app/go.sum WORKDIR /app/op-heartbeat RUN make op-heartbeat -FROM alpine:3.15 +FROM alpine:3.16 COPY --from=builder /app/op-heartbeat/bin/op-heartbeat /usr/local/bin diff --git a/op-heartbeat/cmd/main.go b/op-heartbeat/cmd/main.go index cd7b759a657a..46ee115f5c5b 100644 --- a/op-heartbeat/cmd/main.go +++ b/op-heartbeat/cmd/main.go @@ -8,7 +8,7 @@ import ( "github.com/ethereum-optimism/optimism/op-heartbeat/flags" oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum/go-ethereum/log" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) var ( diff --git a/op-heartbeat/config.go b/op-heartbeat/config.go index f260422d70f8..84129ad1bd1a 100644 --- a/op-heartbeat/config.go +++ b/op-heartbeat/config.go @@ -7,7 +7,7 @@ import ( oplog "github.com/ethereum-optimism/optimism/op-service/log" opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" oppprof "github.com/ethereum-optimism/optimism/op-service/pprof" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) type Config struct { @@ -42,8 +42,8 @@ func (c Config) Check() error { func NewConfig(ctx *cli.Context) Config { return Config{ - HTTPAddr: ctx.GlobalString(flags.HTTPAddrFlag.Name), - HTTPPort: ctx.GlobalInt(flags.HTTPPortFlag.Name), + HTTPAddr: ctx.String(flags.HTTPAddrFlag.Name), + HTTPPort: ctx.Int(flags.HTTPPortFlag.Name), Log: oplog.ReadCLIConfig(ctx), Metrics: opmetrics.ReadCLIConfig(ctx), Pprof: oppprof.ReadCLIConfig(ctx), diff --git a/op-heartbeat/flags/flags.go b/op-heartbeat/flags/flags.go index 970d0b3933a0..a5bd8123d687 100644 --- a/op-heartbeat/flags/flags.go +++ b/op-heartbeat/flags/flags.go @@ -4,28 +4,32 @@ import ( opservice "github.com/ethereum-optimism/optimism/op-service" oplog "github.com/ethereum-optimism/optimism/op-service/log" opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) const envPrefix = "OP_HEARTBEAT" +func prefixEnvVars(name string) []string { + return opservice.PrefixEnvVar(envPrefix, name) +} + const ( HTTPAddrFlagName = "http.addr" HTTPPortFlagName = "http.port" ) var ( - HTTPAddrFlag = cli.StringFlag{ - Name: HTTPAddrFlagName, - Usage: "Address the server should listen on", - Value: "0.0.0.0", - EnvVar: opservice.PrefixEnvVar(envPrefix, "HTTP_ADDR"), + HTTPAddrFlag = &cli.StringFlag{ + Name: HTTPAddrFlagName, + Usage: "Address the server should listen on", + Value: "0.0.0.0", + EnvVars: prefixEnvVars("HTTP_ADDR"), } - HTTPPortFlag = cli.IntFlag{ - Name: HTTPPortFlagName, - Usage: "Port the server should listen on", - Value: 8080, - EnvVar: opservice.PrefixEnvVar(envPrefix, "HTTP_PORT"), + HTTPPortFlag = &cli.IntFlag{ + Name: HTTPPortFlagName, + Usage: "Port the server should listen on", + Value: 8080, + EnvVars: prefixEnvVars("HTTP_PORT"), } ) diff --git a/op-heartbeat/go.mod b/op-heartbeat/go.mod deleted file mode 100644 index b3693b42982a..000000000000 --- a/op-heartbeat/go.mod +++ /dev/null @@ -1,43 +0,0 @@ -module github.com/ethereum-optimism/optimism/op-heartbeat - -go 1.18 - -require ( - github.com/ethereum-optimism/optimism/op-node v0.10.13 - github.com/ethereum-optimism/optimism/op-service v0.10.13 - github.com/ethereum/go-ethereum v1.10.26 - github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d - github.com/prometheus/client_golang v1.14.0 - github.com/stretchr/testify v1.8.1 - github.com/urfave/cli v1.22.10 -) - -require ( - github.com/beorn7/perks v1.0.1 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/deckarep/golang-set v1.8.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-stack/stack v1.8.1 // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.37.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/shirou/gopsutil v3.21.11+incompatible // indirect - github.com/tklauser/go-sysconf v0.3.10 // indirect - github.com/tklauser/numcpus v0.5.0 // indirect - github.com/yusufpapurcu/wmi v1.2.2 // indirect - golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect - golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43 // indirect - golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect - google.golang.org/protobuf v1.28.1 // indirect - gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/op-heartbeat/go.sum b/op-heartbeat/go.sum deleted file mode 100644 index 3e522be2577e..000000000000 --- a/op-heartbeat/go.sum +++ /dev/null @@ -1,573 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/btcsuite/btcd v0.23.3 h1:4KH/JKy9WiCd+iUS9Mu0Zp7Dnj17TGdKrg9xc/FGj24= -github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= -github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= -github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= -github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= -github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum-optimism/optimism/op-node v0.10.13 h1:a49FPr/gROrtDUyrkZGkWF3mzq6SnTFQkJrGOduYSfY= -github.com/ethereum-optimism/optimism/op-node v0.10.13/go.mod h1:PcoBNd7eLGN6qRx7pxhTyUxRtfCh5Y/Ll8VipivXHDw= -github.com/ethereum-optimism/optimism/op-service v0.10.13 h1:4wv2LgbVD0aLVNtY0H/49Dvoof2KRT6w40OGeb+9pic= -github.com/ethereum-optimism/optimism/op-service v0.10.13/go.mod h1:X+qyGWCSVnf4DU+mzbpKFchrMfrpdscjL/zxiaMZ0rM= -github.com/ethereum/go-ethereum v1.10.26 h1:i/7d9RBBwiXCEuyduBQzJw/mKmnvzsN14jqBmytw72s= -github.com/ethereum/go-ethereum v1.10.26/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= -github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= -github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= -github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -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.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= -github.com/rivo/uniseg v0.3.4 h1:3Z3Eu6FGHZWSfNKJTOUiPatWwfc7DzJRU04jFUqJODw= -github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= -github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= -github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -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.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= -github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= -github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= -github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= -github.com/tklauser/numcpus v0.5.0 h1:ooe7gN0fg6myJ0EKoTAf5hebTZrH52px3New/D9iJ+A= -github.com/tklauser/numcpus v0.5.0/go.mod h1:OGzpTxpcIMNGYQdit2BYL1pvk/dSOaJWjKoflh+RQjo= -github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= -github.com/urfave/cli v1.22.10 h1:p8Fspmz3iTctJstry1PYS3HVdllxnEzTEsgIgtxTrCk= -github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= -github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43 h1:OK7RB6t2WQX54srQQYSXMW8dF5C6/8+oA/s5QBmmto4= -golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc= -golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/op-heartbeat/service.go b/op-heartbeat/service.go index d30d5d2cdf62..c769e0e422f1 100644 --- a/op-heartbeat/service.go +++ b/op-heartbeat/service.go @@ -14,7 +14,7 @@ import ( "syscall" "time" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum/go-ethereum/log" diff --git a/op-node/cmd/batch_decoder/main.go b/op-node/cmd/batch_decoder/main.go index d63b32de63c4..fd96deefc5ef 100644 --- a/op-node/cmd/batch_decoder/main.go +++ b/op-node/cmd/batch_decoder/main.go @@ -12,48 +12,48 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) func main() { app := cli.NewApp() app.Name = "batch-decoder" app.Usage = "Optimism Batch Decoding Utility" - app.Commands = []cli.Command{ + app.Commands = []*cli.Command{ { Name: "fetch", Usage: "Fetches batches in the specified range", Flags: []cli.Flag{ - cli.IntFlag{ + &cli.IntFlag{ Name: "start", Required: true, Usage: "First block (inclusive) to fetch", }, - cli.IntFlag{ + &cli.IntFlag{ Name: "end", Required: true, Usage: "Last block (exclusive) to fetch", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "inbox", Required: true, Usage: "Batch Inbox Address", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "sender", Required: true, Usage: "Batch Sender Address", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "out", Value: "/tmp/batch_decoder/transactions_cache", Usage: "Cache directory for the found transactions", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "l1", Required: true, Usage: "L1 RPC URL", - EnvVar: "L1_RPC", + EnvVars: []string{"L1_RPC"}, }, }, Action: func(cliCtx *cli.Context) error { @@ -88,17 +88,17 @@ func main() { Name: "reassemble", Usage: "Reassembles channels from fetched batches", Flags: []cli.Flag{ - cli.StringFlag{ + &cli.StringFlag{ Name: "inbox", Value: "0xff00000000000000000000000000000000000420", Usage: "Batch Inbox Address", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "in", Value: "/tmp/batch_decoder/transactions_cache", Usage: "Cache directory for the found transactions", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "out", Value: "/tmp/batch_decoder/channel_cache", Usage: "Cache directory for the found channels", @@ -118,17 +118,17 @@ func main() { Name: "force-close", Usage: "Create the tx data which will force close a channel", Flags: []cli.Flag{ - cli.StringFlag{ + &cli.StringFlag{ Name: "id", Required: true, Usage: "ID of the channel to close", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "inbox", Value: "0x0000000000000000000000000000000000000000", Usage: "(Optional) Batch Inbox Address", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "in", Value: "/tmp/batch_decoder/transactions_cache", Usage: "Cache directory for the found transactions", diff --git a/op-node/cmd/doc/cmd.go b/op-node/cmd/doc/cmd.go index 2a55b6b064ea..4e2e5acda9b8 100644 --- a/op-node/cmd/doc/cmd.go +++ b/op-node/cmd/doc/cmd.go @@ -8,7 +8,7 @@ import ( "github.com/ethereum-optimism/optimism/op-node/metrics" "github.com/olekukonko/tablewriter" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) var Subcommands = cli.Commands{ @@ -16,7 +16,7 @@ var Subcommands = cli.Commands{ Name: "metrics", Usage: "Dumps a list of supported metrics to stdout", Flags: []cli.Flag{ - cli.StringFlag{ + &cli.StringFlag{ Name: "format", Value: "markdown", Usage: "Output format (json|markdown)", diff --git a/op-node/cmd/genesis/cmd.go b/op-node/cmd/genesis/cmd.go index ac3597b84914..b2f81677f628 100644 --- a/op-node/cmd/genesis/cmd.go +++ b/op-node/cmd/genesis/cmd.go @@ -8,7 +8,7 @@ import ( "os" "path/filepath" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" @@ -22,19 +22,19 @@ var Subcommands = cli.Commands{ Name: "devnet", Usage: "Initialize new L1 and L2 genesis files and rollup config suitable for a local devnet", Flags: []cli.Flag{ - cli.StringFlag{ + &cli.StringFlag{ Name: "deploy-config", Usage: "Path to hardhat deploy config file", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "outfile.l1", Usage: "Path to L1 genesis output file", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "outfile.l2", Usage: "Path to L2 genesis output file", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "outfile.rollup", Usage: "Path to rollup output file", }, @@ -85,23 +85,23 @@ var Subcommands = cli.Commands{ Name: "l2", Usage: "Generates an L2 genesis file and rollup config suitable for a deployed network", Flags: []cli.Flag{ - cli.StringFlag{ + &cli.StringFlag{ Name: "l1-rpc", Usage: "L1 RPC URL", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "deploy-config", Usage: "Path to hardhat deploy config file", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "deployment-dir", Usage: "Path to deployment directory", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "outfile.l2", Usage: "Path to L2 genesis output file", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "outfile.rollup", Usage: "Path to rollup output file", }, diff --git a/op-node/cmd/main.go b/op-node/cmd/main.go index e8f682968628..e8c66a7d7ca8 100644 --- a/op-node/cmd/main.go +++ b/op-node/cmd/main.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-node/cmd/doc" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum/go-ethereum/log" @@ -59,7 +59,7 @@ func main() { app.Usage = "Optimism Rollup Node" app.Description = "The Optimism Rollup Node derives L2 block inputs from L1 data and drives an external L2 Execution Engine to build a L2 chain." app.Action = RollupNodeMain - app.Commands = []cli.Command{ + app.Commands = []*cli.Command{ { Name: "p2p", Subcommands: p2p.Subcommands, diff --git a/op-node/cmd/p2p/cmd.go b/op-node/cmd/p2p/cmd.go index 8fc039028edc..3419769c322d 100644 --- a/op-node/cmd/p2p/cmd.go +++ b/op-node/cmd/p2p/cmd.go @@ -10,7 +10,7 @@ import ( "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/peer" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) func Priv2PeerID(r io.Reader) (string, error) { diff --git a/op-node/flags/flags.go b/op-node/flags/flags.go index 0c9df1251b8d..1e422114a2be 100644 --- a/op-node/flags/flags.go +++ b/op-node/flags/flags.go @@ -10,202 +10,202 @@ import ( openum "github.com/ethereum-optimism/optimism/op-service/enum" oplog "github.com/ethereum-optimism/optimism/op-service/log" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) // Flags const EnvVarPrefix = "OP_NODE" -func prefixEnvVar(name string) string { - return EnvVarPrefix + "_" + name +func prefixEnvVars(name string) []string { + return []string{EnvVarPrefix + "_" + name} } var ( /* Required Flags */ - L1NodeAddr = cli.StringFlag{ - Name: "l1", - Usage: "Address of L1 User JSON-RPC endpoint to use (eth namespace required)", - Value: "http://127.0.0.1:8545", - EnvVar: prefixEnvVar("L1_ETH_RPC"), - } - L2EngineAddr = cli.StringFlag{ - Name: "l2", - Usage: "Address of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required)", - EnvVar: prefixEnvVar("L2_ENGINE_RPC"), - } - RollupConfig = cli.StringFlag{ - Name: "rollup.config", - Usage: "Rollup chain parameters", - EnvVar: prefixEnvVar("ROLLUP_CONFIG"), - } - Network = cli.StringFlag{ - Name: "network", - Usage: fmt.Sprintf("Predefined network selection. Available networks: %s", strings.Join(chaincfg.AvailableNetworks(), ", ")), - EnvVar: prefixEnvVar("NETWORK"), - } - RPCListenAddr = cli.StringFlag{ - Name: "rpc.addr", - Usage: "RPC listening address", - EnvVar: prefixEnvVar("RPC_ADDR"), - } - RPCListenPort = cli.IntFlag{ - Name: "rpc.port", - Usage: "RPC listening port", - EnvVar: prefixEnvVar("RPC_PORT"), - } - RPCEnableAdmin = cli.BoolFlag{ - Name: "rpc.enable-admin", - Usage: "Enable the admin API (experimental)", - EnvVar: prefixEnvVar("RPC_ENABLE_ADMIN"), + L1NodeAddr = &cli.StringFlag{ + Name: "l1", + Usage: "Address of L1 User JSON-RPC endpoint to use (eth namespace required)", + Value: "http://127.0.0.1:8545", + EnvVars: prefixEnvVars("L1_ETH_RPC"), + } + L2EngineAddr = &cli.StringFlag{ + Name: "l2", + Usage: "Address of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required)", + EnvVars: prefixEnvVars("L2_ENGINE_RPC"), + } + RollupConfig = &cli.StringFlag{ + Name: "rollup.config", + Usage: "Rollup chain parameters", + EnvVars: prefixEnvVars("ROLLUP_CONFIG"), + } + Network = &cli.StringFlag{ + Name: "network", + Usage: fmt.Sprintf("Predefined network selection. Available networks: %s", strings.Join(chaincfg.AvailableNetworks(), ", ")), + EnvVars: prefixEnvVars("NETWORK"), + } + RPCListenAddr = &cli.StringFlag{ + Name: "rpc.addr", + Usage: "RPC listening address", + EnvVars: prefixEnvVars("RPC_ADDR"), + } + RPCListenPort = &cli.IntFlag{ + Name: "rpc.port", + Usage: "RPC listening port", + EnvVars: prefixEnvVars("RPC_PORT"), + } + RPCEnableAdmin = &cli.BoolFlag{ + Name: "rpc.enable-admin", + Usage: "Enable the admin API (experimental)", + EnvVars: prefixEnvVars("RPC_ENABLE_ADMIN"), } /* Optional Flags */ - L1TrustRPC = cli.BoolFlag{ - Name: "l1.trustrpc", - Usage: "Trust the L1 RPC, sync faster at risk of malicious/buggy RPC providing bad or inconsistent L1 data", - EnvVar: prefixEnvVar("L1_TRUST_RPC"), + L1TrustRPC = &cli.BoolFlag{ + Name: "l1.trustrpc", + Usage: "Trust the L1 RPC, sync faster at risk of malicious/buggy RPC providing bad or inconsistent L1 data", + EnvVars: prefixEnvVars("L1_TRUST_RPC"), } - L1RPCProviderKind = cli.GenericFlag{ + L1RPCProviderKind = &cli.GenericFlag{ Name: "l1.rpckind", Usage: "The kind of RPC provider, used to inform optimal transactions receipts fetching, and thus reduce costs. Valid options: " + openum.EnumString(sources.RPCProviderKinds), - EnvVar: prefixEnvVar("L1_RPC_KIND"), + EnvVars: prefixEnvVars("L1_RPC_KIND"), Value: func() *sources.RPCProviderKind { out := sources.RPCKindBasic return &out }(), } - L1RPCRateLimit = cli.Float64Flag{ - Name: "l1.rpc-rate-limit", - Usage: "Optional self-imposed global rate-limit on L1 RPC requests, specified in requests / second. Disabled if set to 0.", - EnvVar: prefixEnvVar("L1_RPC_RATE_LIMIT"), - Value: 0, - } - L1RPCMaxBatchSize = cli.IntFlag{ - Name: "l1.rpc-max-batch-size", - Usage: "Maximum number of RPC requests to bundle, e.g. during L1 blocks receipt fetching. The L1 RPC rate limit counts this as N items, but allows it to burst at once.", - EnvVar: prefixEnvVar("L1_RPC_MAX_BATCH_SIZE"), - Value: 20, - } - L1HTTPPollInterval = cli.DurationFlag{ - Name: "l1.http-poll-interval", - Usage: "Polling interval for latest-block subscription when using an HTTP RPC provider. Ignored for other types of RPC endpoints.", - EnvVar: prefixEnvVar("L1_HTTP_POLL_INTERVAL"), - Value: time.Second * 12, - } - L2EngineJWTSecret = cli.StringFlag{ + L1RPCRateLimit = &cli.Float64Flag{ + Name: "l1.rpc-rate-limit", + Usage: "Optional self-imposed global rate-limit on L1 RPC requests, specified in requests / second. Disabled if set to 0.", + EnvVars: prefixEnvVars("L1_RPC_RATE_LIMIT"), + Value: 0, + } + L1RPCMaxBatchSize = &cli.IntFlag{ + Name: "l1.rpc-max-batch-size", + Usage: "Maximum number of RPC requests to bundle, e.g. during L1 blocks receipt fetching. The L1 RPC rate limit counts this as N items, but allows it to burst at once.", + EnvVars: prefixEnvVars("L1_RPC_MAX_BATCH_SIZE"), + Value: 20, + } + L1HTTPPollInterval = &cli.DurationFlag{ + Name: "l1.http-poll-interval", + Usage: "Polling interval for latest-block subscription when using an HTTP RPC provider. Ignored for other types of RPC endpoints.", + EnvVars: prefixEnvVars("L1_HTTP_POLL_INTERVAL"), + Value: time.Second * 12, + } + L2EngineJWTSecret = &cli.StringFlag{ Name: "l2.jwt-secret", Usage: "Path to JWT secret key. Keys are 32 bytes, hex encoded in a file. A new key will be generated if left empty.", - EnvVar: prefixEnvVar("L2_ENGINE_AUTH"), + EnvVars: prefixEnvVars("L2_ENGINE_AUTH"), Required: false, Value: "", Destination: new(string), } - VerifierL1Confs = cli.Uint64Flag{ + VerifierL1Confs = &cli.Uint64Flag{ Name: "verifier.l1-confs", Usage: "Number of L1 blocks to keep distance from the L1 head before deriving L2 data from. Reorgs are supported, but may be slow to perform.", - EnvVar: prefixEnvVar("VERIFIER_L1_CONFS"), + EnvVars: prefixEnvVars("VERIFIER_L1_CONFS"), Required: false, Value: 0, } - SequencerEnabledFlag = cli.BoolFlag{ - Name: "sequencer.enabled", - Usage: "Enable sequencing of new L2 blocks. A separate batch submitter has to be deployed to publish the data for verifiers.", - EnvVar: prefixEnvVar("SEQUENCER_ENABLED"), + SequencerEnabledFlag = &cli.BoolFlag{ + Name: "sequencer.enabled", + Usage: "Enable sequencing of new L2 blocks. A separate batch submitter has to be deployed to publish the data for verifiers.", + EnvVars: prefixEnvVars("SEQUENCER_ENABLED"), } - SequencerStoppedFlag = cli.BoolFlag{ - Name: "sequencer.stopped", - Usage: "Initialize the sequencer in a stopped state. The sequencer can be started using the admin_startSequencer RPC", - EnvVar: prefixEnvVar("SEQUENCER_STOPPED"), + SequencerStoppedFlag = &cli.BoolFlag{ + Name: "sequencer.stopped", + Usage: "Initialize the sequencer in a stopped state. The sequencer can be started using the admin_startSequencer RPC", + EnvVars: prefixEnvVars("SEQUENCER_STOPPED"), } - SequencerMaxSafeLagFlag = cli.Uint64Flag{ + SequencerMaxSafeLagFlag = &cli.Uint64Flag{ Name: "sequencer.max-safe-lag", Usage: "Maximum number of L2 blocks for restricting the distance between L2 safe and unsafe. Disabled if 0.", - EnvVar: prefixEnvVar("SEQUENCER_MAX_SAFE_LAG"), + EnvVars: prefixEnvVars("SEQUENCER_MAX_SAFE_LAG"), Required: false, Value: 0, } - SequencerL1Confs = cli.Uint64Flag{ + SequencerL1Confs = &cli.Uint64Flag{ Name: "sequencer.l1-confs", Usage: "Number of L1 blocks to keep distance from the L1 head as a sequencer for picking an L1 origin.", - EnvVar: prefixEnvVar("SEQUENCER_L1_CONFS"), + EnvVars: prefixEnvVars("SEQUENCER_L1_CONFS"), Required: false, Value: 4, } - L1EpochPollIntervalFlag = cli.DurationFlag{ + L1EpochPollIntervalFlag = &cli.DurationFlag{ Name: "l1.epoch-poll-interval", Usage: "Poll interval for retrieving new L1 epoch updates such as safe and finalized block changes. Disabled if 0 or negative.", - EnvVar: prefixEnvVar("L1_EPOCH_POLL_INTERVAL"), + EnvVars: prefixEnvVars("L1_EPOCH_POLL_INTERVAL"), Required: false, Value: time.Second * 12 * 32, } - MetricsEnabledFlag = cli.BoolFlag{ - Name: "metrics.enabled", - Usage: "Enable the metrics server", - EnvVar: prefixEnvVar("METRICS_ENABLED"), - } - MetricsAddrFlag = cli.StringFlag{ - Name: "metrics.addr", - Usage: "Metrics listening address", - Value: "0.0.0.0", - EnvVar: prefixEnvVar("METRICS_ADDR"), - } - MetricsPortFlag = cli.IntFlag{ - Name: "metrics.port", - Usage: "Metrics listening port", - Value: 7300, - EnvVar: prefixEnvVar("METRICS_PORT"), - } - PprofEnabledFlag = cli.BoolFlag{ - Name: "pprof.enabled", - Usage: "Enable the pprof server", - EnvVar: prefixEnvVar("PPROF_ENABLED"), - } - PprofAddrFlag = cli.StringFlag{ - Name: "pprof.addr", - Usage: "pprof listening address", - Value: "0.0.0.0", - EnvVar: prefixEnvVar("PPROF_ADDR"), - } - PprofPortFlag = cli.IntFlag{ - Name: "pprof.port", - Usage: "pprof listening port", - Value: 6060, - EnvVar: prefixEnvVar("PPROF_PORT"), - } - SnapshotLog = cli.StringFlag{ - Name: "snapshotlog.file", - Usage: "Path to the snapshot log file", - EnvVar: prefixEnvVar("SNAPSHOT_LOG"), - } - HeartbeatEnabledFlag = cli.BoolFlag{ - Name: "heartbeat.enabled", - Usage: "Enables or disables heartbeating", - EnvVar: prefixEnvVar("HEARTBEAT_ENABLED"), - } - HeartbeatMonikerFlag = cli.StringFlag{ - Name: "heartbeat.moniker", - Usage: "Sets a moniker for this node", - EnvVar: prefixEnvVar("HEARTBEAT_MONIKER"), - } - HeartbeatURLFlag = cli.StringFlag{ - Name: "heartbeat.url", - Usage: "Sets the URL to heartbeat to", - EnvVar: prefixEnvVar("HEARTBEAT_URL"), - Value: "https://heartbeat.optimism.io", - } - BackupL2UnsafeSyncRPC = cli.StringFlag{ + MetricsEnabledFlag = &cli.BoolFlag{ + Name: "metrics.enabled", + Usage: "Enable the metrics server", + EnvVars: prefixEnvVars("METRICS_ENABLED"), + } + MetricsAddrFlag = &cli.StringFlag{ + Name: "metrics.addr", + Usage: "Metrics listening address", + Value: "0.0.0.0", + EnvVars: prefixEnvVars("METRICS_ADDR"), + } + MetricsPortFlag = &cli.IntFlag{ + Name: "metrics.port", + Usage: "Metrics listening port", + Value: 7300, + EnvVars: prefixEnvVars("METRICS_PORT"), + } + PprofEnabledFlag = &cli.BoolFlag{ + Name: "pprof.enabled", + Usage: "Enable the pprof server", + EnvVars: prefixEnvVars("PPROF_ENABLED"), + } + PprofAddrFlag = &cli.StringFlag{ + Name: "pprof.addr", + Usage: "pprof listening address", + Value: "0.0.0.0", + EnvVars: prefixEnvVars("PPROF_ADDR"), + } + PprofPortFlag = &cli.IntFlag{ + Name: "pprof.port", + Usage: "pprof listening port", + Value: 6060, + EnvVars: prefixEnvVars("PPROF_PORT"), + } + SnapshotLog = &cli.StringFlag{ + Name: "snapshotlog.file", + Usage: "Path to the snapshot log file", + EnvVars: prefixEnvVars("SNAPSHOT_LOG"), + } + HeartbeatEnabledFlag = &cli.BoolFlag{ + Name: "heartbeat.enabled", + Usage: "Enables or disables heartbeating", + EnvVars: prefixEnvVars("HEARTBEAT_ENABLED"), + } + HeartbeatMonikerFlag = &cli.StringFlag{ + Name: "heartbeat.moniker", + Usage: "Sets a moniker for this node", + EnvVars: prefixEnvVars("HEARTBEAT_MONIKER"), + } + HeartbeatURLFlag = &cli.StringFlag{ + Name: "heartbeat.url", + Usage: "Sets the URL to heartbeat to", + EnvVars: prefixEnvVars("HEARTBEAT_URL"), + Value: "https://heartbeat.optimism.io", + } + BackupL2UnsafeSyncRPC = &cli.StringFlag{ Name: "l2.backup-unsafe-sync-rpc", Usage: "Set the backup L2 unsafe sync RPC endpoint.", - EnvVar: prefixEnvVar("L2_BACKUP_UNSAFE_SYNC_RPC"), + EnvVars: prefixEnvVars("L2_BACKUP_UNSAFE_SYNC_RPC"), Required: false, } - BackupL2UnsafeSyncRPCTrustRPC = cli.StringFlag{ + BackupL2UnsafeSyncRPCTrustRPC = &cli.StringFlag{ Name: "l2.backup-unsafe-sync-rpc.trustrpc", Usage: "Like l1.trustrpc, configure if response data from the RPC needs to be verified, e.g. blockhash computation." + "This does not include checks if the blockhash is part of the canonical chain.", - EnvVar: prefixEnvVar("L2_BACKUP_UNSAFE_SYNC_RPC_TRUST_RPC"), + EnvVars: prefixEnvVars("L2_BACKUP_UNSAFE_SYNC_RPC_TRUST_RPC"), Required: false, } ) @@ -258,8 +258,8 @@ func init() { func CheckRequired(ctx *cli.Context) error { for _, f := range requiredFlags { - if !ctx.GlobalIsSet(f.GetName()) { - return fmt.Errorf("flag %s is required", f.GetName()) + if !ctx.IsSet(f.Names()[0]) { + return fmt.Errorf("flag %s is required", f.Names()[0]) } } return nil diff --git a/op-node/flags/flags_test.go b/op-node/flags/flags_test.go index 80d05648615f..da652618a9c4 100644 --- a/op-node/flags/flags_test.go +++ b/op-node/flags/flags_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/stretchr/testify/require" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) // TestOptionalFlagsDontSetRequired asserts that all flags deemed optional set @@ -21,7 +21,7 @@ func TestOptionalFlagsDontSetRequired(t *testing.T) { func TestUniqueFlags(t *testing.T) { seenCLI := make(map[string]struct{}) for _, flag := range Flags { - name := flag.GetName() + name := flag.Names()[0] if _, ok := seenCLI[name]; ok { t.Errorf("duplicate flag %s", name) continue diff --git a/op-node/flags/p2p_flags.go b/op-node/flags/p2p_flags.go index ae24c0fb3f04..e808ebccd9d0 100644 --- a/op-node/flags/p2p_flags.go +++ b/op-node/flags/p2p_flags.go @@ -4,41 +4,41 @@ import ( "fmt" "time" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/op-node/p2p" ) -func p2pEnv(v string) string { - return prefixEnvVar("P2P_" + v) +func p2pEnv(v string) []string { + return prefixEnvVars("P2P_" + v) } var ( - DisableP2P = cli.BoolFlag{ + DisableP2P = &cli.BoolFlag{ Name: "p2p.disable", Usage: "Completely disable the P2P stack", Required: false, - EnvVar: p2pEnv("DISABLE"), + EnvVars: p2pEnv("DISABLE"), } - NoDiscovery = cli.BoolFlag{ + NoDiscovery = &cli.BoolFlag{ Name: "p2p.no-discovery", Usage: "Disable Discv5 (node discovery)", Required: false, - EnvVar: p2pEnv("NO_DISCOVERY"), + EnvVars: p2pEnv("NO_DISCOVERY"), } - Scoring = cli.StringFlag{ + Scoring = &cli.StringFlag{ Name: "p2p.scoring", Usage: "Sets the peer scoring strategy for the P2P stack. Can be one of: none or light.", Required: false, - EnvVar: p2pEnv("PEER_SCORING"), + EnvVars: p2pEnv("PEER_SCORING"), } - PeerScoring = cli.StringFlag{ + PeerScoring = &cli.StringFlag{ Name: "p2p.scoring.peers", Usage: fmt.Sprintf("Deprecated: Use %v instead", Scoring.Name), Required: false, Hidden: true, } - PeerScoreBands = cli.StringFlag{ + PeerScoreBands = &cli.StringFlag{ Name: "p2p.score.bands", Usage: "Deprecated. This option is ignored and is only present for backwards compatibility.", Required: false, @@ -47,185 +47,185 @@ var ( } // Banning Flag - whether or not we want to act on the scoring - Banning = cli.BoolFlag{ + Banning = &cli.BoolFlag{ Name: "p2p.ban.peers", Usage: "Enables peer banning. This should ONLY be enabled once certain peer scoring is working correctly.", Required: false, - EnvVar: p2pEnv("PEER_BANNING"), + EnvVars: p2pEnv("PEER_BANNING"), } - BanningThreshold = cli.Float64Flag{ + BanningThreshold = &cli.Float64Flag{ Name: "p2p.ban.threshold", Usage: "The minimum score below which peers are disconnected and banned.", Required: false, Value: -100, - EnvVar: p2pEnv("PEER_BANNING_THRESHOLD"), + EnvVars: p2pEnv("PEER_BANNING_THRESHOLD"), } - BanningDuration = cli.DurationFlag{ + BanningDuration = &cli.DurationFlag{ Name: "p2p.ban.duration", Usage: "The duration that peers are banned for.", Required: false, Value: 1 * time.Hour, - EnvVar: p2pEnv("PEER_BANNING_DURATION"), + EnvVars: p2pEnv("PEER_BANNING_DURATION"), } - TopicScoring = cli.StringFlag{ + TopicScoring = &cli.StringFlag{ Name: "p2p.scoring.topics", Usage: fmt.Sprintf("Deprecated: Use %v instead", Scoring.Name), Required: false, Hidden: true, } - P2PPrivPath = cli.StringFlag{ + P2PPrivPath = &cli.StringFlag{ Name: "p2p.priv.path", Usage: "Read the hex-encoded 32-byte private key for the peer ID from this txt file. Created if not already exists." + "Important to persist to keep the same network identity after restarting, maintaining the previous advertised identity.", Required: false, Value: "opnode_p2p_priv.txt", - EnvVar: p2pEnv("PRIV_PATH"), + EnvVars: p2pEnv("PRIV_PATH"), TakesFile: true, } - P2PPrivRaw = cli.StringFlag{ + P2PPrivRaw = &cli.StringFlag{ // sometimes it may be ok to not persist the peer priv key as file, and instead pass it directly. Name: "p2p.priv.raw", Usage: "The hex-encoded 32-byte private key for the peer ID", Required: false, Hidden: true, Value: "", - EnvVar: p2pEnv("PRIV_RAW"), + EnvVars: p2pEnv("PRIV_RAW"), } - ListenIP = cli.StringFlag{ + ListenIP = &cli.StringFlag{ Name: "p2p.listen.ip", Usage: "IP to bind LibP2P and Discv5 to", Required: false, Value: "0.0.0.0", - EnvVar: p2pEnv("LISTEN_IP"), + EnvVars: p2pEnv("LISTEN_IP"), } - ListenTCPPort = cli.UintFlag{ + ListenTCPPort = &cli.UintFlag{ Name: "p2p.listen.tcp", Usage: "TCP port to bind LibP2P to. Any available system port if set to 0.", Required: false, Value: 9222, - EnvVar: p2pEnv("LISTEN_TCP_PORT"), + EnvVars: p2pEnv("LISTEN_TCP_PORT"), } - ListenUDPPort = cli.UintFlag{ + ListenUDPPort = &cli.UintFlag{ Name: "p2p.listen.udp", Usage: "UDP port to bind Discv5 to. Same as TCP port if left 0.", Required: false, Value: 0, // can simply match the TCP libp2p port - EnvVar: p2pEnv("LISTEN_UDP_PORT"), + EnvVars: p2pEnv("LISTEN_UDP_PORT"), } - AdvertiseIP = cli.StringFlag{ + AdvertiseIP = &cli.StringFlag{ Name: "p2p.advertise.ip", Usage: "The IP address to advertise in Discv5, put into the ENR of the node. This may also be a hostname / domain name to resolve to an IP.", Required: false, // Ignored by default, nodes can discover their own external IP in the happy case, // by communicating with bootnodes. Fixed IP is recommended for faster bootstrap though. - Value: "", - EnvVar: p2pEnv("ADVERTISE_IP"), + Value: "", + EnvVars: p2pEnv("ADVERTISE_IP"), } - AdvertiseTCPPort = cli.UintFlag{ + AdvertiseTCPPort = &cli.UintFlag{ Name: "p2p.advertise.tcp", Usage: "The TCP port to advertise in Discv5, put into the ENR of the node. Set to p2p.listen.tcp value if 0.", Required: false, Value: 0, - EnvVar: p2pEnv("ADVERTISE_TCP"), + EnvVars: p2pEnv("ADVERTISE_TCP"), } - AdvertiseUDPPort = cli.UintFlag{ + AdvertiseUDPPort = &cli.UintFlag{ Name: "p2p.advertise.udp", Usage: "The UDP port to advertise in Discv5 as fallback if not determined by Discv5, put into the ENR of the node. Set to p2p.listen.udp value if 0.", Required: false, Value: 0, - EnvVar: p2pEnv("ADVERTISE_UDP"), + EnvVars: p2pEnv("ADVERTISE_UDP"), } - Bootnodes = cli.StringFlag{ + Bootnodes = &cli.StringFlag{ Name: "p2p.bootnodes", Usage: "Comma-separated base64-format ENR list. Bootnodes to start discovering other node records from.", Required: false, Value: "", - EnvVar: p2pEnv("BOOTNODES"), + EnvVars: p2pEnv("BOOTNODES"), } - StaticPeers = cli.StringFlag{ + StaticPeers = &cli.StringFlag{ Name: "p2p.static", Usage: "Comma-separated multiaddr-format peer list. Static connections to make and maintain, these peers will be regarded as trusted.", Required: false, Value: "", - EnvVar: p2pEnv("STATIC"), + EnvVars: p2pEnv("STATIC"), } - HostMux = cli.StringFlag{ + HostMux = &cli.StringFlag{ Name: "p2p.mux", Usage: "Comma-separated list of multiplexing protocols in order of preference. At least 1 required. Options: 'yamux','mplex'.", Hidden: true, Required: false, Value: "yamux,mplex", - EnvVar: p2pEnv("MUX"), + EnvVars: p2pEnv("MUX"), } - HostSecurity = cli.StringFlag{ + HostSecurity = &cli.StringFlag{ Name: "p2p.security", Usage: "Comma-separated list of transport security protocols in order of preference. At least 1 required. Options: 'noise','tls'. Set to 'none' to disable.", Hidden: true, Required: false, Value: "noise", - EnvVar: p2pEnv("SECURITY"), + EnvVars: p2pEnv("SECURITY"), } - PeersLo = cli.UintFlag{ + PeersLo = &cli.UintFlag{ Name: "p2p.peers.lo", Usage: "Low-tide peer count. The node actively searches for new peer connections if below this amount.", Required: false, Value: 20, - EnvVar: p2pEnv("PEERS_LO"), + EnvVars: p2pEnv("PEERS_LO"), } - PeersHi = cli.UintFlag{ + PeersHi = &cli.UintFlag{ Name: "p2p.peers.hi", Usage: "High-tide peer count. The node starts pruning peer connections slowly after reaching this number.", Required: false, Value: 30, - EnvVar: p2pEnv("PEERS_HI"), + EnvVars: p2pEnv("PEERS_HI"), } - PeersGrace = cli.DurationFlag{ + PeersGrace = &cli.DurationFlag{ Name: "p2p.peers.grace", Usage: "Grace period to keep a newly connected peer around, if it is not misbehaving.", Required: false, Value: 30 * time.Second, - EnvVar: p2pEnv("PEERS_GRACE"), + EnvVars: p2pEnv("PEERS_GRACE"), } - NAT = cli.BoolFlag{ + NAT = &cli.BoolFlag{ Name: "p2p.nat", Usage: "Enable NAT traversal with PMP/UPNP devices to learn external IP.", Required: false, - EnvVar: p2pEnv("NAT"), + EnvVars: p2pEnv("NAT"), } - UserAgent = cli.StringFlag{ + UserAgent = &cli.StringFlag{ Name: "p2p.useragent", Usage: "User-agent string to share via LibP2P identify. If empty it defaults to 'optimism'.", Hidden: true, Required: false, Value: "optimism", - EnvVar: p2pEnv("AGENT"), + EnvVars: p2pEnv("AGENT"), } - TimeoutNegotiation = cli.DurationFlag{ + TimeoutNegotiation = &cli.DurationFlag{ Name: "p2p.timeout.negotiation", Usage: "Negotiation timeout, time for new peer connections to share their their supported p2p protocols", Hidden: true, Required: false, Value: 10 * time.Second, - EnvVar: p2pEnv("TIMEOUT_NEGOTIATION"), + EnvVars: p2pEnv("TIMEOUT_NEGOTIATION"), } - TimeoutAccept = cli.DurationFlag{ + TimeoutAccept = &cli.DurationFlag{ Name: "p2p.timeout.accept", Usage: "Accept timeout, time for connection to be accepted.", Hidden: true, Required: false, Value: 10 * time.Second, - EnvVar: p2pEnv("TIMEOUT_ACCEPT"), + EnvVars: p2pEnv("TIMEOUT_ACCEPT"), } - TimeoutDial = cli.DurationFlag{ + TimeoutDial = &cli.DurationFlag{ Name: "p2p.timeout.dial", Usage: "Dial timeout for outgoing connection requests", Hidden: true, Required: false, Value: 10 * time.Second, - EnvVar: p2pEnv("TIMEOUT_DIAL"), + EnvVars: p2pEnv("TIMEOUT_DIAL"), } - PeerstorePath = cli.StringFlag{ + PeerstorePath = &cli.StringFlag{ Name: "p2p.peerstore.path", Usage: "Peerstore database location. Persisted peerstores help recover peers after restarts. " + "Set to 'memory' to never persist the peerstore. Peerstore records will be pruned / expire as necessary. " + @@ -233,67 +233,67 @@ var ( Required: false, TakesFile: true, Value: "opnode_peerstore_db", - EnvVar: p2pEnv("PEERSTORE_PATH"), + EnvVars: p2pEnv("PEERSTORE_PATH"), } - DiscoveryPath = cli.StringFlag{ + DiscoveryPath = &cli.StringFlag{ Name: "p2p.discovery.path", Usage: "Discovered ENRs are persisted in a database to recover from a restart without having to bootstrap the discovery process again. Set to 'memory' to never persist the peerstore.", Required: false, TakesFile: true, Value: "opnode_discovery_db", - EnvVar: p2pEnv("DISCOVERY_PATH"), + EnvVars: p2pEnv("DISCOVERY_PATH"), } - SequencerP2PKeyFlag = cli.StringFlag{ + SequencerP2PKeyFlag = &cli.StringFlag{ Name: "p2p.sequencer.key", Usage: "Hex-encoded private key for signing off on p2p application messages as sequencer.", Required: false, Value: "", - EnvVar: p2pEnv("SEQUENCER_KEY"), + EnvVars: p2pEnv("SEQUENCER_KEY"), } - GossipMeshDFlag = cli.UintFlag{ + 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"), + EnvVars: p2pEnv("GOSSIP_MESH_D"), } - GossipMeshDloFlag = cli.UintFlag{ + 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"), + EnvVars: p2pEnv("GOSSIP_MESH_DLO"), } - GossipMeshDhiFlag = cli.UintFlag{ + 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"), + EnvVars: p2pEnv("GOSSIP_MESH_DHI"), } - GossipMeshDlazyFlag = cli.UintFlag{ + 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"), + EnvVars: p2pEnv("GOSSIP_MESH_DLAZY"), } - GossipFloodPublishFlag = cli.BoolFlag{ + 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"), + EnvVars: p2pEnv("GOSSIP_FLOOD_PUBLISH"), } - SyncReqRespFlag = cli.BoolFlag{ + SyncReqRespFlag = &cli.BoolFlag{ Name: "p2p.sync.req-resp", Usage: "Enables experimental P2P req-resp alternative sync method, on both server and client side.", Required: false, - EnvVar: p2pEnv("SYNC_REQ_RESP"), + EnvVars: p2pEnv("SYNC_REQ_RESP"), } ) diff --git a/op-node/p2p/app_params.go b/op-node/p2p/app_params.go new file mode 100644 index 000000000000..de81b59032ed --- /dev/null +++ b/op-node/p2p/app_params.go @@ -0,0 +1,56 @@ +package p2p + +import ( + "time" + + "github.com/ethereum-optimism/optimism/op-node/rollup" +) + +type ApplicationScoreParams struct { + ValidResponseCap float64 + ValidResponseWeight float64 + ValidResponseDecay float64 + + ErrorResponseCap float64 + ErrorResponseWeight float64 + ErrorResponseDecay float64 + + RejectedPayloadCap float64 + RejectedPayloadWeight float64 + RejectedPayloadDecay float64 + + DecayToZero float64 + DecayInterval time.Duration +} + +func LightApplicationScoreParams(cfg *rollup.Config) ApplicationScoreParams { + slot := time.Duration(cfg.BlockTime) * time.Second + if slot == 0 { + slot = 2 * time.Second + } + // We initialize an "epoch" as 6 blocks suggesting 6 blocks, + // each taking ~ 2 seconds, is 12 seconds + epoch := 6 * slot + tenEpochs := 10 * epoch + return ApplicationScoreParams{ + // Max positive score from valid responses: 5 + ValidResponseCap: 10, + ValidResponseWeight: 0.5, + ValidResponseDecay: ScoreDecay(tenEpochs, slot), + + // Takes 20 error responses to reach the default ban threshold of -100 + // But at most we track 10. These errors include not supporting p2p sync + // so we don't (yet) want to ban a peer based on this measure alone. + ErrorResponseCap: 10, + ErrorResponseWeight: -5, + ErrorResponseDecay: ScoreDecay(tenEpochs, slot), + + // Takes 5 rejected payloads to reach the default ban threshold of -100 + RejectedPayloadCap: 20, + RejectedPayloadWeight: -20, + RejectedPayloadDecay: ScoreDecay(tenEpochs, slot), + + DecayToZero: DecayToZero, + DecayInterval: slot, + } +} diff --git a/op-node/p2p/app_scores.go b/op-node/p2p/app_scores.go new file mode 100644 index 000000000000..06693868c3e2 --- /dev/null +++ b/op-node/p2p/app_scores.go @@ -0,0 +1,151 @@ +package p2p + +import ( + "context" + "sync" + + "github.com/ethereum-optimism/optimism/op-node/p2p/store" + "github.com/ethereum-optimism/optimism/op-service/clock" + "github.com/ethereum/go-ethereum/log" + "github.com/libp2p/go-libp2p/core/peer" +) + +type ScoreBook interface { + GetPeerScores(id peer.ID) (store.PeerScores, error) + SetScore(id peer.ID, diff store.ScoreDiff) (store.PeerScores, error) +} + +type ApplicationScorer interface { + ApplicationScore(id peer.ID) float64 + onValidResponse(id peer.ID) + onResponseError(id peer.ID) + onRejectedPayload(id peer.ID) + start() + stop() +} + +type peerApplicationScorer struct { + ctx context.Context + cancelFunc context.CancelFunc + log log.Logger + clock clock.Clock + params *ApplicationScoreParams + scorebook ScoreBook + connectedPeers func() []peer.ID + + done sync.WaitGroup +} + +var _ ApplicationScorer = (*peerApplicationScorer)(nil) + +func newPeerApplicationScorer(ctx context.Context, logger log.Logger, clock clock.Clock, params *ApplicationScoreParams, scorebook ScoreBook, connectedPeers func() []peer.ID) *peerApplicationScorer { + ctx, cancelFunc := context.WithCancel(ctx) + return &peerApplicationScorer{ + ctx: ctx, + cancelFunc: cancelFunc, + log: logger, + clock: clock, + params: params, + scorebook: scorebook, + connectedPeers: connectedPeers, + } +} + +func (s *peerApplicationScorer) ApplicationScore(id peer.ID) float64 { + scores, err := s.scorebook.GetPeerScores(id) + if err != nil { + s.log.Error("Failed to load peer scores", "peer", id, "err", err) + return 0 + } + score := scores.ReqResp.ValidResponses * s.params.ValidResponseWeight + score += scores.ReqResp.ErrorResponses * s.params.ErrorResponseWeight + score += scores.ReqResp.RejectedPayloads * s.params.RejectedPayloadWeight + return score +} + +func (s *peerApplicationScorer) onValidResponse(id peer.ID) { + _, err := s.scorebook.SetScore(id, store.IncrementValidResponses{Cap: s.params.ValidResponseCap}) + if err != nil { + s.log.Error("Unable to update peer score", "peer", id, "err", err) + return + } +} + +func (s *peerApplicationScorer) onResponseError(id peer.ID) { + _, err := s.scorebook.SetScore(id, store.IncrementErrorResponses{Cap: s.params.ErrorResponseCap}) + if err != nil { + s.log.Error("Unable to update peer score", "peer", id, "err", err) + return + } +} + +func (s *peerApplicationScorer) onRejectedPayload(id peer.ID) { + _, err := s.scorebook.SetScore(id, store.IncrementRejectedPayloads{Cap: s.params.RejectedPayloadCap}) + if err != nil { + s.log.Error("Unable to update peer score", "peer", id, "err", err) + return + } +} + +func (s *peerApplicationScorer) decayScores(id peer.ID) { + _, err := s.scorebook.SetScore(id, &store.DecayApplicationScores{ + ValidResponseDecay: s.params.ValidResponseDecay, + ErrorResponseDecay: s.params.ErrorResponseDecay, + RejectedPayloadDecay: s.params.RejectedPayloadDecay, + DecayToZero: s.params.DecayToZero, + }) + if err != nil { + s.log.Error("Unable to decay peer score", "peer", id, "err", err) + return + } +} + +func (s *peerApplicationScorer) decayConnectedPeerScores() { + for _, id := range s.connectedPeers() { + s.decayScores(id) + } +} + +func (s *peerApplicationScorer) start() { + s.done.Add(1) + go func() { + defer s.done.Done() + ticker := s.clock.NewTicker(s.params.DecayInterval) + for { + select { + case <-s.ctx.Done(): + return + case <-ticker.Ch(): + s.decayConnectedPeerScores() + } + } + }() +} + +func (s *peerApplicationScorer) stop() { + s.cancelFunc() + s.done.Wait() +} + +type NoopApplicationScorer struct{} + +func (n *NoopApplicationScorer) ApplicationScore(_ peer.ID) float64 { + return 0 +} + +func (n *NoopApplicationScorer) onValidResponse(_ peer.ID) { +} + +func (n *NoopApplicationScorer) onResponseError(_ peer.ID) { +} + +func (n *NoopApplicationScorer) onRejectedPayload(_ peer.ID) { +} + +func (n *NoopApplicationScorer) start() { +} + +func (n *NoopApplicationScorer) stop() { +} + +var _ ApplicationScorer = (*NoopApplicationScorer)(nil) diff --git a/op-node/p2p/app_scores_test.go b/op-node/p2p/app_scores_test.go new file mode 100644 index 000000000000..82122a142418 --- /dev/null +++ b/op-node/p2p/app_scores_test.go @@ -0,0 +1,167 @@ +package p2p + +import ( + "context" + "errors" + "testing" + "time" + + "github.com/ethereum-optimism/optimism/op-node/p2p/store" + "github.com/ethereum-optimism/optimism/op-node/testlog" + "github.com/ethereum-optimism/optimism/op-service/clock" + "github.com/ethereum/go-ethereum/log" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/stretchr/testify/require" +) + +type stubScoreBookUpdate struct { + id peer.ID + diff store.ScoreDiff +} +type stubScoreBook struct { + err error + scores map[peer.ID]store.PeerScores + updates chan stubScoreBookUpdate +} + +func (s *stubScoreBook) GetPeerScores(id peer.ID) (store.PeerScores, error) { + if s.err != nil { + return store.PeerScores{}, s.err + } + scores, ok := s.scores[id] + if !ok { + return store.PeerScores{}, nil + } + return scores, nil +} + +func (s *stubScoreBook) SetScore(id peer.ID, diff store.ScoreDiff) (store.PeerScores, error) { + s.updates <- stubScoreBookUpdate{id, diff} + return s.GetPeerScores(id) +} + +type appScoreTestData struct { + ctx context.Context + logger log.Logger + clock *clock.DeterministicClock + peers []peer.ID + scorebook *stubScoreBook +} + +func (a *appScoreTestData) WaitForNextScoreBookUpdate(t *testing.T) stubScoreBookUpdate { + ctx, cancelFunc := context.WithTimeout(a.ctx, 30*time.Second) + defer cancelFunc() + select { + case update := <-a.scorebook.updates: + return update + case <-ctx.Done(): + t.Fatal("Did not receive expected scorebook update") + return stubScoreBookUpdate{} + } +} + +func setupPeerApplicationScorerTest(t *testing.T, params *ApplicationScoreParams) (*appScoreTestData, *peerApplicationScorer) { + data := &appScoreTestData{ + ctx: context.Background(), + logger: testlog.Logger(t, log.LvlInfo), + clock: clock.NewDeterministicClock(time.UnixMilli(1000)), + peers: []peer.ID{}, + scorebook: &stubScoreBook{ + scores: make(map[peer.ID]store.PeerScores), + updates: make(chan stubScoreBookUpdate, 10), + }, + } + appScorer := newPeerApplicationScorer(data.ctx, data.logger, data.clock, params, data.scorebook, func() []peer.ID { + return data.peers + }) + return data, appScorer +} + +func TestIncrementValidResponses(t *testing.T) { + data, appScorer := setupPeerApplicationScorerTest(t, &ApplicationScoreParams{ + ValidResponseCap: 10, + }) + + appScorer.onValidResponse("aaa") + require.Len(t, data.scorebook.updates, 1) + update := <-data.scorebook.updates + require.Equal(t, stubScoreBookUpdate{peer.ID("aaa"), store.IncrementValidResponses{Cap: 10}}, update) +} + +func TestIncrementErrorResponses(t *testing.T) { + data, appScorer := setupPeerApplicationScorerTest(t, &ApplicationScoreParams{ + ErrorResponseCap: 10, + }) + + appScorer.onResponseError("aaa") + require.Len(t, data.scorebook.updates, 1) + update := <-data.scorebook.updates + require.Equal(t, stubScoreBookUpdate{peer.ID("aaa"), store.IncrementErrorResponses{Cap: 10}}, update) +} + +func TestIncrementRejectedPayloads(t *testing.T) { + data, appScorer := setupPeerApplicationScorerTest(t, &ApplicationScoreParams{ + RejectedPayloadCap: 10, + }) + + appScorer.onRejectedPayload("aaa") + require.Len(t, data.scorebook.updates, 1) + update := <-data.scorebook.updates + require.Equal(t, stubScoreBookUpdate{peer.ID("aaa"), store.IncrementRejectedPayloads{Cap: 10}}, update) +} + +func TestApplicationScore(t *testing.T) { + data, appScorer := setupPeerApplicationScorerTest(t, &ApplicationScoreParams{ + ValidResponseWeight: 0.8, + ErrorResponseWeight: 0.6, + RejectedPayloadWeight: 0.4, + }) + + peerScore := store.PeerScores{ + ReqResp: store.ReqRespScores{ + ValidResponses: 1, + ErrorResponses: 2, + RejectedPayloads: 3, + }, + } + data.scorebook.scores["aaa"] = peerScore + score := appScorer.ApplicationScore("aaa") + require.Equal(t, 1*0.8+2*0.6+3*0.4, score) +} + +func TestApplicationScoreZeroWhenScoreDoesNotLoad(t *testing.T) { + data, appScorer := setupPeerApplicationScorerTest(t, &ApplicationScoreParams{}) + + data.scorebook.err = errors.New("boom") + score := appScorer.ApplicationScore("aaa") + require.Zero(t, score) +} + +func TestDecayScoresAfterDecayInterval(t *testing.T) { + params := &ApplicationScoreParams{ + ValidResponseDecay: 0.8, + ErrorResponseDecay: 0.7, + RejectedPayloadDecay: 0.3, + DecayToZero: 0.1, + DecayInterval: 90 * time.Second, + } + data, appScorer := setupPeerApplicationScorerTest(t, params) + data.peers = []peer.ID{"aaa", "bbb"} + + expectedDecay := &store.DecayApplicationScores{ + ValidResponseDecay: 0.8, + ErrorResponseDecay: 0.7, + RejectedPayloadDecay: 0.3, + DecayToZero: 0.1, + } + + appScorer.start() + defer appScorer.stop() + + data.clock.WaitForNewPendingTaskWithTimeout(30 * time.Second) + + data.clock.AdvanceTime(params.DecayInterval) + + require.Equal(t, stubScoreBookUpdate{id: "aaa", diff: expectedDecay}, data.WaitForNextScoreBookUpdate(t)) + require.Equal(t, stubScoreBookUpdate{id: "bbb", diff: expectedDecay}, data.WaitForNextScoreBookUpdate(t)) +} diff --git a/op-node/p2p/cli/load_config.go b/op-node/p2p/cli/load_config.go index 1f272c7d5a99..6605dea4af8d 100644 --- a/op-node/p2p/cli/load_config.go +++ b/op-node/p2p/cli/load_config.go @@ -20,7 +20,7 @@ import ( "github.com/ethereum-optimism/optimism/op-node/flags" "github.com/ethereum-optimism/optimism/op-node/p2p" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum/go-ethereum/p2p/enode" ) @@ -28,7 +28,7 @@ import ( func NewConfig(ctx *cli.Context, rollupCfg *rollup.Config) (*p2p.Config, error) { conf := &p2p.Config{} - if ctx.GlobalBool(flags.DisableP2P.Name) { + if ctx.Bool(flags.DisableP2P.Name) { conf.DisableP2P = true return conf, nil } @@ -63,7 +63,7 @@ func NewConfig(ctx *cli.Context, rollupCfg *rollup.Config) (*p2p.Config, error) return nil, fmt.Errorf("failed to load banning option: %w", err) } - conf.EnableReqRespSync = ctx.GlobalBool(flags.SyncReqRespFlag.Name) + conf.EnableReqRespSync = ctx.Bool(flags.SyncReqRespFlag.Name) return conf, nil } @@ -83,13 +83,13 @@ func validatePort(p uint) (uint16, error) { // loadScoringParams loads the peer scoring options from the CLI context. func loadScoringParams(conf *p2p.Config, ctx *cli.Context, rollupCfg *rollup.Config) error { - scoringLevel := ctx.GlobalString(flags.Scoring.Name) + scoringLevel := ctx.String(flags.Scoring.Name) // Check old names for backwards compatibility if scoringLevel == "" { - scoringLevel = ctx.GlobalString(flags.PeerScoring.Name) + scoringLevel = ctx.String(flags.PeerScoring.Name) } if scoringLevel == "" { - scoringLevel = ctx.GlobalString(flags.TopicScoring.Name) + scoringLevel = ctx.String(flags.TopicScoring.Name) } if scoringLevel != "" { params, err := p2p.GetScoringParams(scoringLevel, rollupCfg) @@ -104,14 +104,14 @@ func loadScoringParams(conf *p2p.Config, ctx *cli.Context, rollupCfg *rollup.Con // loadBanningOptions loads whether or not to ban peers from the CLI context. func loadBanningOptions(conf *p2p.Config, ctx *cli.Context) error { - conf.BanningEnabled = ctx.GlobalBool(flags.Banning.Name) - conf.BanningThreshold = ctx.GlobalFloat64(flags.BanningThreshold.Name) - conf.BanningDuration = ctx.GlobalDuration(flags.BanningDuration.Name) + conf.BanningEnabled = ctx.Bool(flags.Banning.Name) + conf.BanningThreshold = ctx.Float64(flags.BanningThreshold.Name) + conf.BanningDuration = ctx.Duration(flags.BanningDuration.Name) return nil } func loadListenOpts(conf *p2p.Config, ctx *cli.Context) error { - listenIP := ctx.GlobalString(flags.ListenIP.Name) + listenIP := ctx.String(flags.ListenIP.Name) if listenIP != "" { // optional conf.ListenIP = net.ParseIP(listenIP) if conf.ListenIP == nil { @@ -119,11 +119,11 @@ func loadListenOpts(conf *p2p.Config, ctx *cli.Context) error { } } var err error - conf.ListenTCPPort, err = validatePort(ctx.GlobalUint(flags.ListenTCPPort.Name)) + conf.ListenTCPPort, err = validatePort(ctx.Uint(flags.ListenTCPPort.Name)) if err != nil { return fmt.Errorf("bad listen TCP port: %w", err) } - conf.ListenUDPPort, err = validatePort(ctx.GlobalUint(flags.ListenUDPPort.Name)) + conf.ListenUDPPort, err = validatePort(ctx.Uint(flags.ListenUDPPort.Name)) if err != nil { return fmt.Errorf("bad listen UDP port: %w", err) } @@ -131,20 +131,20 @@ func loadListenOpts(conf *p2p.Config, ctx *cli.Context) error { } func loadDiscoveryOpts(conf *p2p.Config, ctx *cli.Context) error { - if ctx.GlobalBool(flags.NoDiscovery.Name) { + if ctx.Bool(flags.NoDiscovery.Name) { conf.NoDiscovery = true } var err error - conf.AdvertiseTCPPort, err = validatePort(ctx.GlobalUint(flags.AdvertiseTCPPort.Name)) + conf.AdvertiseTCPPort, err = validatePort(ctx.Uint(flags.AdvertiseTCPPort.Name)) if err != nil { return fmt.Errorf("bad advertised TCP port: %w", err) } - conf.AdvertiseUDPPort, err = validatePort(ctx.GlobalUint(flags.AdvertiseUDPPort.Name)) + conf.AdvertiseUDPPort, err = validatePort(ctx.Uint(flags.AdvertiseUDPPort.Name)) if err != nil { return fmt.Errorf("bad advertised UDP port: %w", err) } - adIP := ctx.GlobalString(flags.AdvertiseIP.Name) + adIP := ctx.String(flags.AdvertiseIP.Name) if adIP != "" { // optional ips, err := net.LookupIP(adIP) if err != nil { @@ -162,7 +162,7 @@ func loadDiscoveryOpts(conf *p2p.Config, ctx *cli.Context) error { } } - dbPath := ctx.GlobalString(flags.DiscoveryPath.Name) + dbPath := ctx.String(flags.DiscoveryPath.Name) if dbPath == "" { dbPath = "opnode_discovery_db" } @@ -175,7 +175,7 @@ func loadDiscoveryOpts(conf *p2p.Config, ctx *cli.Context) error { } bootnodes := make([]*enode.Node, 0) - records := strings.Split(ctx.GlobalString(flags.Bootnodes.Name), ",") + records := strings.Split(ctx.String(flags.Bootnodes.Name), ",") for i, recordB64 := range records { recordB64 = strings.TrimSpace(recordB64) if recordB64 == "" { // ignore empty records @@ -197,7 +197,7 @@ func loadDiscoveryOpts(conf *p2p.Config, ctx *cli.Context) error { } func loadLibp2pOpts(conf *p2p.Config, ctx *cli.Context) error { - addrs := strings.Split(ctx.GlobalString(flags.StaticPeers.Name), ",") + addrs := strings.Split(ctx.String(flags.StaticPeers.Name), ",") for i, addr := range addrs { addr = strings.TrimSpace(addr) if addr == "" { @@ -210,7 +210,7 @@ func loadLibp2pOpts(conf *p2p.Config, ctx *cli.Context) error { conf.StaticPeers = append(conf.StaticPeers, a) } - for _, v := range strings.Split(ctx.GlobalString(flags.HostMux.Name), ",") { + for _, v := range strings.Split(ctx.String(flags.HostMux.Name), ",") { v = strings.ToLower(strings.TrimSpace(v)) switch v { case "yamux": @@ -222,7 +222,7 @@ func loadLibp2pOpts(conf *p2p.Config, ctx *cli.Context) error { } } - secArr := strings.Split(ctx.GlobalString(flags.HostSecurity.Name), ",") + secArr := strings.Split(ctx.String(flags.HostSecurity.Name), ",") for _, v := range secArr { v = strings.ToLower(strings.TrimSpace(v)) switch v { @@ -240,16 +240,16 @@ func loadLibp2pOpts(conf *p2p.Config, ctx *cli.Context) error { } } - 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) + conf.PeersLo = ctx.Uint(flags.PeersLo.Name) + conf.PeersHi = ctx.Uint(flags.PeersHi.Name) + conf.PeersGrace = ctx.Duration(flags.PeersGrace.Name) + conf.NAT = ctx.Bool(flags.NAT.Name) + conf.UserAgent = ctx.String(flags.UserAgent.Name) + conf.TimeoutNegotiation = ctx.Duration(flags.TimeoutNegotiation.Name) + conf.TimeoutAccept = ctx.Duration(flags.TimeoutAccept.Name) + conf.TimeoutDial = ctx.Duration(flags.TimeoutDial.Name) - peerstorePath := ctx.GlobalString(flags.PeerstorePath.Name) + peerstorePath := ctx.String(flags.PeerstorePath.Name) if peerstorePath == "" { return errors.New("peerstore path must be specified, use 'memory' to explicitly not persist peer records") } @@ -270,11 +270,11 @@ func loadLibp2pOpts(conf *p2p.Config, ctx *cli.Context) error { } func loadNetworkPrivKey(ctx *cli.Context) (*crypto.Secp256k1PrivateKey, error) { - raw := ctx.GlobalString(flags.P2PPrivRaw.Name) + raw := ctx.String(flags.P2PPrivRaw.Name) if raw != "" { return parsePriv(raw) } - keyPath := ctx.GlobalString(flags.P2PPrivPath.Name) + keyPath := ctx.String(flags.P2PPrivPath.Name) if keyPath == "" { return nil, errors.New("no p2p private key path specified, cannot auto-generate key without path") } @@ -324,10 +324,10 @@ func parsePriv(data string) (*crypto.Secp256k1PrivateKey, error) { } 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) + conf.MeshD = ctx.Int(flags.GossipMeshDFlag.Name) + conf.MeshDLo = ctx.Int(flags.GossipMeshDloFlag.Name) + conf.MeshDHi = ctx.Int(flags.GossipMeshDhiFlag.Name) + conf.MeshDLazy = ctx.Int(flags.GossipMeshDlazyFlag.Name) + conf.FloodPublish = ctx.Bool(flags.GossipFloodPublishFlag.Name) return nil } diff --git a/op-node/p2p/cli/load_signer.go b/op-node/p2p/cli/load_signer.go index 44e8c3eb0eb6..bb89c92bf540 100644 --- a/op-node/p2p/cli/load_signer.go +++ b/op-node/p2p/cli/load_signer.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/ethereum/go-ethereum/crypto" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/op-node/flags" "github.com/ethereum-optimism/optimism/op-node/p2p" @@ -15,7 +15,7 @@ import ( // 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) + key := ctx.String(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). diff --git a/op-node/p2p/config.go b/op-node/p2p/config.go index 266f12914161..c5f2d5633486 100644 --- a/op-node/p2p/config.go +++ b/op-node/p2p/config.go @@ -53,7 +53,8 @@ type SetupP2P interface { // ScoringParams defines the various types of peer scoring parameters. type ScoringParams struct { - PeerScoring pubsub.PeerScoreParams + PeerScoring pubsub.PeerScoreParams + ApplicationScoring ApplicationScoreParams } // Config sets up a p2p host and discv5 service from configuration. @@ -137,11 +138,11 @@ func (conf *Config) Disabled() bool { return conf.DisableP2P } -func (conf *Config) PeerScoringParams() *pubsub.PeerScoreParams { +func (conf *Config) PeerScoringParams() *ScoringParams { if conf.ScoringParams == nil { return nil } - return &conf.ScoringParams.PeerScoring + return conf.ScoringParams } func (conf *Config) BanPeers() bool { diff --git a/op-node/p2p/gossip.go b/op-node/p2p/gossip.go index 36694156a372..1669a14f5383 100644 --- a/op-node/p2p/gossip.go +++ b/op-node/p2p/gossip.go @@ -51,7 +51,7 @@ var MessageDomainInvalidSnappy = [4]byte{0, 0, 0, 0} var MessageDomainValidSnappy = [4]byte{1, 0, 0, 0} type GossipSetupConfigurables interface { - PeerScoringParams() *pubsub.PeerScoreParams + PeerScoringParams() *ScoringParams // ConfigureGossip creates configuration options to apply to the GossipSub setup ConfigureGossip(rollupCfg *rollup.Config) []pubsub.Option } diff --git a/op-node/p2p/host.go b/op-node/p2p/host.go index a2a3510417a7..d7294f016670 100644 --- a/op-node/p2p/host.go +++ b/op-node/p2p/host.go @@ -149,7 +149,7 @@ func (conf *Config) Host(log log.Logger, reporter metrics.Reporter, metrics Host var scoreRetention time.Duration if peerScoreParams != nil { // Use the same retention period as gossip will if available - scoreRetention = peerScoreParams.RetainScore + scoreRetention = peerScoreParams.PeerScoring.RetainScore } else { // Disable score GC if peer scoring is disabled scoreRetention = 0 diff --git a/op-node/p2p/node.go b/op-node/p2p/node.go index 6fae5dae6bd7..92aeaef5bc43 100644 --- a/op-node/p2p/node.go +++ b/op-node/p2p/node.go @@ -37,6 +37,7 @@ type NodeP2P struct { connMgr connmgr.ConnManager // p2p conn manager, to keep a reliable number of peers, may be nil even with p2p enabled peerMonitor *monitor.PeerMonitor // peer monitor to disconnect bad peers, may be nil even with p2p enabled store store.ExtendedPeerstore // peerstore of host, with extra bindings for scoring and banning + appScorer ApplicationScorer log log.Logger // the below components are all optional, and may be nil. They require the host to not be nil. dv5Local *enode.LocalNode // p2p discovery identity @@ -89,9 +90,21 @@ func (n *NodeP2P) init(resourcesCtx context.Context, rollupCfg *rollup.Config, l n.gater = extra.ConnectionGater() n.connMgr = extra.ConnectionManager() } + eps, ok := n.host.Peerstore().(store.ExtendedPeerstore) + if !ok { + return fmt.Errorf("cannot init without extended peerstore: %w", err) + } + n.store = eps + scoreParams := setup.PeerScoringParams() + + if scoreParams != nil { + n.appScorer = newPeerApplicationScorer(resourcesCtx, log, clock.SystemClock, &scoreParams.ApplicationScoring, eps, n.host.Network().Peers) + } else { + n.appScorer = &NoopApplicationScorer{} + } // Activate the P2P req-resp sync if enabled by feature-flag. if setup.ReqRespSyncEnabled() { - n.syncCl = NewSyncClient(log, rollupCfg, n.host.NewStream, gossipIn.OnUnsafeL2Payload, metrics) + n.syncCl = NewSyncClient(log, rollupCfg, n.host.NewStream, gossipIn.OnUnsafeL2Payload, metrics, n.appScorer) n.host.Network().Notify(&network.NotifyBundle{ ConnectedF: func(nw network.Network, conn network.Conn) { n.syncCl.AddPeer(conn.RemotePeer()) @@ -112,12 +125,7 @@ func (n *NodeP2P) init(resourcesCtx context.Context, rollupCfg *rollup.Config, l n.host.SetStreamHandler(PayloadByNumberProtocolID(rollupCfg.L2ChainID), payloadByNumber) } } - eps, ok := n.host.Peerstore().(store.ExtendedPeerstore) - if !ok { - return fmt.Errorf("cannot init without extended peerstore: %w", err) - } - n.store = eps - n.scorer = NewScorer(rollupCfg, eps, metrics, log) + n.scorer = NewScorer(rollupCfg, eps, metrics, n.appScorer, log) // notify of any new connections/streams/etc. n.host.Network().Notify(NewNetworkNotifier(log, metrics)) // note: the IDDelta functionality was removed from libP2P, and no longer needs to be explicitly disabled. @@ -150,6 +158,7 @@ func (n *NodeP2P) init(resourcesCtx context.Context, rollupCfg *rollup.Config, l n.peerMonitor = monitor.NewPeerMonitor(resourcesCtx, log, clock.SystemClock, n, setup.BanThreshold(), setup.BanDuration()) n.peerMonitor.Start() } + n.appScorer.start() } return nil } @@ -258,6 +267,9 @@ func (n *NodeP2P) Close() error { } } } + if n.appScorer != nil { + n.appScorer.stop() + } return result.ErrorOrNil() } diff --git a/op-node/p2p/peer_params.go b/op-node/p2p/peer_params.go index fcfaf3d689cc..6a60e2160b28 100644 --- a/op-node/p2p/peer_params.go +++ b/op-node/p2p/peer_params.go @@ -32,7 +32,7 @@ func ScoreDecay(duration time.Duration, slot time.Duration) float64 { // See [PeerScoreParams] for detailed documentation. // // [PeerScoreParams]: https://pkg.go.dev/github.com/libp2p/go-libp2p-pubsub@v0.8.1#PeerScoreParams -var LightPeerScoreParams = func(cfg *rollup.Config) pubsub.PeerScoreParams { +func LightPeerScoreParams(cfg *rollup.Config) pubsub.PeerScoreParams { slot := time.Duration(cfg.BlockTime) * time.Second if slot == 0 { slot = 2 * time.Second @@ -91,7 +91,8 @@ func GetScoringParams(name string, cfg *rollup.Config) (*ScoringParams, error) { switch name { case "light": return &ScoringParams{ - PeerScoring: LightPeerScoreParams(cfg), + PeerScoring: LightPeerScoreParams(cfg), + ApplicationScoring: LightApplicationScoreParams(cfg), }, nil case "none": return nil, nil diff --git a/op-node/p2p/peer_params_test.go b/op-node/p2p/peer_params_test.go index 2630647ac214..53b25b1e91fc 100644 --- a/op-node/p2p/peer_params_test.go +++ b/op-node/p2p/peer_params_test.go @@ -81,6 +81,19 @@ func (testSuite *PeerParamsTestSuite) TestGetPeerScoreParams_Light() { testSuite.Equal(peerParams.DecayInterval, slot) testSuite.Equal(peerParams.DecayToZero, DecayToZero) testSuite.Equal(peerParams.RetainScore, oneHundredEpochs) + + appParams := scoringParams.ApplicationScoring + testSuite.Positive(appParams.ValidResponseCap) + testSuite.Positive(appParams.ValidResponseWeight) + testSuite.Positive(appParams.ValidResponseDecay) + testSuite.Positive(appParams.ErrorResponseCap) + testSuite.Negative(appParams.ErrorResponseWeight) + testSuite.Positive(appParams.ErrorResponseDecay) + testSuite.Positive(appParams.RejectedPayloadCap) + testSuite.Negative(appParams.RejectedPayloadWeight) + testSuite.Positive(appParams.RejectedPayloadDecay) + testSuite.Equal(DecayToZero, appParams.DecayToZero) + testSuite.Equal(slot, appParams.DecayInterval) } // TestParamsZeroBlockTime validates peer score params use default slot for 0 block time. @@ -91,4 +104,5 @@ func (testSuite *PeerParamsTestSuite) TestParamsZeroBlockTime() { params, err := GetScoringParams("light", &cfg) testSuite.NoError(err) testSuite.Equal(params.PeerScoring.DecayInterval, slot) + testSuite.Equal(params.ApplicationScoring.DecayInterval, slot) } diff --git a/op-node/p2p/peer_scorer.go b/op-node/p2p/peer_scorer.go index feb831d2edfe..e8a46bbcebe3 100644 --- a/op-node/p2p/peer_scorer.go +++ b/op-node/p2p/peer_scorer.go @@ -14,6 +14,7 @@ import ( type scorer struct { peerStore Peerstore metricer ScoreMetrics + appScorer ApplicationScorer log log.Logger cfg *rollup.Config } @@ -36,6 +37,7 @@ type Peerstore interface { // Scorer is a peer scorer that scores peers based on application-specific metrics. type Scorer interface { SnapshotHook() pubsub.ExtendedPeerScoreInspectFn + ApplicationScore(peer.ID) float64 } //go:generate mockery --name ScoreMetrics --output mocks/ @@ -44,10 +46,11 @@ type ScoreMetrics interface { } // NewScorer returns a new peer scorer. -func NewScorer(cfg *rollup.Config, peerStore Peerstore, metricer ScoreMetrics, log log.Logger) Scorer { +func NewScorer(cfg *rollup.Config, peerStore Peerstore, metricer ScoreMetrics, appScorer ApplicationScorer, log log.Logger) Scorer { return &scorer{ peerStore: peerStore, metricer: metricer, + appScorer: appScorer, log: log, cfg: cfg, } @@ -84,3 +87,7 @@ func (s *scorer) SnapshotHook() pubsub.ExtendedPeerScoreInspectFn { s.metricer.SetPeerScores(allScores) } } + +func (s *scorer) ApplicationScore(id peer.ID) float64 { + return s.appScorer.ApplicationScore(id) +} diff --git a/op-node/p2p/peer_scorer_test.go b/op-node/p2p/peer_scorer_test.go index cb39a5546b40..0abd18b1442f 100644 --- a/op-node/p2p/peer_scorer_test.go +++ b/op-node/p2p/peer_scorer_test.go @@ -44,6 +44,7 @@ func (testSuite *PeerScorerTestSuite) TestScorer_SnapshotHook() { &rollup.Config{L2ChainID: big.NewInt(123)}, testSuite.mockStore, testSuite.mockMetricer, + &p2p.NoopApplicationScorer{}, testSuite.logger, ) inspectFn := scorer.SnapshotHook() diff --git a/op-node/p2p/peer_scores.go b/op-node/p2p/peer_scores.go index 081dc8beb9f0..66647fd62d2a 100644 --- a/op-node/p2p/peer_scores.go +++ b/op-node/p2p/peer_scores.go @@ -9,12 +9,15 @@ import ( func ConfigurePeerScoring(gossipConf GossipSetupConfigurables, scorer Scorer, log log.Logger) []pubsub.Option { // If we want to completely disable scoring config here, we can use the [peerScoringParams] // to return early without returning any [pubsub.Option]. - peerScoreParams := gossipConf.PeerScoringParams() - peerScoreThresholds := NewPeerScoreThresholds() + scoreParams := gossipConf.PeerScoringParams() opts := []pubsub.Option{} - if peerScoreParams != nil { + if scoreParams != nil { + peerScoreThresholds := NewPeerScoreThresholds() + // Create copy of params before modifying the AppSpecificScore + params := scoreParams.PeerScoring + params.AppSpecificScore = scorer.ApplicationScore opts = []pubsub.Option{ - pubsub.WithPeerScore(peerScoreParams, &peerScoreThresholds), + pubsub.WithPeerScore(¶ms, &peerScoreThresholds), pubsub.WithPeerScoreInspect(scorer.SnapshotHook(), peerScoreInspectFrequency), } } else { diff --git a/op-node/p2p/peer_scores_test.go b/op-node/p2p/peer_scores_test.go index 52406f4a5667..37b77b575793 100644 --- a/op-node/p2p/peer_scores_test.go +++ b/op-node/p2p/peer_scores_test.go @@ -82,6 +82,18 @@ func getNetHosts(testSuite *PeerScoresTestSuite, ctx context.Context, n int) []h return out } +type discriminatingAppScorer struct { + badPeer peer.ID + NoopApplicationScorer +} + +func (d *discriminatingAppScorer) ApplicationScore(id peer.ID) float64 { + if id == d.badPeer { + return -1000 + } + return 0 +} + func newGossipSubs(testSuite *PeerScoresTestSuite, ctx context.Context, hosts []host.Host) []*pubsub.PubSub { var psubs []*pubsub.PubSub @@ -100,17 +112,10 @@ func newGossipSubs(testSuite *PeerScoresTestSuite, ctx context.Context, hosts [] scorer := NewScorer( &rollup.Config{L2ChainID: big.NewInt(123)}, - extPeerStore, testSuite.mockMetricer, logger) + extPeerStore, testSuite.mockMetricer, &discriminatingAppScorer{badPeer: hosts[0].ID()}, logger) opts = append(opts, ConfigurePeerScoring(&Config{ ScoringParams: &ScoringParams{ PeerScoring: pubsub.PeerScoreParams{ - AppSpecificScore: func(p peer.ID) float64 { - if p == hosts[0].ID() { - return -1000 - } else { - return 0 - } - }, AppSpecificWeight: 1, DecayInterval: time.Second, DecayToZero: 0.01, diff --git a/op-node/p2p/prepared.go b/op-node/p2p/prepared.go index 7b66191d8244..dfa49a009695 100644 --- a/op-node/p2p/prepared.go +++ b/op-node/p2p/prepared.go @@ -69,7 +69,7 @@ func (p *Prepared) ConfigureGossip(rollupCfg *rollup.Config) []pubsub.Option { } } -func (p *Prepared) PeerScoringParams() *pubsub.PeerScoreParams { +func (p *Prepared) PeerScoringParams() *ScoringParams { return nil } diff --git a/op-node/p2p/sync.go b/op-node/p2p/sync.go index ab2b8f46290c..d5c1f15f5c38 100644 --- a/op-node/p2p/sync.go +++ b/op-node/p2p/sync.go @@ -111,6 +111,12 @@ type SyncClientMetrics interface { PayloadsQuarantineSize(n int) } +type SyncPeerScorer interface { + onValidResponse(id peer.ID) + onResponseError(id peer.ID) + onRejectedPayload(id peer.ID) +} + // SyncClient implements a reverse chain sync with a minimal interface: // signal the desired range, and receive blocks within this range back. // Through parent-hash verification, received blocks are all ensured to be part of the canonical chain at one point, @@ -180,7 +186,8 @@ type SyncClient struct { cfg *rollup.Config - metrics SyncClientMetrics + metrics SyncClientMetrics + appScorer SyncPeerScorer newStreamFn newStreamFn payloadByNumber protocol.ID @@ -227,13 +234,14 @@ type SyncClient struct { closingPeers bool } -func NewSyncClient(log log.Logger, cfg *rollup.Config, newStream newStreamFn, rcv receivePayloadFn, metrics SyncClientMetrics) *SyncClient { +func NewSyncClient(log log.Logger, cfg *rollup.Config, newStream newStreamFn, rcv receivePayloadFn, metrics SyncClientMetrics, appScorer SyncPeerScorer) *SyncClient { ctx, cancel := context.WithCancel(context.Background()) c := &SyncClient{ log: log, cfg: cfg, metrics: metrics, + appScorer: appScorer, newStreamFn: newStream, payloadByNumber: PayloadByNumberProtocolID(cfg.L2ChainID), peers: make(map[peer.ID]context.CancelFunc), @@ -268,11 +276,11 @@ func (s *SyncClient) Start() { func (s *SyncClient) AddPeer(id peer.ID) { s.peersLock.Lock() defer s.peersLock.Unlock() - if _, ok := s.peers[id]; ok { - s.log.Warn("cannot register peer for sync duties, peer was already registered", "peer", id) + if s.closingPeers { return } - if s.closingPeers { + if _, ok := s.peers[id]; ok { + s.log.Warn("cannot register peer for sync duties, peer was already registered", "peer", id) return } s.wg.Add(1) @@ -424,7 +432,8 @@ func (s *SyncClient) onQuarantineEvict(key common.Hash, value syncResult) { s.metrics.PayloadsQuarantineSize(s.quarantine.Len()) if !s.trusted.Contains(key) { s.log.Debug("evicting untrusted payload from quarantine", "id", value.payload.ID(), "peer", value.peer) - // TODO(CLI-3732): downscore peer for having provided us a bad block that never turned out to be canonical + // Down-score peer for having provided us a bad block that never turned out to be canonical + s.appScorer.onRejectedPayload(value.peer) } else { s.log.Debug("evicting trusted payload from quarantine", "id", value.payload.ID(), "peer", value.peer) } @@ -492,9 +501,9 @@ func (s *SyncClient) peerLoop(ctx context.Context, id peer.ID) { defer func() { s.peersLock.Lock() delete(s.peers, id) // clean up + s.log.Debug("stopped syncing loop of peer", "id", id) s.wg.Done() s.peersLock.Unlock() - s.log.Debug("stopped syncing loop of peer", "id", id) }() log := s.log.New("peer", id) @@ -525,6 +534,7 @@ func (s *SyncClient) peerLoop(ctx context.Context, id peer.ID) { // mark as complete if there's an error: we are not sending any result and can complete immediately. pr.complete.Store(true) log.Warn("failed p2p sync request", "num", pr.num, "err", err) + s.appScorer.onResponseError(id) // If we hit an error, then count it as many requests. // We'd like to avoid making more requests for a while, to back off. if err := rl.WaitN(ctx, clientErrRateCost); err != nil { @@ -532,11 +542,9 @@ func (s *SyncClient) peerLoop(ctx context.Context, id peer.ID) { } } else { log.Debug("completed p2p sync request", "num", pr.num) + s.appScorer.onValidResponse(id) } took := time.Since(start) - // TODO(CLI-3732): update scores: depending on the speed of the result, - // increase the p2p-sync part of the peer score - // (don't allow the score to grow indefinitely only based on this factor though) resultCode := byte(0) if err != nil { diff --git a/op-node/p2p/sync_test.go b/op-node/p2p/sync_test.go index a11bf9168189..fe13dc8bbf3d 100644 --- a/op-node/p2p/sync_test.go +++ b/op-node/p2p/sync_test.go @@ -137,7 +137,7 @@ func TestSinglePeerSync(t *testing.T) { hostA.SetStreamHandler(PayloadByNumberProtocolID(cfg.L2ChainID), payloadByNumber) // Setup host B as the client - cl := NewSyncClient(log.New("role", "client"), cfg, hostB.NewStream, receivePayload, metrics.NoopMetrics) + cl := NewSyncClient(log.New("role", "client"), cfg, hostB.NewStream, receivePayload, metrics.NoopMetrics, &NoopApplicationScorer{}) // Setup host B (client) to sync from its peer Host A (server) cl.AddPeer(hostA.ID()) @@ -190,7 +190,7 @@ func TestMultiPeerSync(t *testing.T) { payloadByNumber := MakeStreamHandler(ctx, log.New("serve", "payloads_by_number"), srv.HandleSyncRequest) h.SetStreamHandler(PayloadByNumberProtocolID(cfg.L2ChainID), payloadByNumber) - cl := NewSyncClient(log.New("role", "client"), cfg, h.NewStream, receivePayload, metrics.NoopMetrics) + cl := NewSyncClient(log.New("role", "client"), cfg, h.NewStream, receivePayload, metrics.NoopMetrics, &NoopApplicationScorer{}) return cl, received } diff --git a/op-node/service.go b/op-node/service.go index 33c3d5c7d0dc..a6b59f2e5120 100644 --- a/op-node/service.go +++ b/op-node/service.go @@ -12,7 +12,7 @@ import ( "github.com/ethereum-optimism/optimism/op-node/sources" oppprof "github.com/ethereum-optimism/optimism/op-service/pprof" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -64,27 +64,27 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) { Rollup: *rollupConfig, Driver: *driverConfig, RPC: node.RPCConfig{ - ListenAddr: ctx.GlobalString(flags.RPCListenAddr.Name), - ListenPort: ctx.GlobalInt(flags.RPCListenPort.Name), - EnableAdmin: ctx.GlobalBool(flags.RPCEnableAdmin.Name), + ListenAddr: ctx.String(flags.RPCListenAddr.Name), + ListenPort: ctx.Int(flags.RPCListenPort.Name), + EnableAdmin: ctx.Bool(flags.RPCEnableAdmin.Name), }, Metrics: node.MetricsConfig{ - Enabled: ctx.GlobalBool(flags.MetricsEnabledFlag.Name), - ListenAddr: ctx.GlobalString(flags.MetricsAddrFlag.Name), - ListenPort: ctx.GlobalInt(flags.MetricsPortFlag.Name), + Enabled: ctx.Bool(flags.MetricsEnabledFlag.Name), + ListenAddr: ctx.String(flags.MetricsAddrFlag.Name), + ListenPort: ctx.Int(flags.MetricsPortFlag.Name), }, Pprof: oppprof.CLIConfig{ - Enabled: ctx.GlobalBool(flags.PprofEnabledFlag.Name), - ListenAddr: ctx.GlobalString(flags.PprofAddrFlag.Name), - ListenPort: ctx.GlobalInt(flags.PprofPortFlag.Name), + Enabled: ctx.Bool(flags.PprofEnabledFlag.Name), + ListenAddr: ctx.String(flags.PprofAddrFlag.Name), + ListenPort: ctx.Int(flags.PprofPortFlag.Name), }, P2P: p2pConfig, P2PSigner: p2pSignerSetup, - L1EpochPollInterval: ctx.GlobalDuration(flags.L1EpochPollIntervalFlag.Name), + L1EpochPollInterval: ctx.Duration(flags.L1EpochPollIntervalFlag.Name), Heartbeat: node.HeartbeatConfig{ - Enabled: ctx.GlobalBool(flags.HeartbeatEnabledFlag.Name), - Moniker: ctx.GlobalString(flags.HeartbeatMonikerFlag.Name), - URL: ctx.GlobalString(flags.HeartbeatURLFlag.Name), + Enabled: ctx.Bool(flags.HeartbeatEnabledFlag.Name), + Moniker: ctx.String(flags.HeartbeatMonikerFlag.Name), + URL: ctx.String(flags.HeartbeatURLFlag.Name), }, } if err := cfg.Check(); err != nil { @@ -95,18 +95,18 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) { func NewL1EndpointConfig(ctx *cli.Context) *node.L1EndpointConfig { return &node.L1EndpointConfig{ - L1NodeAddr: ctx.GlobalString(flags.L1NodeAddr.Name), - L1TrustRPC: ctx.GlobalBool(flags.L1TrustRPC.Name), - L1RPCKind: sources.RPCProviderKind(strings.ToLower(ctx.GlobalString(flags.L1RPCProviderKind.Name))), - RateLimit: ctx.GlobalFloat64(flags.L1RPCRateLimit.Name), - BatchSize: ctx.GlobalInt(flags.L1RPCMaxBatchSize.Name), + L1NodeAddr: ctx.String(flags.L1NodeAddr.Name), + L1TrustRPC: ctx.Bool(flags.L1TrustRPC.Name), + L1RPCKind: sources.RPCProviderKind(strings.ToLower(ctx.String(flags.L1RPCProviderKind.Name))), + RateLimit: ctx.Float64(flags.L1RPCRateLimit.Name), + BatchSize: ctx.Int(flags.L1RPCMaxBatchSize.Name), HttpPollInterval: ctx.Duration(flags.L1HTTPPollInterval.Name), } } func NewL2EndpointConfig(ctx *cli.Context, log log.Logger) (*node.L2EndpointConfig, error) { - l2Addr := ctx.GlobalString(flags.L2EngineAddr.Name) - fileName := ctx.GlobalString(flags.L2EngineJWTSecret.Name) + l2Addr := ctx.String(flags.L2EngineAddr.Name) + fileName := ctx.String(flags.L2EngineJWTSecret.Name) var secret [32]byte fileName = strings.TrimSpace(fileName) if fileName == "" { @@ -138,23 +138,23 @@ func NewL2EndpointConfig(ctx *cli.Context, log log.Logger) (*node.L2EndpointConf // flag is set, otherwise nil. func NewL2SyncEndpointConfig(ctx *cli.Context) *node.L2SyncEndpointConfig { return &node.L2SyncEndpointConfig{ - L2NodeAddr: ctx.GlobalString(flags.BackupL2UnsafeSyncRPC.Name), - TrustRPC: ctx.GlobalBool(flags.BackupL2UnsafeSyncRPCTrustRPC.Name), + L2NodeAddr: ctx.String(flags.BackupL2UnsafeSyncRPC.Name), + TrustRPC: ctx.Bool(flags.BackupL2UnsafeSyncRPCTrustRPC.Name), } } func NewDriverConfig(ctx *cli.Context) *driver.Config { return &driver.Config{ - VerifierConfDepth: ctx.GlobalUint64(flags.VerifierL1Confs.Name), - SequencerConfDepth: ctx.GlobalUint64(flags.SequencerL1Confs.Name), - SequencerEnabled: ctx.GlobalBool(flags.SequencerEnabledFlag.Name), - SequencerStopped: ctx.GlobalBool(flags.SequencerStoppedFlag.Name), - SequencerMaxSafeLag: ctx.GlobalUint64(flags.SequencerMaxSafeLagFlag.Name), + VerifierConfDepth: ctx.Uint64(flags.VerifierL1Confs.Name), + SequencerConfDepth: ctx.Uint64(flags.SequencerL1Confs.Name), + SequencerEnabled: ctx.Bool(flags.SequencerEnabledFlag.Name), + SequencerStopped: ctx.Bool(flags.SequencerStoppedFlag.Name), + SequencerMaxSafeLag: ctx.Uint64(flags.SequencerMaxSafeLagFlag.Name), } } func NewRollupConfig(ctx *cli.Context) (*rollup.Config, error) { - network := ctx.GlobalString(flags.Network.Name) + network := ctx.String(flags.Network.Name) if network != "" { config, err := chaincfg.GetRollupConfig(network) if err != nil { @@ -164,7 +164,7 @@ func NewRollupConfig(ctx *cli.Context) (*rollup.Config, error) { return &config, nil } - rollupConfigPath := ctx.GlobalString(flags.RollupConfig.Name) + rollupConfigPath := ctx.String(flags.RollupConfig.Name) file, err := os.Open(rollupConfigPath) if err != nil { return nil, fmt.Errorf("failed to read rollup config: %w", err) @@ -179,7 +179,7 @@ func NewRollupConfig(ctx *cli.Context) (*rollup.Config, error) { } func NewSnapshotLogger(ctx *cli.Context) (log.Logger, error) { - snapshotFile := ctx.GlobalString(flags.SnapshotLog.Name) + snapshotFile := ctx.String(flags.SnapshotLog.Name) handler := log.DiscardHandler() if snapshotFile != "" { var err error diff --git a/op-program/host/cmd/main.go b/op-program/host/cmd/main.go index adfbfc2b1be1..6e4efe6c8e52 100644 --- a/op-program/host/cmd/main.go +++ b/op-program/host/cmd/main.go @@ -10,7 +10,7 @@ import ( "github.com/ethereum-optimism/optimism/op-program/host/version" oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum/go-ethereum/log" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) var ( diff --git a/op-program/host/config/config.go b/op-program/host/config/config.go index 00f3f2800b5f..4cb5b37bd0d0 100644 --- a/op-program/host/config/config.go +++ b/op-program/host/config/config.go @@ -13,7 +13,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/params" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) var ( @@ -118,23 +118,23 @@ func NewConfigFromCLI(ctx *cli.Context) (*Config, error) { if err != nil { return nil, err } - l2Head := common.HexToHash(ctx.GlobalString(flags.L2Head.Name)) + l2Head := common.HexToHash(ctx.String(flags.L2Head.Name)) if l2Head == (common.Hash{}) { return nil, ErrInvalidL2Head } - l2Claim := common.HexToHash(ctx.GlobalString(flags.L2Claim.Name)) + l2Claim := common.HexToHash(ctx.String(flags.L2Claim.Name)) if l2Claim == (common.Hash{}) { return nil, ErrInvalidL2Claim } - l2ClaimBlockNum := ctx.GlobalUint64(flags.L2BlockNumber.Name) - l1Head := common.HexToHash(ctx.GlobalString(flags.L1Head.Name)) + l2ClaimBlockNum := ctx.Uint64(flags.L2BlockNumber.Name) + l1Head := common.HexToHash(ctx.String(flags.L1Head.Name)) if l1Head == (common.Hash{}) { return nil, ErrInvalidL1Head } - l2GenesisPath := ctx.GlobalString(flags.L2GenesisPath.Name) + l2GenesisPath := ctx.String(flags.L2GenesisPath.Name) var l2ChainConfig *params.ChainConfig if l2GenesisPath == "" { - networkName := ctx.GlobalString(flags.Network.Name) + networkName := ctx.String(flags.Network.Name) l2ChainConfig = L2ChainConfigsByName[networkName] if l2ChainConfig == nil { return nil, fmt.Errorf("flag %s is required for network %s", flags.L2GenesisPath.Name, networkName) @@ -147,18 +147,18 @@ func NewConfigFromCLI(ctx *cli.Context) (*Config, error) { } return &Config{ Rollup: rollupCfg, - DataDir: ctx.GlobalString(flags.DataDir.Name), - L2URL: ctx.GlobalString(flags.L2NodeAddr.Name), + DataDir: ctx.String(flags.DataDir.Name), + L2URL: ctx.String(flags.L2NodeAddr.Name), L2ChainConfig: l2ChainConfig, L2Head: l2Head, L2Claim: l2Claim, L2ClaimBlockNumber: l2ClaimBlockNum, L1Head: l1Head, - L1URL: ctx.GlobalString(flags.L1NodeAddr.Name), - L1TrustRPC: ctx.GlobalBool(flags.L1TrustRPC.Name), - L1RPCKind: sources.RPCProviderKind(ctx.GlobalString(flags.L1RPCProviderKind.Name)), - ExecCmd: ctx.GlobalString(flags.Exec.Name), - ServerMode: ctx.GlobalBool(flags.Server.Name), + L1URL: ctx.String(flags.L1NodeAddr.Name), + L1TrustRPC: ctx.Bool(flags.L1TrustRPC.Name), + L1RPCKind: sources.RPCProviderKind(ctx.String(flags.L1RPCProviderKind.Name)), + ExecCmd: ctx.String(flags.Exec.Name), + ServerMode: ctx.Bool(flags.Server.Name), }, nil } diff --git a/op-program/host/flags/flags.go b/op-program/host/flags/flags.go index 46c171e2061c..b334d3dd12db 100644 --- a/op-program/host/flags/flags.go +++ b/op-program/host/flags/flags.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-node/sources" @@ -15,81 +15,85 @@ import ( const EnvVarPrefix = "OP_PROGRAM" +func prefixEnvVars(name string) []string { + return service.PrefixEnvVar(EnvVarPrefix, name) +} + var ( - RollupConfig = cli.StringFlag{ - Name: "rollup.config", - Usage: "Rollup chain parameters", - EnvVar: service.PrefixEnvVar(EnvVarPrefix, "ROLLUP_CONFIG"), - } - Network = cli.StringFlag{ - Name: "network", - Usage: fmt.Sprintf("Predefined network selection. Available networks: %s", strings.Join(chaincfg.AvailableNetworks(), ", ")), - EnvVar: service.PrefixEnvVar(EnvVarPrefix, "NETWORK"), - } - DataDir = cli.StringFlag{ - Name: "datadir", - Usage: "Directory to use for preimage data storage. Default uses in-memory storage", - EnvVar: service.PrefixEnvVar(EnvVarPrefix, "DATADIR"), - } - L2NodeAddr = cli.StringFlag{ - Name: "l2", - Usage: "Address of L2 JSON-RPC endpoint to use (eth and debug namespace required)", - EnvVar: service.PrefixEnvVar(EnvVarPrefix, "L2_RPC"), - } - L1Head = cli.StringFlag{ - Name: "l1.head", - Usage: "Hash of the L1 head block. Derivation stops after this block is processed.", - EnvVar: service.PrefixEnvVar(EnvVarPrefix, "L1_HEAD"), - } - L2Head = cli.StringFlag{ - Name: "l2.head", - Usage: "Hash of the agreed L2 block to start derivation from", - EnvVar: service.PrefixEnvVar(EnvVarPrefix, "L2_HEAD"), - } - L2Claim = cli.StringFlag{ - Name: "l2.claim", - Usage: "Claimed L2 output root to validate", - EnvVar: service.PrefixEnvVar(EnvVarPrefix, "L2_CLAIM"), - } - L2BlockNumber = cli.Uint64Flag{ - Name: "l2.blocknumber", - Usage: "Number of the L2 block that the claim is from", - EnvVar: service.PrefixEnvVar(EnvVarPrefix, "L2_BLOCK_NUM"), - } - L2GenesisPath = cli.StringFlag{ - Name: "l2.genesis", - Usage: "Path to the op-geth genesis file", - EnvVar: service.PrefixEnvVar(EnvVarPrefix, "L2_GENESIS"), - } - L1NodeAddr = cli.StringFlag{ - Name: "l1", - Usage: "Address of L1 JSON-RPC endpoint to use (eth namespace required)", - EnvVar: service.PrefixEnvVar(EnvVarPrefix, "L1_RPC"), - } - L1TrustRPC = cli.BoolFlag{ - Name: "l1.trustrpc", - Usage: "Trust the L1 RPC, sync faster at risk of malicious/buggy RPC providing bad or inconsistent L1 data", - EnvVar: service.PrefixEnvVar(EnvVarPrefix, "L1_TRUST_RPC"), - } - L1RPCProviderKind = cli.GenericFlag{ + RollupConfig = &cli.StringFlag{ + Name: "rollup.config", + Usage: "Rollup chain parameters", + EnvVars: prefixEnvVars("ROLLUP_CONFIG"), + } + Network = &cli.StringFlag{ + Name: "network", + Usage: fmt.Sprintf("Predefined network selection. Available networks: %s", strings.Join(chaincfg.AvailableNetworks(), ", ")), + EnvVars: prefixEnvVars("NETWORK"), + } + DataDir = &cli.StringFlag{ + Name: "datadir", + Usage: "Directory to use for preimage data storage. Default uses in-memory storage", + EnvVars: prefixEnvVars("DATADIR"), + } + L2NodeAddr = &cli.StringFlag{ + Name: "l2", + Usage: "Address of L2 JSON-RPC endpoint to use (eth and debug namespace required)", + EnvVars: prefixEnvVars("L2_RPC"), + } + L1Head = &cli.StringFlag{ + Name: "l1.head", + Usage: "Hash of the L1 head block. Derivation stops after this block is processed.", + EnvVars: prefixEnvVars("L1_HEAD"), + } + L2Head = &cli.StringFlag{ + Name: "l2.head", + Usage: "Hash of the agreed L2 block to start derivation from", + EnvVars: prefixEnvVars("L2_HEAD"), + } + L2Claim = &cli.StringFlag{ + Name: "l2.claim", + Usage: "Claimed L2 output root to validate", + EnvVars: prefixEnvVars("L2_CLAIM"), + } + L2BlockNumber = &cli.Uint64Flag{ + Name: "l2.blocknumber", + Usage: "Number of the L2 block that the claim is from", + EnvVars: prefixEnvVars("L2_BLOCK_NUM"), + } + L2GenesisPath = &cli.StringFlag{ + Name: "l2.genesis", + Usage: "Path to the op-geth genesis file", + EnvVars: prefixEnvVars("L2_GENESIS"), + } + L1NodeAddr = &cli.StringFlag{ + Name: "l1", + Usage: "Address of L1 JSON-RPC endpoint to use (eth namespace required)", + EnvVars: prefixEnvVars("L1_RPC"), + } + L1TrustRPC = &cli.BoolFlag{ + Name: "l1.trustrpc", + Usage: "Trust the L1 RPC, sync faster at risk of malicious/buggy RPC providing bad or inconsistent L1 data", + EnvVars: prefixEnvVars("L1_TRUST_RPC"), + } + L1RPCProviderKind = &cli.GenericFlag{ Name: "l1.rpckind", Usage: "The kind of RPC provider, used to inform optimal transactions receipts fetching, and thus reduce costs. Valid options: " + openum.EnumString(sources.RPCProviderKinds), - EnvVar: service.PrefixEnvVar(EnvVarPrefix, "L1_RPC_KIND"), + EnvVars: prefixEnvVars("L1_RPC_KIND"), Value: func() *sources.RPCProviderKind { out := sources.RPCKindBasic return &out }(), } - Exec = cli.StringFlag{ - Name: "exec", - Usage: "Run the specified client program as a separate process detached from the host. Default is to run the client program in the host process.", - EnvVar: service.PrefixEnvVar(EnvVarPrefix, "EXEC"), + Exec = &cli.StringFlag{ + Name: "exec", + Usage: "Run the specified client program as a separate process detached from the host. Default is to run the client program in the host process.", + EnvVars: prefixEnvVars("EXEC"), } - Server = cli.BoolFlag{ - Name: "server", - Usage: "Run in pre-image server mode without executing any client program.", - EnvVar: service.PrefixEnvVar(EnvVarPrefix, "SERVER"), + Server = &cli.BoolFlag{ + Name: "server", + Usage: "Run in pre-image server mode without executing any client program.", + EnvVars: prefixEnvVars("SERVER"), } ) @@ -122,20 +126,20 @@ func init() { } func CheckRequired(ctx *cli.Context) error { - rollupConfig := ctx.GlobalString(RollupConfig.Name) - network := ctx.GlobalString(Network.Name) + rollupConfig := ctx.String(RollupConfig.Name) + network := ctx.String(Network.Name) if rollupConfig == "" && network == "" { return fmt.Errorf("flag %s or %s is required", RollupConfig.Name, Network.Name) } if rollupConfig != "" && network != "" { return fmt.Errorf("cannot specify both %s and %s", RollupConfig.Name, Network.Name) } - if network == "" && ctx.GlobalString(L2GenesisPath.Name) == "" { + if network == "" && ctx.String(L2GenesisPath.Name) == "" { return fmt.Errorf("flag %s is required for custom networks", L2GenesisPath.Name) } for _, flag := range requiredFlags { - if !ctx.IsSet(flag.GetName()) { - return fmt.Errorf("flag %s is required", flag.GetName()) + if !ctx.IsSet(flag.Names()[0]) { + return fmt.Errorf("flag %s is required", flag.Names()[0]) } } return nil diff --git a/op-program/host/flags/flags_test.go b/op-program/host/flags/flags_test.go index f046f4fe1e6d..0fc39cf945ab 100644 --- a/op-program/host/flags/flags_test.go +++ b/op-program/host/flags/flags_test.go @@ -5,14 +5,14 @@ import ( "strings" "testing" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) // TestUniqueFlags asserts that all flag names are unique, to avoid accidental conflicts between the many flags. func TestUniqueFlags(t *testing.T) { seenCLI := make(map[string]struct{}) for _, flag := range Flags { - name := flag.GetName() + name := flag.Names()[0] if _, ok := seenCLI[name]; ok { t.Errorf("duplicate flag %s", name) continue @@ -38,22 +38,22 @@ func TestCorrectEnvVarPrefix(t *testing.T) { for _, flag := range Flags { envVar := envVarForFlag(flag) if envVar == "" { - t.Errorf("Failed to find EnvVar for flag %v", flag.GetName()) + t.Errorf("Failed to find EnvVar for flag %v", flag.Names()[0]) } if !strings.HasPrefix(envVar, "OP_PROGRAM_") { - t.Errorf("Flag %v env var (%v) does not start with OP_PROGRAM_", flag.GetName(), envVar) + t.Errorf("Flag %v env var (%v) does not start with OP_PROGRAM_", flag.Names()[0], envVar) } if strings.Contains(envVar, "__") { - t.Errorf("Flag %v env var (%v) has duplicate underscores", flag.GetName(), envVar) + t.Errorf("Flag %v env var (%v) has duplicate underscores", flag.Names()[0], envVar) } } } func envVarForFlag(flag cli.Flag) string { values := reflect.ValueOf(flag) - envVarValue := values.FieldByName("EnvVar") - if envVarValue == (reflect.Value{}) { + envVarValue := values.Elem().FieldByName("EnvVars") + if envVarValue == (reflect.Value{}) || envVarValue.Len() == 0 { return "" } - return envVarValue.String() + return envVarValue.Index(0).String() } diff --git a/op-program/host/host.go b/op-program/host/host.go index 8610e90e8881..77623407ef51 100644 --- a/op-program/host/host.go +++ b/op-program/host/host.go @@ -6,7 +6,6 @@ import ( "fmt" "io" "io/fs" - "math" "os" "os/exec" @@ -22,13 +21,10 @@ import ( "github.com/ethereum-optimism/optimism/op-program/host/prefetcher" oppio "github.com/ethereum-optimism/optimism/op-program/io" opservice "github.com/ethereum-optimism/optimism/op-service" - opclient "github.com/ethereum-optimism/optimism/op-service/client" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" ) -const maxRPCRetries = math.MaxInt - type L2Source struct { *sources.L2Client *sources.DebugClient @@ -192,41 +188,31 @@ func PreimageServer(ctx context.Context, logger log.Logger, cfg *config.Config, func makePrefetcher(ctx context.Context, logger log.Logger, kv kvstore.KV, cfg *config.Config) (*prefetcher.Prefetcher, error) { logger.Info("Connecting to L1 node", "l1", cfg.L1URL) - l1RPC, err := createRetryingRPC(ctx, logger, cfg.L1URL) + l1RPC, err := client.NewRPC(ctx, logger, cfg.L1URL) if err != nil { return nil, fmt.Errorf("failed to setup L1 RPC: %w", err) } logger.Info("Connecting to L2 node", "l2", cfg.L2URL) - l2RPC, err := createRetryingRPC(ctx, logger, cfg.L2URL) + l2RPC, err := client.NewRPC(ctx, logger, cfg.L2URL) if err != nil { return nil, fmt.Errorf("failed to setup L2 RPC: %w", err) } l1ClCfg := sources.L1ClientDefaultConfig(cfg.Rollup, cfg.L1TrustRPC, cfg.L1RPCKind) + l2ClCfg := sources.L2ClientDefaultConfig(cfg.Rollup, true) l1Cl, err := sources.NewL1Client(l1RPC, logger, nil, l1ClCfg) if err != nil { return nil, fmt.Errorf("failed to create L1 client: %w", err) } - - l2ClCfg := sources.L2ClientDefaultConfig(cfg.Rollup, true) l2Cl, err := sources.NewL2Client(l2RPC, logger, nil, l2ClCfg) if err != nil { return nil, fmt.Errorf("failed to create L2 client: %w", err) } - l2DebugCl := &L2Source{L2Client: l2Cl, DebugClient: sources.NewDebugClient(l2RPC.CallContext)} return prefetcher.NewPrefetcher(logger, l1Cl, l2DebugCl, kv), nil } -func createRetryingRPC(ctx context.Context, logger log.Logger, url string) (client.RPC, error) { - rpc, err := client.NewRPC(ctx, logger, url) - if err != nil { - return nil, err - } - return opclient.NewRetryingClient(logger, rpc, maxRPCRetries), nil -} - func routeHints(logger log.Logger, hHostRW io.ReadWriter, hinter preimage.HintHandler) chan error { chErr := make(chan error) hintReader := preimage.NewHintReader(hHostRW) diff --git a/op-program/host/prefetcher/prefetcher.go b/op-program/host/prefetcher/prefetcher.go index 84ce50141ab4..0f4abc0ff887 100644 --- a/op-program/host/prefetcher/prefetcher.go +++ b/op-program/host/prefetcher/prefetcher.go @@ -42,8 +42,8 @@ type Prefetcher struct { func NewPrefetcher(logger log.Logger, l1Fetcher L1Source, l2Fetcher L2Source, kvStore kvstore.KV) *Prefetcher { return &Prefetcher{ logger: logger, - l1Fetcher: l1Fetcher, - l2Fetcher: l2Fetcher, + l1Fetcher: NewRetryingL1Source(logger, l1Fetcher), + l2Fetcher: NewRetryingL2Source(logger, l2Fetcher), kvStore: kvStore, } } diff --git a/op-program/host/prefetcher/retry.go b/op-program/host/prefetcher/retry.go new file mode 100644 index 000000000000..dad6ebad1e7f --- /dev/null +++ b/op-program/host/prefetcher/retry.go @@ -0,0 +1,136 @@ +package prefetcher + +import ( + "context" + "math" + + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-service/backoff" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" +) + +const maxAttempts = math.MaxInt // Succeed or die trying + +type RetryingL1Source struct { + logger log.Logger + source L1Source + strategy backoff.Strategy +} + +func NewRetryingL1Source(logger log.Logger, source L1Source) *RetryingL1Source { + return &RetryingL1Source{ + logger: logger, + source: source, + strategy: backoff.Exponential(), + } +} + +func (s *RetryingL1Source) InfoByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, error) { + var info eth.BlockInfo + err := backoff.DoCtx(ctx, maxAttempts, s.strategy, func() error { + res, err := s.source.InfoByHash(ctx, blockHash) + if err != nil { + s.logger.Warn("Failed to retrieve info", "hash", blockHash, "err", err) + return err + } + info = res + return nil + }) + return info, err +} + +func (s *RetryingL1Source) InfoAndTxsByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, error) { + var info eth.BlockInfo + var txs types.Transactions + err := backoff.DoCtx(ctx, maxAttempts, s.strategy, func() error { + i, t, err := s.source.InfoAndTxsByHash(ctx, blockHash) + if err != nil { + s.logger.Warn("Failed to retrieve l1 info and txs", "hash", blockHash, "err", err) + return err + } + info = i + txs = t + return nil + }) + return info, txs, err +} + +func (s *RetryingL1Source) FetchReceipts(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Receipts, error) { + var info eth.BlockInfo + var rcpts types.Receipts + err := backoff.DoCtx(ctx, maxAttempts, s.strategy, func() error { + i, r, err := s.source.FetchReceipts(ctx, blockHash) + if err != nil { + s.logger.Warn("Failed to fetch receipts", "hash", blockHash, "err", err) + return err + } + info = i + rcpts = r + return nil + }) + return info, rcpts, err +} + +var _ L1Source = (*RetryingL1Source)(nil) + +type RetryingL2Source struct { + logger log.Logger + source L2Source + strategy backoff.Strategy +} + +func (s *RetryingL2Source) InfoAndTxsByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, error) { + var info eth.BlockInfo + var txs types.Transactions + err := backoff.DoCtx(ctx, maxAttempts, s.strategy, func() error { + i, t, err := s.source.InfoAndTxsByHash(ctx, blockHash) + if err != nil { + s.logger.Warn("Failed to retrieve l2 info and txs", "hash", blockHash, "err", err) + return err + } + info = i + txs = t + return nil + }) + return info, txs, err +} + +func (s *RetryingL2Source) NodeByHash(ctx context.Context, hash common.Hash) ([]byte, error) { + var node []byte + err := backoff.DoCtx(ctx, maxAttempts, s.strategy, func() error { + n, err := s.source.NodeByHash(ctx, hash) + if err != nil { + s.logger.Warn("Failed to retrieve node", "hash", hash, "err", err) + return err + } + node = n + return nil + }) + return node, err +} + +func (s *RetryingL2Source) CodeByHash(ctx context.Context, hash common.Hash) ([]byte, error) { + var code []byte + err := backoff.DoCtx(ctx, maxAttempts, s.strategy, func() error { + c, err := s.source.CodeByHash(ctx, hash) + if err != nil { + s.logger.Warn("Failed to retrieve code", "hash", hash, "err", err) + return err + } + code = c + return nil + }) + return code, err +} + +func NewRetryingL2Source(logger log.Logger, source L2Source) *RetryingL2Source { + return &RetryingL2Source{ + logger: logger, + source: source, + strategy: backoff.Exponential(), + } +} + +var _ L2Source = (*RetryingL2Source)(nil) diff --git a/op-program/host/prefetcher/retry_test.go b/op-program/host/prefetcher/retry_test.go new file mode 100644 index 000000000000..84e211b6a1bd --- /dev/null +++ b/op-program/host/prefetcher/retry_test.go @@ -0,0 +1,232 @@ +package prefetcher + +import ( + "context" + "errors" + "testing" + + "github.com/ethereum-optimism/optimism/op-node/eth" + "github.com/ethereum-optimism/optimism/op-node/testlog" + "github.com/ethereum-optimism/optimism/op-node/testutils" + "github.com/ethereum-optimism/optimism/op-service/backoff" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +func TestRetryingL1Source(t *testing.T) { + ctx := context.Background() + hash := common.Hash{0xab} + info := &testutils.MockBlockInfo{InfoHash: hash} + // The mock really doesn't like returning nil for a eth.BlockInfo so return a value we expect to be ignored instead + wrongInfo := &testutils.MockBlockInfo{InfoHash: common.Hash{0x99}} + txs := types.Transactions{ + &types.Transaction{}, + } + rcpts := types.Receipts{ + &types.Receipt{}, + } + + t.Run("InfoByHash Success", func(t *testing.T) { + source, mock := createL1Source(t) + defer mock.AssertExpectations(t) + mock.ExpectInfoByHash(hash, info, nil) + + result, err := source.InfoByHash(ctx, hash) + require.NoError(t, err) + require.Equal(t, info, result) + }) + + t.Run("InfoByHash Error", func(t *testing.T) { + source, mock := createL1Source(t) + defer mock.AssertExpectations(t) + expectedErr := errors.New("boom") + mock.ExpectInfoByHash(hash, wrongInfo, expectedErr) + mock.ExpectInfoByHash(hash, info, nil) + + result, err := source.InfoByHash(ctx, hash) + require.NoError(t, err) + require.Equal(t, info, result) + }) + + t.Run("InfoAndTxsByHash Success", func(t *testing.T) { + source, mock := createL1Source(t) + defer mock.AssertExpectations(t) + mock.ExpectInfoAndTxsByHash(hash, info, txs, nil) + + actualInfo, actualTxs, err := source.InfoAndTxsByHash(ctx, hash) + require.NoError(t, err) + require.Equal(t, info, actualInfo) + require.Equal(t, txs, actualTxs) + }) + + t.Run("InfoAndTxsByHash Error", func(t *testing.T) { + source, mock := createL1Source(t) + defer mock.AssertExpectations(t) + expectedErr := errors.New("boom") + mock.ExpectInfoAndTxsByHash(hash, wrongInfo, nil, expectedErr) + mock.ExpectInfoAndTxsByHash(hash, info, txs, nil) + + actualInfo, actualTxs, err := source.InfoAndTxsByHash(ctx, hash) + require.NoError(t, err) + require.Equal(t, info, actualInfo) + require.Equal(t, txs, actualTxs) + }) + + t.Run("FetchReceipts Success", func(t *testing.T) { + source, mock := createL1Source(t) + defer mock.AssertExpectations(t) + mock.ExpectFetchReceipts(hash, info, rcpts, nil) + + actualInfo, actualRcpts, err := source.FetchReceipts(ctx, hash) + require.NoError(t, err) + require.Equal(t, info, actualInfo) + require.Equal(t, rcpts, actualRcpts) + }) + + t.Run("FetchReceipts Error", func(t *testing.T) { + source, mock := createL1Source(t) + defer mock.AssertExpectations(t) + expectedErr := errors.New("boom") + mock.ExpectFetchReceipts(hash, wrongInfo, nil, expectedErr) + mock.ExpectFetchReceipts(hash, info, rcpts, nil) + + actualInfo, actualRcpts, err := source.FetchReceipts(ctx, hash) + require.NoError(t, err) + require.Equal(t, info, actualInfo) + require.Equal(t, rcpts, actualRcpts) + }) +} + +func createL1Source(t *testing.T) (*RetryingL1Source, *testutils.MockL1Source) { + logger := testlog.Logger(t, log.LvlDebug) + mock := &testutils.MockL1Source{} + source := NewRetryingL1Source(logger, mock) + // Avoid sleeping in tests by using a fixed backoff strategy with no delay + source.strategy = backoff.Fixed(0) + return source, mock +} + +func TestRetryingL2Source(t *testing.T) { + ctx := context.Background() + hash := common.Hash{0xab} + info := &testutils.MockBlockInfo{InfoHash: hash} + // The mock really doesn't like returning nil for a eth.BlockInfo so return a value we expect to be ignored instead + wrongInfo := &testutils.MockBlockInfo{InfoHash: common.Hash{0x99}} + txs := types.Transactions{ + &types.Transaction{}, + } + data := []byte{1, 2, 3, 4, 5} + + t.Run("InfoAndTxsByHash Success", func(t *testing.T) { + source, mock := createL2Source(t) + defer mock.AssertExpectations(t) + mock.ExpectInfoAndTxsByHash(hash, info, txs, nil) + + actualInfo, actualTxs, err := source.InfoAndTxsByHash(ctx, hash) + require.NoError(t, err) + require.Equal(t, info, actualInfo) + require.Equal(t, txs, actualTxs) + }) + + t.Run("InfoAndTxsByHash Error", func(t *testing.T) { + source, mock := createL2Source(t) + defer mock.AssertExpectations(t) + expectedErr := errors.New("boom") + mock.ExpectInfoAndTxsByHash(hash, wrongInfo, nil, expectedErr) + mock.ExpectInfoAndTxsByHash(hash, info, txs, nil) + + actualInfo, actualTxs, err := source.InfoAndTxsByHash(ctx, hash) + require.NoError(t, err) + require.Equal(t, info, actualInfo) + require.Equal(t, txs, actualTxs) + }) + + t.Run("NodeByHash Success", func(t *testing.T) { + source, mock := createL2Source(t) + defer mock.AssertExpectations(t) + mock.ExpectNodeByHash(hash, data, nil) + + actual, err := source.NodeByHash(ctx, hash) + require.NoError(t, err) + require.Equal(t, data, actual) + }) + + t.Run("NodeByHash Error", func(t *testing.T) { + source, mock := createL2Source(t) + defer mock.AssertExpectations(t) + expectedErr := errors.New("boom") + mock.ExpectNodeByHash(hash, nil, expectedErr) + mock.ExpectNodeByHash(hash, data, nil) + + actual, err := source.NodeByHash(ctx, hash) + require.NoError(t, err) + require.Equal(t, data, actual) + }) + + t.Run("CodeByHash Success", func(t *testing.T) { + source, mock := createL2Source(t) + defer mock.AssertExpectations(t) + mock.ExpectCodeByHash(hash, data, nil) + + actual, err := source.CodeByHash(ctx, hash) + require.NoError(t, err) + require.Equal(t, data, actual) + }) + + t.Run("CodeByHash Error", func(t *testing.T) { + source, mock := createL2Source(t) + defer mock.AssertExpectations(t) + expectedErr := errors.New("boom") + mock.ExpectCodeByHash(hash, nil, expectedErr) + mock.ExpectCodeByHash(hash, data, nil) + + actual, err := source.CodeByHash(ctx, hash) + require.NoError(t, err) + require.Equal(t, data, actual) + }) +} + +func createL2Source(t *testing.T) (*RetryingL2Source, *MockL2Source) { + logger := testlog.Logger(t, log.LvlDebug) + mock := &MockL2Source{} + source := NewRetryingL2Source(logger, mock) + // Avoid sleeping in tests by using a fixed backoff strategy with no delay + source.strategy = backoff.Fixed(0) + return source, mock +} + +type MockL2Source struct { + mock.Mock +} + +func (m *MockL2Source) InfoAndTxsByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, error) { + out := m.Mock.MethodCalled("InfoAndTxsByHash", blockHash) + return out[0].(eth.BlockInfo), out[1].(types.Transactions), *out[2].(*error) +} + +func (m *MockL2Source) NodeByHash(ctx context.Context, hash common.Hash) ([]byte, error) { + out := m.Mock.MethodCalled("NodeByHash", hash) + return out[0].([]byte), *out[1].(*error) +} + +func (m *MockL2Source) CodeByHash(ctx context.Context, hash common.Hash) ([]byte, error) { + out := m.Mock.MethodCalled("CodeByHash", hash) + return out[0].([]byte), *out[1].(*error) +} + +func (m *MockL2Source) ExpectInfoAndTxsByHash(blockHash common.Hash, info eth.BlockInfo, txs types.Transactions, err error) { + m.Mock.On("InfoAndTxsByHash", blockHash).Once().Return(info, txs, &err) +} + +func (m *MockL2Source) ExpectNodeByHash(hash common.Hash, node []byte, err error) { + m.Mock.On("NodeByHash", hash).Once().Return(node, &err) +} + +func (m *MockL2Source) ExpectCodeByHash(hash common.Hash, code []byte, err error) { + m.Mock.On("CodeByHash", hash).Once().Return(code, &err) +} + +var _ L2Source = (*MockL2Source)(nil) diff --git a/op-proposer/cmd/doc/cmd.go b/op-proposer/cmd/doc/cmd.go index 2eb135c7e53a..ccb9a9c35ed3 100644 --- a/op-proposer/cmd/doc/cmd.go +++ b/op-proposer/cmd/doc/cmd.go @@ -8,7 +8,7 @@ import ( "github.com/ethereum-optimism/optimism/op-proposer/metrics" "github.com/olekukonko/tablewriter" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) var Subcommands = cli.Commands{ @@ -16,7 +16,7 @@ var Subcommands = cli.Commands{ Name: "metrics", Usage: "Dumps a list of supported metrics to stdout", Flags: []cli.Flag{ - cli.StringFlag{ + &cli.StringFlag{ Name: "format", Value: "markdown", Usage: "Output format (json|markdown)", diff --git a/op-proposer/cmd/main.go b/op-proposer/cmd/main.go index 03ece09f48b3..298bc24e4de8 100644 --- a/op-proposer/cmd/main.go +++ b/op-proposer/cmd/main.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/op-proposer/cmd/doc" "github.com/ethereum-optimism/optimism/op-proposer/flags" @@ -29,7 +29,7 @@ func main() { app.Usage = "L2Output Submitter" app.Description = "Service for generating and submitting L2 Output checkpoints to the L2OutputOracle contract" app.Action = curryMain(Version) - app.Commands = []cli.Command{ + app.Commands = []*cli.Command{ { Name: "doc", Subcommands: doc.Subcommands, diff --git a/op-proposer/flags/flags.go b/op-proposer/flags/flags.go index 595932e6d2a1..d9acde95dcd4 100644 --- a/op-proposer/flags/flags.go +++ b/op-proposer/flags/flags.go @@ -4,7 +4,7 @@ import ( "fmt" "time" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" opservice "github.com/ethereum-optimism/optimism/op-service" oplog "github.com/ethereum-optimism/optimism/op-service/log" @@ -16,35 +16,39 @@ import ( const EnvVarPrefix = "OP_PROPOSER" +func prefixEnvVars(name string) []string { + return opservice.PrefixEnvVar(EnvVarPrefix, name) +} + var ( // Required Flags - L1EthRpcFlag = cli.StringFlag{ - Name: "l1-eth-rpc", - Usage: "HTTP provider URL for L1", - EnvVar: opservice.PrefixEnvVar(EnvVarPrefix, "L1_ETH_RPC"), + L1EthRpcFlag = &cli.StringFlag{ + Name: "l1-eth-rpc", + Usage: "HTTP provider URL for L1", + EnvVars: prefixEnvVars("L1_ETH_RPC"), } - RollupRpcFlag = cli.StringFlag{ - Name: "rollup-rpc", - Usage: "HTTP provider URL for the rollup node", - EnvVar: opservice.PrefixEnvVar(EnvVarPrefix, "ROLLUP_RPC"), + RollupRpcFlag = &cli.StringFlag{ + Name: "rollup-rpc", + Usage: "HTTP provider URL for the rollup node", + EnvVars: prefixEnvVars("ROLLUP_RPC"), } - L2OOAddressFlag = cli.StringFlag{ - Name: "l2oo-address", - Usage: "Address of the L2OutputOracle contract", - EnvVar: opservice.PrefixEnvVar(EnvVarPrefix, "L2OO_ADDRESS"), + L2OOAddressFlag = &cli.StringFlag{ + Name: "l2oo-address", + Usage: "Address of the L2OutputOracle contract", + EnvVars: prefixEnvVars("L2OO_ADDRESS"), } // Optional flags - PollIntervalFlag = cli.DurationFlag{ - Name: "poll-interval", - Usage: "How frequently to poll L2 for new blocks", - Value: 6 * time.Second, - EnvVar: opservice.PrefixEnvVar(EnvVarPrefix, "POLL_INTERVAL"), + PollIntervalFlag = &cli.DurationFlag{ + Name: "poll-interval", + Usage: "How frequently to poll L2 for new blocks", + Value: 6 * time.Second, + EnvVars: prefixEnvVars("POLL_INTERVAL"), } - AllowNonFinalizedFlag = cli.BoolFlag{ - Name: "allow-non-finalized", - Usage: "Allow the proposer to submit proposals for L2 blocks derived from non-finalized L1 blocks.", - EnvVar: opservice.PrefixEnvVar(EnvVarPrefix, "ALLOW_NON_FINALIZED"), + AllowNonFinalizedFlag = &cli.BoolFlag{ + Name: "allow-non-finalized", + Usage: "Allow the proposer to submit proposals for L2 blocks derived from non-finalized L1 blocks.", + EnvVars: prefixEnvVars("ALLOW_NON_FINALIZED"), } // Legacy Flags L2OutputHDPathFlag = txmgr.L2OutputHDPathFlag @@ -77,8 +81,8 @@ var Flags []cli.Flag func CheckRequired(ctx *cli.Context) error { for _, f := range requiredFlags { - if !ctx.GlobalIsSet(f.GetName()) { - return fmt.Errorf("flag %s is required", f.GetName()) + if !ctx.IsSet(f.Names()[0]) { + return fmt.Errorf("flag %s is required", f.Names()[0]) } } return nil diff --git a/op-proposer/proposer/config.go b/op-proposer/proposer/config.go index 59fb6a5ba79b..76546935d243 100644 --- a/op-proposer/proposer/config.go +++ b/op-proposer/proposer/config.go @@ -5,7 +5,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/op-node/sources" "github.com/ethereum-optimism/optimism/op-proposer/flags" @@ -86,13 +86,13 @@ func (c CLIConfig) Check() error { func NewConfig(ctx *cli.Context) CLIConfig { return CLIConfig{ // Required Flags - L1EthRpc: ctx.GlobalString(flags.L1EthRpcFlag.Name), - RollupRpc: ctx.GlobalString(flags.RollupRpcFlag.Name), - L2OOAddress: ctx.GlobalString(flags.L2OOAddressFlag.Name), - PollInterval: ctx.GlobalDuration(flags.PollIntervalFlag.Name), + L1EthRpc: ctx.String(flags.L1EthRpcFlag.Name), + RollupRpc: ctx.String(flags.RollupRpcFlag.Name), + L2OOAddress: ctx.String(flags.L2OOAddressFlag.Name), + PollInterval: ctx.Duration(flags.PollIntervalFlag.Name), TxMgrConfig: txmgr.ReadCLIConfig(ctx), // Optional Flags - AllowNonFinalized: ctx.GlobalBool(flags.AllowNonFinalizedFlag.Name), + AllowNonFinalized: ctx.Bool(flags.AllowNonFinalizedFlag.Name), RPCConfig: oprpc.ReadCLIConfig(ctx), LogConfig: oplog.ReadCLIConfig(ctx), MetricsConfig: opmetrics.ReadCLIConfig(ctx), diff --git a/op-proposer/proposer/l2_output_submitter.go b/op-proposer/proposer/l2_output_submitter.go index b79b5479b268..344b695dce32 100644 --- a/op-proposer/proposer/l2_output_submitter.go +++ b/op-proposer/proposer/l2_output_submitter.go @@ -14,7 +14,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-node/eth" diff --git a/op-service/client/retry.go b/op-service/client/retry.go deleted file mode 100644 index f80a49b57879..000000000000 --- a/op-service/client/retry.go +++ /dev/null @@ -1,136 +0,0 @@ -package client - -import ( - "context" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rpc" - "github.com/hashicorp/go-multierror" - - "github.com/ethereum-optimism/optimism/op-node/client" - "github.com/ethereum-optimism/optimism/op-service/backoff" -) - -var ( - // ExponentialBackoff is the default backoff strategy. - ExponentialBackoff = backoff.Exponential() -) - -// retryingClient wraps a [client.RPC] with a backoff strategy. -type retryingClient struct { - log log.Logger - c client.RPC - retryAttempts int - strategy backoff.Strategy -} - -// NewRetryingClient creates a new retrying client. -// The backoff strategy is optional, if not provided, the default exponential backoff strategy is used. -func NewRetryingClient(logger log.Logger, c client.RPC, retries int, strategy ...backoff.Strategy) *retryingClient { - if len(strategy) == 0 { - strategy = []backoff.Strategy{ExponentialBackoff} - } - return &retryingClient{ - log: logger, - c: c, - retryAttempts: retries, - strategy: strategy[0], - } -} - -// BackoffStrategy returns the [backoff.Strategy] used by the client. -func (b *retryingClient) BackoffStrategy() backoff.Strategy { - return b.strategy -} - -func (b *retryingClient) Close() { - b.c.Close() -} - -func (b *retryingClient) CallContext(ctx context.Context, result any, method string, args ...any) error { - return backoff.DoCtx(ctx, b.retryAttempts, b.strategy, func() error { - cCtx, cancel := context.WithTimeout(ctx, 10*time.Second) - defer cancel() - err := b.c.CallContext(cCtx, result, method, args...) - if err != nil { - b.log.Warn("RPC request failed", "method", method, "err", err) - } - return err - }) -} - -// pendingReq combines BatchElem information with the index of this request in the original []rpc.BatchElem -type pendingReq struct { - // req is a copy of the BatchElem individual request to make. - // It never has Result or Error set as it gets copied again as part of being passed to the underlying client. - req rpc.BatchElem - - // idx tracks the index of the original BatchElem in the supplied input array - // This can then be used to set the result on the original input - idx int -} - -func (b *retryingClient) BatchCallContext(ctx context.Context, input []rpc.BatchElem) error { - // Add all BatchElem to the initial pending set - // Each time we retry, we'll remove successful BatchElem for this list so we only retry ones that fail. - pending := make([]*pendingReq, len(input)) - for i, req := range input { - pending[i] = &pendingReq{ - req: req, - idx: i, - } - } - return backoff.DoCtx(ctx, b.retryAttempts, b.strategy, func() error { - cCtx, cancel := context.WithTimeout(ctx, 20*time.Second) - defer cancel() - - batch := make([]rpc.BatchElem, len(pending)) - for i, req := range pending { - batch[i] = req.req - } - err := b.c.BatchCallContext(cCtx, batch) - if err != nil { - b.log.Warn("Batch request failed", "err", err) - // Whole call failed, retry all pending elems again - return err - } - var failed []*pendingReq - var combinedErr error - for i, elem := range batch { - req := pending[i] - idx := req.idx // Index into input of the original BatchElem - - // Set the result on the original batch to pass back to the caller in case we stop retrying - input[idx].Error = elem.Error - input[idx].Result = elem.Result - - // If the individual request failed, add it to the list to retry - if elem.Error != nil { - // Need to retry this request - failed = append(failed, req) - combinedErr = multierror.Append(elem.Error, combinedErr) - } - } - if len(failed) > 0 { - pending = failed - b.log.Warn("Batch request returned errors", "err", combinedErr) - return combinedErr - } - return nil - }) -} - -func (b *retryingClient) EthSubscribe(ctx context.Context, channel any, args ...any) (ethereum.Subscription, error) { - var sub ethereum.Subscription - err := backoff.DoCtx(ctx, b.retryAttempts, b.strategy, func() error { - var err error - sub, err = b.c.EthSubscribe(ctx, channel, args...) - if err != nil { - b.log.Warn("Subscription request failed", "err", err) - } - return err - }) - return sub, err -} diff --git a/op-service/client/retry_test.go b/op-service/client/retry_test.go deleted file mode 100644 index 5b9c951487d7..000000000000 --- a/op-service/client/retry_test.go +++ /dev/null @@ -1,196 +0,0 @@ -package client_test - -import ( - "context" - "errors" - "testing" - - "github.com/ethereum-optimism/optimism/op-node/testlog" - "github.com/ethereum/go-ethereum/log" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/rpc" - - "github.com/ethereum-optimism/optimism/op-service/backoff" - "github.com/ethereum-optimism/optimism/op-service/client" - - opclient "github.com/ethereum-optimism/optimism/op-node/client" -) - -type MockRPC struct { - mock.Mock -} - -func (m *MockRPC) Close() { - m.Called() -} - -func (m *MockRPC) CallContext(ctx context.Context, result any, method string, args ...any) error { - out := m.Mock.MethodCalled("CallContext", ctx, result, method, args) - return *out[0].(*error) -} - -func (m *MockRPC) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { - out := m.Mock.MethodCalled("BatchCallContext", ctx, b) - err, ok := out[0].(*error) - if ok { - return *err - } - return nil -} - -func (m *MockRPC) EthSubscribe(ctx context.Context, channel any, args ...any) (ethereum.Subscription, error) { - out := m.Mock.MethodCalled("EthSubscribe", ctx, channel, args) - return *out[0].(*ethereum.Subscription), *out[1].(*error) -} - -func (m *MockRPC) ExpectCallContext(err error, result any, method string, arg string) { - m.On("CallContext", mock.Anything, result, method, []interface{}{arg}).Return(&err) -} - -func (m *MockRPC) ExpectBatchCallContext(err error, b []rpc.BatchElem) { - m.On("BatchCallContext", mock.Anything, b).Return(&err) -} - -func (m *MockRPC) OnBatchCallContext(err error, b []rpc.BatchElem, action func(callBatches []rpc.BatchElem)) { - m.On("BatchCallContext", mock.Anything, b).Return(err).Run(func(args mock.Arguments) { - action(args[1].([]rpc.BatchElem)) - }) -} - -func (m *MockRPC) ExpectEthSubscribe(sub ethereum.Subscription, err error, channel any, args ...any) { - m.On("EthSubscribe", mock.Anything, channel, args).Return(&sub, &err) -} - -var _ opclient.RPC = (*MockRPC)(nil) - -func TestClient_BackoffClient_Strategy(t *testing.T) { - mockRpc := &MockRPC{} - backoffClient := client.NewRetryingClient(testlog.Logger(t, log.LvlInfo), mockRpc, 0) - require.Equal(t, backoffClient.BackoffStrategy(), client.ExponentialBackoff) - - fixedStrategy := &backoff.FixedStrategy{} - backoffClient = client.NewRetryingClient(testlog.Logger(t, log.LvlInfo), mockRpc, 0, fixedStrategy) - require.Equal(t, backoffClient.BackoffStrategy(), fixedStrategy) -} - -func TestClient_BackoffClient_Close(t *testing.T) { - mockRpc := &MockRPC{} - mockRpc.On("Close").Return() - backoffClient := client.NewRetryingClient(testlog.Logger(t, log.LvlInfo), mockRpc, 0) - backoffClient.Close() - require.True(t, mockRpc.AssertCalled(t, "Close")) -} - -func TestClient_BackoffClient_CallContext(t *testing.T) { - mockRpc := &MockRPC{} - mockRpc.ExpectCallContext(nil, nil, "foo", "bar") - backoffClient := client.NewRetryingClient(testlog.Logger(t, log.LvlInfo), mockRpc, 1) - err := backoffClient.CallContext(context.Background(), nil, "foo", "bar") - require.NoError(t, err) - require.True(t, mockRpc.AssertCalled(t, "CallContext", mock.Anything, nil, "foo", []interface{}{"bar"})) -} - -func TestClient_BackoffClient_CallContext_WithRetries(t *testing.T) { - mockRpc := &MockRPC{} - mockRpc.ExpectCallContext(errors.New("foo"), nil, "foo", "bar") - backoffClient := client.NewRetryingClient(testlog.Logger(t, log.LvlInfo), mockRpc, 2, backoff.Fixed(0)) - err := backoffClient.CallContext(context.Background(), nil, "foo", "bar") - require.Error(t, err) - require.True(t, mockRpc.AssertNumberOfCalls(t, "CallContext", 2)) -} - -func TestClient_BackoffClient_BatchCallContext(t *testing.T) { - mockRpc := &MockRPC{} - mockRpc.ExpectBatchCallContext(nil, []rpc.BatchElem{}) - backoffClient := client.NewRetryingClient(testlog.Logger(t, log.LvlInfo), mockRpc, 1) - err := backoffClient.BatchCallContext(context.Background(), nil) - require.NoError(t, err) - require.True(t, mockRpc.AssertCalled(t, "BatchCallContext", mock.Anything, []rpc.BatchElem{})) -} - -func TestClient_BackoffClient_BatchCallContext_WithRetries(t *testing.T) { - mockRpc := &MockRPC{} - mockRpc.ExpectBatchCallContext(errors.New("foo"), []rpc.BatchElem{}) - backoffClient := client.NewRetryingClient(testlog.Logger(t, log.LvlInfo), mockRpc, 2, backoff.Fixed(0)) - err := backoffClient.BatchCallContext(context.Background(), nil) - require.Error(t, err) - require.True(t, mockRpc.AssertNumberOfCalls(t, "BatchCallContext", 2)) -} - -func TestClient_BackoffClient_BatchCallContext_WithPartialRetries(t *testing.T) { - batches := []rpc.BatchElem{ - {Method: "0"}, - {Method: "1"}, - {Method: "2"}, - } - mockRpc := &MockRPC{} - mockRpc.OnBatchCallContext(nil, batches, func(batch []rpc.BatchElem) { - batch[0].Result = batch[0].Method - batch[1].Error = errors.New("boom") - batch[2].Error = errors.New("boom") - }) - mockRpc.OnBatchCallContext(nil, []rpc.BatchElem{batches[1], batches[2]}, func(batch []rpc.BatchElem) { - batch[0].Error = errors.New("boom again") - batch[1].Result = batch[1].Method - }) - backoffClient := client.NewRetryingClient(testlog.Logger(t, log.LvlInfo), mockRpc, 2, backoff.Fixed(0)) - err := backoffClient.BatchCallContext(context.Background(), batches) - require.Error(t, err) - require.True(t, mockRpc.AssertNumberOfCalls(t, "BatchCallContext", 2)) - - // Check our original batches got updated correctly - require.Equal(t, rpc.BatchElem{Method: "0", Result: "0"}, batches[0]) - require.Equal(t, rpc.BatchElem{Method: "1", Result: nil, Error: errors.New("boom again")}, batches[1]) - require.Equal(t, rpc.BatchElem{Method: "2", Result: "2"}, batches[2]) -} - -func TestClient_BackoffClient_BatchCallContext_WithPartialRetriesUntilSuccess(t *testing.T) { - batches := []rpc.BatchElem{ - {Method: "0"}, - {Method: "1"}, - {Method: "2"}, - } - mockRpc := &MockRPC{} - mockRpc.OnBatchCallContext(nil, batches, func(batch []rpc.BatchElem) { - batch[0].Result = batch[0].Method - batch[1].Error = errors.New("boom") - batch[2].Error = errors.New("boom") - }) - mockRpc.OnBatchCallContext(nil, []rpc.BatchElem{batches[1], batches[2]}, func(batch []rpc.BatchElem) { - batch[0].Error = errors.New("boom again") - batch[1].Result = batch[1].Method - }) - mockRpc.OnBatchCallContext(nil, []rpc.BatchElem{batches[1]}, func(batch []rpc.BatchElem) { - batch[0].Result = batch[0].Method - }) - backoffClient := client.NewRetryingClient(testlog.Logger(t, log.LvlInfo), mockRpc, 4, backoff.Fixed(0)) - err := backoffClient.BatchCallContext(context.Background(), batches) - require.NoError(t, err) - require.True(t, mockRpc.AssertNumberOfCalls(t, "BatchCallContext", 3)) - - // Check our original batches got updated correctly - require.Equal(t, rpc.BatchElem{Method: "0", Result: "0"}, batches[0]) - require.Equal(t, rpc.BatchElem{Method: "1", Result: "1"}, batches[1]) - require.Equal(t, rpc.BatchElem{Method: "2", Result: "2"}, batches[2]) -} - -func TestClient_BackoffClient_EthSubscribe(t *testing.T) { - mockRpc := &MockRPC{} - mockRpc.ExpectEthSubscribe(ethereum.Subscription(nil), nil, nil, "foo", "bar") - backoffClient := client.NewRetryingClient(testlog.Logger(t, log.LvlInfo), mockRpc, 1) - _, err := backoffClient.EthSubscribe(context.Background(), nil, "foo", "bar") - require.NoError(t, err) - require.True(t, mockRpc.AssertCalled(t, "EthSubscribe", mock.Anything, nil, []interface{}{"foo", "bar"})) -} - -func TestClient_BackoffClient_EthSubscribe_WithRetries(t *testing.T) { - mockRpc := &MockRPC{} - mockRpc.ExpectEthSubscribe(ethereum.Subscription(nil), errors.New("foo"), nil, "foo", "bar") - backoffClient := client.NewRetryingClient(testlog.Logger(t, log.LvlInfo), mockRpc, 2, backoff.Fixed(0)) - _, err := backoffClient.EthSubscribe(context.Background(), nil, "foo", "bar") - require.Error(t, err) - require.True(t, mockRpc.AssertNumberOfCalls(t, "EthSubscribe", 2)) -} diff --git a/op-service/log/cli.go b/op-service/log/cli.go index b2fca25c8f79..df449599b6f4 100644 --- a/op-service/log/cli.go +++ b/op-service/log/cli.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/ethereum/go-ethereum/log" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "golang.org/x/term" opservice "github.com/ethereum-optimism/optimism/op-service" @@ -20,22 +20,22 @@ const ( func CLIFlags(envPrefix string) []cli.Flag { return []cli.Flag{ - cli.StringFlag{ - Name: LevelFlagName, - Usage: "The lowest log level that will be output", - Value: "info", - EnvVar: opservice.PrefixEnvVar(envPrefix, "LOG_LEVEL"), + &cli.StringFlag{ + Name: LevelFlagName, + Usage: "The lowest log level that will be output", + Value: "info", + EnvVars: opservice.PrefixEnvVar(envPrefix, "LOG_LEVEL"), }, - cli.StringFlag{ - Name: FormatFlagName, - Usage: "Format the log output. Supported formats: 'text', 'terminal', 'logfmt', 'json', 'json-pretty',", - Value: "text", - EnvVar: opservice.PrefixEnvVar(envPrefix, "LOG_FORMAT"), + &cli.StringFlag{ + Name: FormatFlagName, + Usage: "Format the log output. Supported formats: 'text', 'terminal', 'logfmt', 'json', 'json-pretty',", + Value: "text", + EnvVars: opservice.PrefixEnvVar(envPrefix, "LOG_FORMAT"), }, - cli.BoolFlag{ - Name: ColorFlagName, - Usage: "Color the log output if in terminal mode", - EnvVar: opservice.PrefixEnvVar(envPrefix, "LOG_COLOR"), + &cli.BoolFlag{ + Name: ColorFlagName, + Usage: "Color the log output if in terminal mode", + EnvVars: opservice.PrefixEnvVar(envPrefix, "LOG_COLOR"), }, } } @@ -81,7 +81,7 @@ func DefaultCLIConfig() CLIConfig { } } -func ReadLocalCLIConfig(ctx *cli.Context) CLIConfig { +func ReadCLIConfig(ctx *cli.Context) CLIConfig { cfg := DefaultCLIConfig() cfg.Level = ctx.String(LevelFlagName) cfg.Format = ctx.String(FormatFlagName) @@ -91,16 +91,6 @@ func ReadLocalCLIConfig(ctx *cli.Context) CLIConfig { return cfg } -func ReadCLIConfig(ctx *cli.Context) CLIConfig { - cfg := DefaultCLIConfig() - cfg.Level = ctx.GlobalString(LevelFlagName) - cfg.Format = ctx.GlobalString(FormatFlagName) - if ctx.IsSet(ColorFlagName) { - cfg.Color = ctx.GlobalBool(ColorFlagName) - } - return cfg -} - // Format turns a string and color into a structured Format object func Format(lf string, color bool) log.Format { switch lf { diff --git a/op-service/metrics/cli.go b/op-service/metrics/cli.go index f109eaab4954..f9782b68f321 100644 --- a/op-service/metrics/cli.go +++ b/op-service/metrics/cli.go @@ -6,7 +6,7 @@ import ( opservice "github.com/ethereum-optimism/optimism/op-service" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) const ( @@ -17,22 +17,22 @@ const ( func CLIFlags(envPrefix string) []cli.Flag { return []cli.Flag{ - cli.BoolFlag{ - Name: EnabledFlagName, - Usage: "Enable the metrics server", - EnvVar: opservice.PrefixEnvVar(envPrefix, "METRICS_ENABLED"), + &cli.BoolFlag{ + Name: EnabledFlagName, + Usage: "Enable the metrics server", + EnvVars: opservice.PrefixEnvVar(envPrefix, "METRICS_ENABLED"), }, - cli.StringFlag{ - Name: ListenAddrFlagName, - Usage: "Metrics listening address", - Value: "0.0.0.0", - EnvVar: opservice.PrefixEnvVar(envPrefix, "METRICS_ADDR"), + &cli.StringFlag{ + Name: ListenAddrFlagName, + Usage: "Metrics listening address", + Value: "0.0.0.0", + EnvVars: opservice.PrefixEnvVar(envPrefix, "METRICS_ADDR"), }, - cli.IntFlag{ - Name: PortFlagName, - Usage: "Metrics listening port", - Value: 7300, - EnvVar: opservice.PrefixEnvVar(envPrefix, "METRICS_PORT"), + &cli.IntFlag{ + Name: PortFlagName, + Usage: "Metrics listening port", + Value: 7300, + EnvVars: opservice.PrefixEnvVar(envPrefix, "METRICS_PORT"), }, } } @@ -56,14 +56,6 @@ func (m CLIConfig) Check() error { } func ReadCLIConfig(ctx *cli.Context) CLIConfig { - return CLIConfig{ - Enabled: ctx.GlobalBool(EnabledFlagName), - ListenAddr: ctx.GlobalString(ListenAddrFlagName), - ListenPort: ctx.GlobalInt(PortFlagName), - } -} - -func ReadLocalCLIConfig(ctx *cli.Context) CLIConfig { return CLIConfig{ Enabled: ctx.Bool(EnabledFlagName), ListenAddr: ctx.String(ListenAddrFlagName), diff --git a/op-service/pprof/cli.go b/op-service/pprof/cli.go index 680f34c48d1c..f9d9c361f14b 100644 --- a/op-service/pprof/cli.go +++ b/op-service/pprof/cli.go @@ -5,7 +5,7 @@ import ( "math" opservice "github.com/ethereum-optimism/optimism/op-service" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) const ( @@ -16,22 +16,22 @@ const ( func CLIFlags(envPrefix string) []cli.Flag { return []cli.Flag{ - cli.BoolFlag{ - Name: EnabledFlagName, - Usage: "Enable the pprof server", - EnvVar: opservice.PrefixEnvVar(envPrefix, "PPROF_ENABLED"), + &cli.BoolFlag{ + Name: EnabledFlagName, + Usage: "Enable the pprof server", + EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_ENABLED"), }, - cli.StringFlag{ - Name: ListenAddrFlagName, - Usage: "pprof listening address", - Value: "0.0.0.0", - EnvVar: opservice.PrefixEnvVar(envPrefix, "PPROF_ADDR"), + &cli.StringFlag{ + Name: ListenAddrFlagName, + Usage: "pprof listening address", + Value: "0.0.0.0", + EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_ADDR"), }, - cli.IntFlag{ - Name: PortFlagName, - Usage: "pprof listening port", - Value: 6060, - EnvVar: opservice.PrefixEnvVar(envPrefix, "PPROF_PORT"), + &cli.IntFlag{ + Name: PortFlagName, + Usage: "pprof listening port", + Value: 6060, + EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_PORT"), }, } } @@ -56,8 +56,8 @@ func (m CLIConfig) Check() error { func ReadCLIConfig(ctx *cli.Context) CLIConfig { return CLIConfig{ - Enabled: ctx.GlobalBool(EnabledFlagName), - ListenAddr: ctx.GlobalString(ListenAddrFlagName), - ListenPort: ctx.GlobalInt(PortFlagName), + Enabled: ctx.Bool(EnabledFlagName), + ListenAddr: ctx.String(ListenAddrFlagName), + ListenPort: ctx.Int(PortFlagName), } } diff --git a/op-service/rpc/cli.go b/op-service/rpc/cli.go index cceebdf8392e..f1c4db4b063b 100644 --- a/op-service/rpc/cli.go +++ b/op-service/rpc/cli.go @@ -5,7 +5,7 @@ import ( "math" opservice "github.com/ethereum-optimism/optimism/op-service" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) const ( @@ -15,17 +15,17 @@ const ( func CLIFlags(envPrefix string) []cli.Flag { return []cli.Flag{ - cli.StringFlag{ - Name: ListenAddrFlagName, - Usage: "rpc listening address", - Value: "0.0.0.0", - EnvVar: opservice.PrefixEnvVar(envPrefix, "RPC_ADDR"), + &cli.StringFlag{ + Name: ListenAddrFlagName, + Usage: "rpc listening address", + Value: "0.0.0.0", + EnvVars: opservice.PrefixEnvVar(envPrefix, "RPC_ADDR"), }, - cli.IntFlag{ - Name: PortFlagName, - Usage: "rpc listening port", - Value: 8545, - EnvVar: opservice.PrefixEnvVar(envPrefix, "RPC_PORT"), + &cli.IntFlag{ + Name: PortFlagName, + Usage: "rpc listening port", + Value: 8545, + EnvVars: opservice.PrefixEnvVar(envPrefix, "RPC_PORT"), }, } } @@ -45,7 +45,7 @@ func (c CLIConfig) Check() error { func ReadCLIConfig(ctx *cli.Context) CLIConfig { return CLIConfig{ - ListenAddr: ctx.GlobalString(ListenAddrFlagName), - ListenPort: ctx.GlobalInt(PortFlagName), + ListenAddr: ctx.String(ListenAddrFlagName), + ListenPort: ctx.Int(PortFlagName), } } diff --git a/op-service/tls/cli.go b/op-service/tls/cli.go index 6e8581f1bedd..28a772ab49fc 100644 --- a/op-service/tls/cli.go +++ b/op-service/tls/cli.go @@ -6,7 +6,7 @@ import ( "fmt" "strings" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" opservice "github.com/ethereum-optimism/optimism/op-service" ) @@ -29,24 +29,27 @@ func CLIFlagsWithFlagPrefix(envPrefix string, flagPrefix string) []cli.Flag { prefixFunc := func(flagName string) string { return strings.Trim(fmt.Sprintf("%s.%s", flagPrefix, flagName), ".") } + prefixEnvVars := func(name string) []string { + return opservice.PrefixEnvVar(envPrefix, name) + } return []cli.Flag{ - cli.StringFlag{ - Name: prefixFunc(TLSCaCertFlagName), - Usage: "tls ca cert path", - Value: "tls/ca.crt", - EnvVar: opservice.PrefixEnvVar(envPrefix, "TLS_CA"), + &cli.StringFlag{ + Name: prefixFunc(TLSCaCertFlagName), + Usage: "tls ca cert path", + Value: "tls/ca.crt", + EnvVars: prefixEnvVars("TLS_CA"), }, - cli.StringFlag{ - Name: prefixFunc(TLSCertFlagName), - Usage: "tls cert path", - Value: "tls/tls.crt", - EnvVar: opservice.PrefixEnvVar(envPrefix, "TLS_CERT"), + &cli.StringFlag{ + Name: prefixFunc(TLSCertFlagName), + Usage: "tls cert path", + Value: "tls/tls.crt", + EnvVars: prefixEnvVars("TLS_CERT"), }, - cli.StringFlag{ - Name: prefixFunc(TLSKeyFlagName), - Usage: "tls key", - Value: "tls/tls.key", - EnvVar: opservice.PrefixEnvVar(envPrefix, "TLS_KEY"), + &cli.StringFlag{ + Name: prefixFunc(TLSKeyFlagName), + Usage: "tls key", + Value: "tls/tls.key", + EnvVars: prefixEnvVars("TLS_KEY"), }, } } @@ -73,9 +76,9 @@ func (c CLIConfig) TLSEnabled() bool { // This should be used for server TLS configs, or when client and server tls configs are the same func ReadCLIConfig(ctx *cli.Context) CLIConfig { return CLIConfig{ - TLSCaCert: ctx.GlobalString(TLSCaCertFlagName), - TLSCert: ctx.GlobalString(TLSCertFlagName), - TLSKey: ctx.GlobalString(TLSKeyFlagName), + TLSCaCert: ctx.String(TLSCaCertFlagName), + TLSCert: ctx.String(TLSCertFlagName), + TLSKey: ctx.String(TLSKeyFlagName), } } @@ -86,8 +89,8 @@ func ReadCLIConfigWithPrefix(ctx *cli.Context, flagPrefix string) CLIConfig { return strings.Trim(fmt.Sprintf("%s.%s", flagPrefix, flagName), ".") } return CLIConfig{ - TLSCaCert: ctx.GlobalString(prefixFunc(TLSCaCertFlagName)), - TLSCert: ctx.GlobalString(prefixFunc(TLSCertFlagName)), - TLSKey: ctx.GlobalString(prefixFunc(TLSKeyFlagName)), + TLSCaCert: ctx.String(prefixFunc(TLSCaCertFlagName)), + TLSCert: ctx.String(prefixFunc(TLSCertFlagName)), + TLSKey: ctx.String(prefixFunc(TLSKeyFlagName)), } } diff --git a/op-service/txmgr/cli.go b/op-service/txmgr/cli.go index 61173b6fc857..d4ab7b650147 100644 --- a/op-service/txmgr/cli.go +++ b/op-service/txmgr/cli.go @@ -13,7 +13,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) const ( @@ -34,78 +34,81 @@ const ( ) var ( - SequencerHDPathFlag = cli.StringFlag{ + SequencerHDPathFlag = &cli.StringFlag{ Name: "sequencer-hd-path", Usage: "DEPRECATED: The HD path used to derive the sequencer wallet from the " + "mnemonic. The mnemonic flag must also be set.", - EnvVar: "OP_BATCHER_SEQUENCER_HD_PATH", + EnvVars: []string{"OP_BATCHER_SEQUENCER_HD_PATH"}, } - L2OutputHDPathFlag = cli.StringFlag{ + L2OutputHDPathFlag = &cli.StringFlag{ Name: "l2-output-hd-path", Usage: "DEPRECATED:The HD path used to derive the l2output wallet from the " + "mnemonic. The mnemonic flag must also be set.", - EnvVar: "OP_PROPOSER_L2_OUTPUT_HD_PATH", + EnvVars: []string{"OP_PROPOSER_L2_OUTPUT_HD_PATH"}, } ) func CLIFlags(envPrefix string) []cli.Flag { + prefixEnvVars := func(name string) []string { + return opservice.PrefixEnvVar(envPrefix, name) + } return append([]cli.Flag{ - cli.StringFlag{ - Name: MnemonicFlagName, - Usage: "The mnemonic used to derive the wallets for either the service", - EnvVar: opservice.PrefixEnvVar(envPrefix, "MNEMONIC"), + &cli.StringFlag{ + Name: MnemonicFlagName, + Usage: "The mnemonic used to derive the wallets for either the service", + EnvVars: prefixEnvVars("MNEMONIC"), }, - cli.StringFlag{ - Name: HDPathFlagName, - Usage: "The HD path used to derive the sequencer wallet from the mnemonic. The mnemonic flag must also be set.", - EnvVar: opservice.PrefixEnvVar(envPrefix, "HD_PATH"), + &cli.StringFlag{ + Name: HDPathFlagName, + Usage: "The HD path used to derive the sequencer wallet from the mnemonic. The mnemonic flag must also be set.", + EnvVars: prefixEnvVars("HD_PATH"), }, - cli.StringFlag{ - Name: PrivateKeyFlagName, - Usage: "The private key to use with the service. Must not be used with mnemonic.", - EnvVar: opservice.PrefixEnvVar(envPrefix, "PRIVATE_KEY"), + &cli.StringFlag{ + Name: PrivateKeyFlagName, + Usage: "The private key to use with the service. Must not be used with mnemonic.", + EnvVars: prefixEnvVars("PRIVATE_KEY"), }, - cli.Uint64Flag{ - Name: NumConfirmationsFlagName, - Usage: "Number of confirmations which we will wait after sending a transaction", - Value: 10, - EnvVar: opservice.PrefixEnvVar(envPrefix, "NUM_CONFIRMATIONS"), + &cli.Uint64Flag{ + Name: NumConfirmationsFlagName, + Usage: "Number of confirmations which we will wait after sending a transaction", + Value: 10, + EnvVars: prefixEnvVars("NUM_CONFIRMATIONS"), }, - cli.Uint64Flag{ - Name: SafeAbortNonceTooLowCountFlagName, - Usage: "Number of ErrNonceTooLow observations required to give up on a tx at a particular nonce without receiving confirmation", - Value: 3, - EnvVar: opservice.PrefixEnvVar(envPrefix, "SAFE_ABORT_NONCE_TOO_LOW_COUNT"), + &cli.Uint64Flag{ + Name: SafeAbortNonceTooLowCountFlagName, + Usage: "Number of ErrNonceTooLow observations required to give up on a tx at a particular nonce without receiving confirmation", + Value: 3, + EnvVars: prefixEnvVars("SAFE_ABORT_NONCE_TOO_LOW_COUNT"), }, - cli.DurationFlag{ - Name: ResubmissionTimeoutFlagName, - Usage: "Duration we will wait before resubmitting a transaction to L1", - Value: 48 * time.Second, - EnvVar: opservice.PrefixEnvVar(envPrefix, "RESUBMISSION_TIMEOUT"), + &cli.DurationFlag{ + Name: ResubmissionTimeoutFlagName, + Usage: "Duration we will wait before resubmitting a transaction to L1", + Value: 48 * time.Second, + EnvVars: prefixEnvVars("RESUBMISSION_TIMEOUT"), }, - cli.DurationFlag{ - Name: NetworkTimeoutFlagName, - Usage: "Timeout for all network operations", - Value: 2 * time.Second, - EnvVar: opservice.PrefixEnvVar(envPrefix, "NETWORK_TIMEOUT"), + &cli.DurationFlag{ + Name: NetworkTimeoutFlagName, + Usage: "Timeout for all network operations", + Value: 2 * time.Second, + EnvVars: prefixEnvVars("NETWORK_TIMEOUT"), }, - cli.DurationFlag{ - Name: TxSendTimeoutFlagName, - Usage: "Timeout for sending transactions. If 0 it is disabled.", - Value: 0, - EnvVar: opservice.PrefixEnvVar(envPrefix, "TXMGR_TX_SEND_TIMEOUT"), + &cli.DurationFlag{ + Name: TxSendTimeoutFlagName, + Usage: "Timeout for sending transactions. If 0 it is disabled.", + Value: 0, + EnvVars: prefixEnvVars("TXMGR_TX_SEND_TIMEOUT"), }, - cli.DurationFlag{ - Name: TxNotInMempoolTimeoutFlagName, - Usage: "Timeout for aborting a tx send if the tx does not make it to the mempool.", - Value: 2 * time.Minute, - EnvVar: opservice.PrefixEnvVar(envPrefix, "TXMGR_TX_NOT_IN_MEMPOOL_TIMEOUT"), + &cli.DurationFlag{ + Name: TxNotInMempoolTimeoutFlagName, + Usage: "Timeout for aborting a tx send if the tx does not make it to the mempool.", + Value: 2 * time.Minute, + EnvVars: prefixEnvVars("TXMGR_TX_NOT_IN_MEMPOOL_TIMEOUT"), }, - cli.DurationFlag{ - Name: ReceiptQueryIntervalFlagName, - Usage: "Frequency to poll for receipts", - Value: 12 * time.Second, - EnvVar: opservice.PrefixEnvVar(envPrefix, "TXMGR_RECEIPT_QUERY_INTERVAL"), + &cli.DurationFlag{ + Name: ReceiptQueryIntervalFlagName, + Usage: "Frequency to poll for receipts", + Value: 12 * time.Second, + EnvVars: prefixEnvVars("TXMGR_RECEIPT_QUERY_INTERVAL"), }, }, client.CLIFlags(envPrefix)...) } @@ -157,20 +160,20 @@ func (m CLIConfig) Check() error { func ReadCLIConfig(ctx *cli.Context) CLIConfig { return CLIConfig{ - L1RPCURL: ctx.GlobalString(L1RPCFlagName), - Mnemonic: ctx.GlobalString(MnemonicFlagName), - HDPath: ctx.GlobalString(HDPathFlagName), - SequencerHDPath: ctx.GlobalString(SequencerHDPathFlag.Name), - L2OutputHDPath: ctx.GlobalString(L2OutputHDPathFlag.Name), - PrivateKey: ctx.GlobalString(PrivateKeyFlagName), + L1RPCURL: ctx.String(L1RPCFlagName), + Mnemonic: ctx.String(MnemonicFlagName), + HDPath: ctx.String(HDPathFlagName), + SequencerHDPath: ctx.String(SequencerHDPathFlag.Name), + L2OutputHDPath: ctx.String(L2OutputHDPathFlag.Name), + PrivateKey: ctx.String(PrivateKeyFlagName), SignerCLIConfig: client.ReadCLIConfig(ctx), - NumConfirmations: ctx.GlobalUint64(NumConfirmationsFlagName), - SafeAbortNonceTooLowCount: ctx.GlobalUint64(SafeAbortNonceTooLowCountFlagName), - ResubmissionTimeout: ctx.GlobalDuration(ResubmissionTimeoutFlagName), - ReceiptQueryInterval: ctx.GlobalDuration(ReceiptQueryIntervalFlagName), - NetworkTimeout: ctx.GlobalDuration(NetworkTimeoutFlagName), - TxSendTimeout: ctx.GlobalDuration(TxSendTimeoutFlagName), - TxNotInMempoolTimeout: ctx.GlobalDuration(TxNotInMempoolTimeoutFlagName), + NumConfirmations: ctx.Uint64(NumConfirmationsFlagName), + SafeAbortNonceTooLowCount: ctx.Uint64(SafeAbortNonceTooLowCountFlagName), + ResubmissionTimeout: ctx.Duration(ResubmissionTimeoutFlagName), + ReceiptQueryInterval: ctx.Duration(ReceiptQueryIntervalFlagName), + NetworkTimeout: ctx.Duration(NetworkTimeoutFlagName), + TxSendTimeout: ctx.Duration(TxSendTimeoutFlagName), + TxNotInMempoolTimeout: ctx.Duration(TxNotInMempoolTimeoutFlagName), } } diff --git a/op-service/txmgr/price_bump_test.go b/op-service/txmgr/price_bump_test.go index 702b02032f70..577e36d0965c 100644 --- a/op-service/txmgr/price_bump_test.go +++ b/op-service/txmgr/price_bump_test.go @@ -30,51 +30,52 @@ func (tc *priceBumpTest) run(t *testing.T) { } func TestUpdateFees(t *testing.T) { + require.Equal(t, int64(10), priceBump, "test must be updated if priceBump is adjusted") tests := []priceBumpTest{ { prevGasTip: 100, prevBasefee: 1000, newGasTip: 90, newBasefee: 900, - expectedTip: 100, expectedFC: 2100, + expectedTip: 110, expectedFC: 2310, }, { prevGasTip: 100, prevBasefee: 1000, newGasTip: 101, newBasefee: 1000, - expectedTip: 115, expectedFC: 2415, + expectedTip: 110, expectedFC: 2310, }, { prevGasTip: 100, prevBasefee: 1000, newGasTip: 100, newBasefee: 1001, - expectedTip: 115, expectedFC: 2415, + expectedTip: 110, expectedFC: 2310, }, { prevGasTip: 100, prevBasefee: 1000, newGasTip: 101, newBasefee: 900, - expectedTip: 115, expectedFC: 2415, + expectedTip: 110, expectedFC: 2310, }, { prevGasTip: 100, prevBasefee: 1000, newGasTip: 90, newBasefee: 1010, - expectedTip: 115, expectedFC: 2415, + expectedTip: 110, expectedFC: 2310, }, { prevGasTip: 100, prevBasefee: 1000, newGasTip: 101, newBasefee: 2000, - expectedTip: 115, expectedFC: 4115, + expectedTip: 110, expectedFC: 4110, }, { prevGasTip: 100, prevBasefee: 1000, newGasTip: 120, newBasefee: 900, - expectedTip: 120, expectedFC: 2415, + expectedTip: 120, expectedFC: 2310, }, { prevGasTip: 100, prevBasefee: 1000, newGasTip: 120, newBasefee: 1100, - expectedTip: 120, expectedFC: 2415, + expectedTip: 120, expectedFC: 2320, }, { prevGasTip: 100, prevBasefee: 1000, newGasTip: 120, newBasefee: 1140, - expectedTip: 120, expectedFC: 2415, + expectedTip: 120, expectedFC: 2400, }, { prevGasTip: 100, prevBasefee: 1000, diff --git a/op-service/txmgr/txmgr.go b/op-service/txmgr/txmgr.go index cc18d7fad28c..cb5e058cd5d2 100644 --- a/op-service/txmgr/txmgr.go +++ b/op-service/txmgr/txmgr.go @@ -20,9 +20,13 @@ import ( "github.com/ethereum-optimism/optimism/op-service/txmgr/metrics" ) -// Geth defaults the priceBump to 10 -// Set it to 15% to be more aggressive about including transactions -const priceBump int64 = 15 +const ( + // Geth requires a minimum fee bump of 10% for tx resubmission + priceBump int64 = 10 + + // The multiplier applied to fee suggestions to put a hard limit on fee increases + feeLimitMultiplier = 5 +) // new = old * (100 + priceBump) / 100 var priceBumpPercent = big.NewInt(100 + priceBump) @@ -280,7 +284,15 @@ func (m *SimpleTxManager) sendTx(ctx context.Context, tx *types.Transaction) (*t return nil, errors.New("aborted transaction sending") } // Increase the gas price & submit the new transaction - tx = m.increaseGasPrice(ctx, tx) + newTx, err := m.increaseGasPrice(ctx, tx) + if err != nil || sendState.IsWaitingForConfirmation() { + // there is a chance the previous tx goes into "waiting for confirmation" state + // during the increaseGasPrice call. In some (but not all) cases increaseGasPrice + // will error out during gas estimation. In either case we should continue waiting + // rather than resubmit the tx. + continue + } + tx = newTx wg.Add(1) bumpCounter += 1 go sendTxAsync(tx) @@ -418,46 +430,67 @@ func (m *SimpleTxManager) queryReceipt(ctx context.Context, txHash common.Hash, return nil } -// increaseGasPrice takes the previous transaction & potentially clones then signs it with a higher tip. -// If the tip + basefee suggested by the network are not greater than the previous values, the same transaction -// will be returned. If they are greater, this function will ensure that they are at least greater by 15% than -// the previous transaction's value to ensure that the price bump is large enough. -// -// We do not re-estimate the amount of gas used because for some stateful transactions (like output proposals) the -// act of including the transaction renders the repeat of the transaction invalid. -// -// If it encounters an error with creating the new transaction, it will return the old transaction. -func (m *SimpleTxManager) increaseGasPrice(ctx context.Context, tx *types.Transaction) *types.Transaction { +// increaseGasPrice takes the previous transaction, clones it, and returns it with fee values that +// are at least `priceBump` percent higher than the previous ones to satisfy Geth's replacement +// rules, and no lower than the values returned by the fee suggestion algorithm to ensure it +// doesn't linger in the mempool. Finally to avoid runaway price increases, fees are capped at a +// `feeLimitMultiplier` multiple of the suggested values. +func (m *SimpleTxManager) increaseGasPrice(ctx context.Context, tx *types.Transaction) (*types.Transaction, error) { + m.l.Info("bumping gas price for tx", "hash", tx.Hash(), "tip", tx.GasTipCap(), "fee", tx.GasFeeCap(), "gaslimit", tx.Gas()) tip, basefee, err := m.suggestGasPriceCaps(ctx) if err != nil { m.l.Warn("failed to get suggested gas tip and basefee", "err", err) - return tx + return nil, err } - gasTipCap, gasFeeCap := updateFees(tx.GasTipCap(), tx.GasFeeCap(), tip, basefee, m.l) + bumpedTip, bumpedFee := updateFees(tx.GasTipCap(), tx.GasFeeCap(), tip, basefee, m.l) - if tx.GasTipCapIntCmp(gasTipCap) == 0 && tx.GasFeeCapIntCmp(gasFeeCap) == 0 { - return tx + // Make sure increase is at most 5x the suggested values + maxTip := new(big.Int).Mul(tip, big.NewInt(feeLimitMultiplier)) + if bumpedTip.Cmp(maxTip) > 0 { + m.l.Warn(fmt.Sprintf("bumped tip getting capped at %dx multiple of the suggested value", feeLimitMultiplier), "bumped", bumpedTip, "suggestion", tip) + bumpedTip.Set(maxTip) + } + maxFee := calcGasFeeCap(new(big.Int).Mul(basefee, big.NewInt(feeLimitMultiplier)), maxTip) + if bumpedFee.Cmp(maxFee) > 0 { + m.l.Warn("bumped fee getting capped at multiple of the implied suggested value", "bumped", bumpedFee, "suggestion", maxFee) + bumpedFee.Set(maxFee) } - rawTx := &types.DynamicFeeTx{ ChainID: tx.ChainId(), Nonce: tx.Nonce(), - GasTipCap: gasTipCap, - GasFeeCap: gasFeeCap, - Gas: tx.Gas(), + GasTipCap: bumpedTip, + GasFeeCap: bumpedFee, To: tx.To(), Value: tx.Value(), Data: tx.Data(), AccessList: tx.AccessList(), } + + // Re-estimate gaslimit in case things have changed or a previous gaslimit estimate was wrong + gas, err := m.backend.EstimateGas(ctx, ethereum.CallMsg{ + From: m.cfg.From, + To: rawTx.To, + GasFeeCap: bumpedTip, + GasTipCap: bumpedFee, + Data: rawTx.Data, + }) + if err != nil { + m.l.Warn("failed to re-estimate gas", "err", err, "gaslimit", tx.Gas()) + return nil, err + } + if tx.Gas() != gas { + m.l.Info("re-estimated gas differs", "oldgas", tx.Gas(), "newgas", gas) + } + rawTx.Gas = gas + ctx, cancel := context.WithTimeout(ctx, m.cfg.NetworkTimeout) defer cancel() newTx, err := m.cfg.Signer(ctx, m.cfg.From, types.NewTx(rawTx)) if err != nil { m.l.Warn("failed to sign new transaction", "err", err) - return tx + return tx, nil } - return newTx + return newTx, nil } // suggestGasPriceCaps suggests what the new tip & new basefee should be based on the current L1 conditions @@ -490,18 +523,15 @@ func calcThresholdValue(x *big.Int) *big.Int { return threshold } -// updateFees takes the old tip/basefee & the new tip/basefee and then suggests -// a gasTipCap and gasFeeCap that satisfies geth's required fee bumps -// Geth: FC and Tip must be bumped if any increase +// updateFees takes an old transaction's tip & fee cap plus a new tip & basefee, and returns +// a suggested tip and fee cap such that: +// +// (a) each satisfies geth's required tx-replacement fee bumps (we use a 10% increase), and +// (b) gasTipCap is no less than new tip, and +// (c) gasFeeCap is no less than calcGasFee(newBaseFee, newTip) func updateFees(oldTip, oldFeeCap, newTip, newBaseFee *big.Int, lgr log.Logger) (*big.Int, *big.Int) { newFeeCap := calcGasFeeCap(newBaseFee, newTip) lgr = lgr.New("old_tip", oldTip, "old_feecap", oldFeeCap, "new_tip", newTip, "new_feecap", newFeeCap) - // If the new prices are less than the old price, reuse the old prices - if oldTip.Cmp(newTip) >= 0 && oldFeeCap.Cmp(newFeeCap) >= 0 { - lgr.Debug("Reusing old tip and feecap") - return oldTip, oldFeeCap - } - // Determine if we need to increase the suggested values thresholdTip := calcThresholdValue(oldTip) thresholdFeeCap := calcThresholdValue(oldFeeCap) if newTip.Cmp(thresholdTip) >= 0 && newFeeCap.Cmp(thresholdFeeCap) >= 0 { diff --git a/op-service/txmgr/txmgr_test.go b/op-service/txmgr/txmgr_test.go index 5018868fbdd9..fe2fc1e31c9a 100644 --- a/op-service/txmgr/txmgr_test.go +++ b/op-service/txmgr/txmgr_test.go @@ -734,12 +734,14 @@ func doGasPriceIncrease(t *testing.T, txTipCap, txFeeCap, newTip, newBaseFee int GasTipCap: big.NewInt(txTipCap), GasFeeCap: big.NewInt(txFeeCap), }) - newTx := mgr.increaseGasPrice(context.Background(), tx) + newTx, err := mgr.increaseGasPrice(context.Background(), tx) + require.NoError(t, err) return tx, newTx } func TestIncreaseGasPrice(t *testing.T) { // t.Parallel() + require.Equal(t, int64(10), priceBump, "test must be updated if priceBump is adjusted") tests := []struct { name string run func(t *testing.T) @@ -781,22 +783,16 @@ func TestIncreaseGasPrice(t *testing.T) { run: func(t *testing.T) { _, newTx := doGasPriceIncrease(t, 100, 2200, 120, 1050) require.True(t, newTx.GasTipCap().Cmp(big.NewInt(120)) == 0, "new tx tip must be equal L1") - require.True(t, newTx.GasFeeCap().Cmp(big.NewInt(2530)) == 0, "new tx fee cap must be equal to the threshold value") + require.True(t, newTx.GasFeeCap().Cmp(big.NewInt(2420)) == 0, "new tx fee cap must be equal to the threshold value") }, }, { name: "uses L1 FC when larger and threshold tip", run: func(t *testing.T) { _, newTx := doGasPriceIncrease(t, 100, 2200, 100, 2000) - require.True(t, newTx.GasTipCap().Cmp(big.NewInt(115)) == 0, "new tx tip must be equal the threshold value") - require.True(t, newTx.GasFeeCap().Cmp(big.NewInt(4115)) == 0, "new tx fee cap must be equal L1") - }, - }, - { - name: "reuses tx when no bump", - run: func(t *testing.T) { - tx, newTx := doGasPriceIncrease(t, 10, 100, 10, 45) - require.Equal(t, tx.Hash(), newTx.Hash(), "tx hash must be the same") + require.True(t, newTx.GasTipCap().Cmp(big.NewInt(110)) == 0, "new tx tip must be equal the threshold value") + t.Log("Vals:", newTx.GasFeeCap()) + require.True(t, newTx.GasFeeCap().Cmp(big.NewInt(4110)) == 0, "new tx fee cap must be equal L1") }, }, } @@ -811,11 +807,12 @@ func TestIncreaseGasPrice(t *testing.T) { func TestIncreaseGasPriceNotExponential(t *testing.T) { t.Parallel() + borkedTip := int64(10) + borkedFee := int64(45) borkedBackend := failingBackend{ - gasTip: big.NewInt(10), - baseFee: big.NewInt(45), + gasTip: big.NewInt(borkedTip), + baseFee: big.NewInt(borkedFee), } - feeCap := calcGasFeeCap(borkedBackend.baseFee, borkedBackend.gasTip) mgr := &SimpleTxManager{ cfg: Config{ @@ -839,14 +836,23 @@ func TestIncreaseGasPriceNotExponential(t *testing.T) { }) // Run IncreaseGasPrice a bunch of times in a row to simulate a very fast resubmit loop. - for i := 0; i < 20; i++ { + var err error + for i := 0; i < 30; i++ { ctx := context.Background() - newTx := mgr.increaseGasPrice(ctx, tx) - require.True(t, newTx.GasFeeCap().Cmp(feeCap) == 0, "new tx fee cap must be equal L1") - require.True(t, newTx.GasTipCap().Cmp(borkedBackend.gasTip) == 0, "new tx tip must be equal L1") - tx = newTx + tx, err = mgr.increaseGasPrice(ctx, tx) + require.NoError(t, err) + } + lastTip, lastFee := tx.GasTipCap(), tx.GasFeeCap() + require.Equal(t, lastTip.Int64(), feeLimitMultiplier*borkedTip) + require.Equal(t, lastFee.Int64(), feeLimitMultiplier*(borkedTip+2*borkedFee)) + // Confirm that fees stop rising + for i := 0; i < 5; i++ { + ctx := context.Background() + tx, err := mgr.increaseGasPrice(ctx, tx) + require.NoError(t, err) + require.True(t, tx.GasTipCap().Cmp(lastTip) == 0, "suggested tx tip must stop increasing") + require.True(t, tx.GasFeeCap().Cmp(lastFee) == 0, "suggested tx fee must stop increasing") } - } func TestErrStringMatch(t *testing.T) { diff --git a/op-service/util.go b/op-service/util.go index 4ba0d521d13f..81ffd1d9bc40 100644 --- a/op-service/util.go +++ b/op-service/util.go @@ -13,11 +13,13 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) -func PrefixEnvVar(prefix, suffix string) string { - return prefix + "_" + suffix +// PrefixEnvVar adds a prefix to the environment variable, +// and returns the env-var wrapped in a slice for usage with urfave CLI v2. +func PrefixEnvVar(prefix, suffix string) []string { + return []string{prefix + "_" + suffix} } // ValidateEnvVars logs all env vars that are found where the env var is @@ -33,8 +35,9 @@ func ValidateEnvVars(prefix string, flags []cli.Flag, log log.Logger) { func cliFlagsToEnvVars(flags []cli.Flag) map[string]struct{} { definedEnvVars := make(map[string]struct{}) for _, flag := range flags { - envVarField := reflect.ValueOf(flag).FieldByName("EnvVar") - if envVarField.IsValid() { + envVars := reflect.ValueOf(flag).Elem().FieldByName("EnvVars") + for i := 0; i < envVars.Len(); i++ { + envVarField := envVars.Index(i) definedEnvVars[envVarField.String()] = struct{}{} } } diff --git a/op-service/util_test.go b/op-service/util_test.go index b7350039c112..12d28f3b3414 100644 --- a/op-service/util_test.go +++ b/op-service/util_test.go @@ -4,16 +4,16 @@ import ( "testing" "github.com/stretchr/testify/require" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) func TestCLIFlagsToEnvVars(t *testing.T) { flags := []cli.Flag{ - cli.StringFlag{ - Name: "test", - EnvVar: "OP_NODE_TEST_VAR", + &cli.StringFlag{ + Name: "test", + EnvVars: []string{"OP_NODE_TEST_VAR"}, }, - cli.IntFlag{ + &cli.IntFlag{ Name: "no env var", }, } diff --git a/op-signer/client/config.go b/op-signer/client/config.go index da542949b14a..8332af8a550e 100644 --- a/op-signer/client/config.go +++ b/op-signer/client/config.go @@ -3,7 +3,7 @@ package client import ( "errors" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" opservice "github.com/ethereum-optimism/optimism/op-service" optls "github.com/ethereum-optimism/optimism/op-service/tls" @@ -17,15 +17,15 @@ const ( func CLIFlags(envPrefix string) []cli.Flag { envPrefix += "_SIGNER" flags := []cli.Flag{ - cli.StringFlag{ - Name: EndpointFlagName, - Usage: "Signer endpoint the client will connect to", - EnvVar: opservice.PrefixEnvVar(envPrefix, "ENDPOINT"), + &cli.StringFlag{ + Name: EndpointFlagName, + Usage: "Signer endpoint the client will connect to", + EnvVars: opservice.PrefixEnvVar(envPrefix, "ENDPOINT"), }, - cli.StringFlag{ - Name: AddressFlagName, - Usage: "Address the signer is signing transactions for", - EnvVar: opservice.PrefixEnvVar(envPrefix, "ADDRESS"), + &cli.StringFlag{ + Name: AddressFlagName, + Usage: "Address the signer is signing transactions for", + EnvVars: opservice.PrefixEnvVar(envPrefix, "ADDRESS"), }, } flags = append(flags, optls.CLIFlagsWithFlagPrefix(envPrefix, "signer")...) diff --git a/op-wheel/cmd/main.go b/op-wheel/cmd/main.go index ce0752777f4d..094f59a10d88 100644 --- a/op-wheel/cmd/main.go +++ b/op-wheel/cmd/main.go @@ -5,7 +5,7 @@ import ( "fmt" "os" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum/go-ethereum/log" @@ -29,7 +29,7 @@ func main() { app.Before = func(c *cli.Context) error { log.Root().SetHandler( log.LvlFilterHandler( - oplog.Level(c.GlobalString(wheel.GlobalGethLogLvlFlag.Name)), + oplog.Level(c.String(wheel.GlobalGethLogLvlFlag.Name)), log.StreamHandler(os.Stdout, log.TerminalFormat(true)), ), ) @@ -40,7 +40,7 @@ func main() { }) app.Writer = os.Stdout app.ErrWriter = os.Stderr - app.Commands = []cli.Command{ + app.Commands = []*cli.Command{ wheel.CheatCmd, wheel.EngineCmd, } diff --git a/op-wheel/commands.go b/op-wheel/commands.go index e14ffec7a433..bf2ee9713e74 100644 --- a/op-wheel/commands.go +++ b/op-wheel/commands.go @@ -16,7 +16,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/rpc" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/op-node/client" opservice "github.com/ethereum-optimism/optimism/op-service" @@ -28,61 +28,65 @@ import ( const envVarPrefix = "OP_WHEEL" +func prefixEnvVars(name string) []string { + return []string{envVarPrefix + "_" + name} +} + var ( - GlobalGethLogLvlFlag = cli.StringFlag{ - Name: "geth-log-level", - Usage: "Set the global geth logging level", - EnvVar: opservice.PrefixEnvVar("OP_WHEEL", "GETH_LOG_LEVEL"), - Value: "error", + GlobalGethLogLvlFlag = &cli.StringFlag{ + Name: "geth-log-level", + Usage: "Set the global geth logging level", + EnvVars: prefixEnvVars("GETH_LOG_LEVEL"), + Value: "error", } - DataDirFlag = cli.StringFlag{ + DataDirFlag = &cli.StringFlag{ Name: "data-dir", Usage: "Geth data dir location.", Required: true, TakesFile: true, - EnvVar: opservice.PrefixEnvVar(envVarPrefix, "DATA_DIR"), + EnvVars: prefixEnvVars("DATA_DIR"), } - EngineEndpoint = cli.StringFlag{ + EngineEndpoint = &cli.StringFlag{ Name: "engine", Usage: "Engine API RPC endpoint, can be HTTP/WS/IPC", Required: true, - EnvVar: opservice.PrefixEnvVar(envVarPrefix, "ENGINE"), + EnvVars: prefixEnvVars("ENGINE"), } - EngineJWTPath = cli.StringFlag{ + EngineJWTPath = &cli.StringFlag{ Name: "engine.jwt-secret", Usage: "Path to JWT secret file used to authenticate Engine API communication with.", Required: true, TakesFile: true, - EnvVar: opservice.PrefixEnvVar(envVarPrefix, "ENGINE_JWT_SECRET"), - } - FeeRecipientFlag = cli.GenericFlag{ - Name: "fee-recipient", - Usage: "fee-recipient of the block building", - EnvVar: opservice.PrefixEnvVar(envVarPrefix, "FEE_RECIPIENT"), - Value: &TextFlag[*common.Address]{Value: &common.Address{1: 0x13, 2: 0x37}}, - } - RandaoFlag = cli.GenericFlag{ - Name: "randao", - Usage: "randao value of the block building", - EnvVar: opservice.PrefixEnvVar(envVarPrefix, "RANDAO"), - Value: &TextFlag[*common.Hash]{Value: &common.Hash{1: 0x13, 2: 0x37}}, - } - BlockTimeFlag = cli.Uint64Flag{ - Name: "block-time", - Usage: "block time, interval of timestamps between blocks to build, in seconds", - EnvVar: opservice.PrefixEnvVar(envVarPrefix, "BLOCK_TIME"), - Value: 12, - } - BuildingTime = cli.DurationFlag{ - Name: "building-time", - Usage: "duration of of block building, this should be set to something lower than the block time.", - EnvVar: opservice.PrefixEnvVar(envVarPrefix, "BUILDING_TIME"), - Value: time.Second * 6, - } - AllowGaps = cli.BoolFlag{ - Name: "allow-gaps", - Usage: "allow gaps in block building, like missed slots on the beacon chain.", - EnvVar: opservice.PrefixEnvVar(envVarPrefix, "ALLOW_GAPS"), + EnvVars: prefixEnvVars("ENGINE_JWT_SECRET"), + } + FeeRecipientFlag = &cli.GenericFlag{ + Name: "fee-recipient", + Usage: "fee-recipient of the block building", + EnvVars: prefixEnvVars("FEE_RECIPIENT"), + Value: &TextFlag[*common.Address]{Value: &common.Address{1: 0x13, 2: 0x37}}, + } + RandaoFlag = &cli.GenericFlag{ + Name: "randao", + Usage: "randao value of the block building", + EnvVars: prefixEnvVars("RANDAO"), + Value: &TextFlag[*common.Hash]{Value: &common.Hash{1: 0x13, 2: 0x37}}, + } + BlockTimeFlag = &cli.Uint64Flag{ + Name: "block-time", + Usage: "block time, interval of timestamps between blocks to build, in seconds", + EnvVars: prefixEnvVars("BLOCK_TIME"), + Value: 12, + } + BuildingTime = &cli.DurationFlag{ + Name: "building-time", + Usage: "duration of of block building, this should be set to something lower than the block time.", + EnvVars: prefixEnvVars("BUILDING_TIME"), + Value: time.Second * 6, + } + AllowGaps = &cli.BoolFlag{ + Name: "allow-gaps", + Usage: "allow gaps in block building, like missed slots on the beacon chain.", + EnvVars: prefixEnvVars("ALLOW_GAPS"), } ) @@ -166,29 +170,29 @@ func (a *TextFlag[T]) Get() T { var _ cli.Generic = (*TextFlag[*common.Address])(nil) -func textFlag[T Text](name string, usage string, value T) cli.GenericFlag { - return cli.GenericFlag{ +func textFlag[T Text](name string, usage string, value T) *cli.GenericFlag { + return &cli.GenericFlag{ Name: name, Usage: usage, - EnvVar: opservice.PrefixEnvVar(envVarPrefix, strings.ToUpper(name)), + EnvVars: prefixEnvVars(strings.ToUpper(name)), Required: true, Value: &TextFlag[T]{Value: value}, } } -func addrFlag(name string, usage string) cli.GenericFlag { +func addrFlag(name string, usage string) *cli.GenericFlag { return textFlag[*common.Address](name, usage, new(common.Address)) } -func bytesFlag(name string, usage string) cli.GenericFlag { +func bytesFlag(name string, usage string) *cli.GenericFlag { return textFlag[*hexutil.Bytes](name, usage, new(hexutil.Bytes)) } -func hashFlag(name string, usage string) cli.GenericFlag { +func hashFlag(name string, usage string) *cli.GenericFlag { return textFlag[*common.Hash](name, usage, new(common.Hash)) } -func bigFlag(name string, usage string) cli.GenericFlag { +func bigFlag(name string, usage string) *cli.GenericFlag { return textFlag[*big.Int](name, usage, new(big.Int)) } @@ -209,7 +213,7 @@ func bigFlagValue(name string, ctx *cli.Context) *big.Int { } var ( - CheatStorageGetCmd = cli.Command{ + CheatStorageGetCmd = &cli.Command{ Name: "get", Aliases: []string{"read"}, Flags: []cli.Flag{ @@ -221,7 +225,7 @@ var ( return ch.RunAndClose(cheat.StorageGet(addrFlagValue("address", ctx), hashFlagValue("key", ctx), ctx.App.Writer)) }), } - CheatStorageSetCmd = cli.Command{ + CheatStorageSetCmd = &cli.Command{ Name: "set", Aliases: []string{"write"}, Flags: []cli.Flag{ @@ -234,7 +238,7 @@ var ( return ch.RunAndClose(cheat.StorageSet(addrFlagValue("address", ctx), hashFlagValue("key", ctx), hashFlagValue("value", ctx))) }), } - CheatStorageReadAll = cli.Command{ + CheatStorageReadAll = &cli.Command{ Name: "read-all", Aliases: []string{"get-all"}, Usage: "Read all storage of the given account", @@ -243,7 +247,7 @@ var ( return ch.RunAndClose(cheat.StorageReadAll(addrFlagValue("address", ctx), ctx.App.Writer)) }), } - CheatStorageDiffCmd = cli.Command{ + CheatStorageDiffCmd = &cli.Command{ Name: "diff", Usage: "Diff the storage of accounts A and B", Flags: []cli.Flag{DataDirFlag, hashFlag("a", "address of account A"), hashFlag("b", "address of account B")}, @@ -251,7 +255,7 @@ var ( return ch.RunAndClose(cheat.StorageDiff(ctx.App.Writer, addrFlagValue("a", ctx), addrFlagValue("b", ctx))) }), } - CheatStoragePatchCmd = cli.Command{ + CheatStoragePatchCmd = &cli.Command{ Name: "patch", Usage: "Apply storage patch from STDIN to the given account address", Flags: []cli.Flag{DataDirFlag, addrFlag("address", "Address to patch storage of")}, @@ -259,9 +263,9 @@ var ( return ch.RunAndClose(cheat.StoragePatch(os.Stdin, addrFlagValue("address", ctx))) }), } - CheatStorageCmd = cli.Command{ + CheatStorageCmd = &cli.Command{ Name: "storage", - Subcommands: []cli.Command{ + Subcommands: []*cli.Command{ CheatStorageGetCmd, CheatStorageSetCmd, CheatStorageReadAll, @@ -269,7 +273,7 @@ var ( CheatStoragePatchCmd, }, } - CheatSetBalanceCmd = cli.Command{ + CheatSetBalanceCmd = &cli.Command{ Name: "balance", Flags: []cli.Flag{ DataDirFlag, @@ -280,7 +284,7 @@ var ( return ch.RunAndClose(cheat.SetBalance(addrFlagValue("address", ctx), bigFlagValue("balance", ctx))) }), } - CheatSetCodeCmd = cli.Command{ + CheatSetCodeCmd = &cli.Command{ Name: "code", Flags: []cli.Flag{ DataDirFlag, @@ -291,7 +295,7 @@ var ( return ch.RunAndClose(cheat.SetCode(addrFlagValue("address", ctx), bytesFlagValue("code", ctx))) }), } - CheatSetNonceCmd = cli.Command{ + CheatSetNonceCmd = &cli.Command{ Name: "nonce", Flags: []cli.Flag{ DataDirFlag, @@ -302,15 +306,15 @@ var ( return ch.RunAndClose(cheat.SetNonce(addrFlagValue("address", ctx), bigFlagValue("balance", ctx).Uint64())) }), } - CheatOvmOwnersCmd = cli.Command{ + CheatOvmOwnersCmd = &cli.Command{ Name: "ovm-owners", Flags: []cli.Flag{ DataDirFlag, - cli.StringFlag{ + &cli.StringFlag{ Name: "config", Usage: "Path to JSON config of OVM address replacements to apply.", Required: true, - EnvVar: opservice.PrefixEnvVar(envVarPrefix, "OVM_OWNERS"), + EnvVars: prefixEnvVars("OVM_OWNERS"), Value: "ovm-owners.json", }, }, @@ -326,7 +330,7 @@ var ( return ch.RunAndClose(cheat.OvmOwners(&conf)) }), } - CheatPrintHeadBlock = cli.Command{ + CheatPrintHeadBlock = &cli.Command{ Name: "head-block", Usage: "dump head block as JSON", Flags: []cli.Flag{ @@ -345,7 +349,7 @@ var ( }) }), } - CheatPrintHeadHeader = cli.Command{ + CheatPrintHeadHeader = &cli.Command{ Name: "head-header", Usage: "dump head header as JSON", Flags: []cli.Flag{ @@ -357,7 +361,7 @@ var ( return enc.Encode(rawdb.ReadHeadHeader(db)) }), } - EngineBlockCmd = cli.Command{ + EngineBlockCmd = &cli.Command{ Name: "block", Usage: "build the next block using the Engine API", Flags: []cli.Flag{ @@ -382,7 +386,7 @@ var ( return err }), } - EngineAutoCmd = cli.Command{ + EngineAutoCmd = &cli.Command{ Name: "auto", Usage: "Run a proof-of-nothing chain with fixed block time.", Description: "The block time can be changed. The execution engine must be synced to a post-Merge state first.", @@ -391,7 +395,7 @@ var ( FeeRecipientFlag, RandaoFlag, BlockTimeFlag, BuildingTime, AllowGaps, }, oplog.CLIFlags(envVarPrefix)...), opmetrics.CLIFlags(envVarPrefix)...), Action: EngineAction(func(ctx *cli.Context, client client.RPC) error { - logCfg := oplog.ReadLocalCLIConfig(ctx) + logCfg := oplog.ReadCLIConfig(ctx) if err := logCfg.Check(); err != nil { return fmt.Errorf("failed to parse log configuration: %w", err) } @@ -400,7 +404,7 @@ var ( settings := ParseBuildingArgs(ctx) // TODO: finalize/safe flag - metricsCfg := opmetrics.ReadLocalCLIConfig(ctx) + metricsCfg := opmetrics.ReadCLIConfig(ctx) return opservice.CloseAction(func(ctx context.Context, shutdown <-chan struct{}) error { registry := opmetrics.NewRegistry() @@ -417,7 +421,7 @@ var ( }) }), } - EngineStatusCmd = cli.Command{ + EngineStatusCmd = &cli.Command{ Name: "status", Flags: []cli.Flag{EngineEndpoint, EngineJWTPath}, Action: EngineAction(func(ctx *cli.Context, client client.RPC) error { @@ -430,15 +434,15 @@ var ( return enc.Encode(stat) }), } - EngineCopyCmd = cli.Command{ + EngineCopyCmd = &cli.Command{ Name: "copy", Flags: []cli.Flag{ EngineEndpoint, EngineJWTPath, - cli.StringFlag{ + &cli.StringFlag{ Name: "source", Usage: "Unauthenticated regular eth JSON RPC to pull block data from, can be HTTP/WS/IPC.", Required: true, - EnvVar: opservice.PrefixEnvVar(envVarPrefix, "ENGINE"), + EnvVars: prefixEnvVars("ENGINE"), }, }, Action: EngineAction(func(ctx *cli.Context, dest client.RPC) error { @@ -452,12 +456,12 @@ var ( } ) -var CheatCmd = cli.Command{ +var CheatCmd = &cli.Command{ Name: "cheat", Usage: "Cheating commands to modify a Geth database.", Description: "Each sub-command opens a Geth database, applies the cheat, and then saves and closes the database." + "The Geth node will live in its own false reality, other nodes cannot sync the cheated state if they process the blocks.", - Subcommands: []cli.Command{ + Subcommands: []*cli.Command{ CheatStorageCmd, CheatSetBalanceCmd, CheatSetCodeCmd, @@ -468,11 +472,11 @@ var CheatCmd = cli.Command{ }, } -var EngineCmd = cli.Command{ +var EngineCmd = &cli.Command{ Name: "engine", Usage: "Engine API commands to build/reorg/finalize blocks.", Description: "Each sub-command dials the engine API endpoint (with provided JWT secret) and then runs the action", - Subcommands: []cli.Command{ + Subcommands: []*cli.Command{ EngineBlockCmd, EngineAutoCmd, EngineStatusCmd, diff --git a/packages/contracts-bedrock/.gas-snapshot b/packages/contracts-bedrock/.gas-snapshot index 90126b2b06e7..46393f0ffac3 100644 --- a/packages/contracts-bedrock/.gas-snapshot +++ b/packages/contracts-bedrock/.gas-snapshot @@ -1,28 +1,28 @@ Bytes_slice_Test:test_slice_acrossMultipleWords_works() (gas: 9413) Bytes_slice_Test:test_slice_acrossWords_works() (gas: 1430) Bytes_slice_Test:test_slice_fromNonZeroIdx_works() (gas: 17240) -Bytes_slice_Test:test_slice_fromZeroIdx_works() (gas: 20826) +Bytes_slice_Test:test_slice_fromZeroIdx_works() (gas: 20804) Bytes_toNibbles_Test:test_toNibbles_expectedResult128Bytes_works() (gas: 78882) Bytes_toNibbles_Test:test_toNibbles_expectedResult5Bytes_works() (gas: 3992) Bytes_toNibbles_Test:test_toNibbles_zeroLengthInput_works() (gas: 823) CrossDomainMessenger_BaseGas_Test:test_baseGas_succeeds() (gas: 20412) -CrossDomainOwnable2_Test:test_onlyOwner_notMessenger_reverts() (gas: 8416) +CrossDomainOwnable2_Test:test_onlyOwner_notMessenger_reverts() (gas: 8461) CrossDomainOwnable2_Test:test_onlyOwner_notOwner2_reverts() (gas: 57515) -CrossDomainOwnable2_Test:test_onlyOwner_notOwner_reverts() (gas: 16588) +CrossDomainOwnable2_Test:test_onlyOwner_notOwner_reverts() (gas: 16610) CrossDomainOwnable2_Test:test_onlyOwner_succeeds() (gas: 73543) CrossDomainOwnable3_Test:test_constructor_succeeds() (gas: 10554) -CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notMessenger_reverts() (gas: 28334) +CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notMessenger_reverts() (gas: 28289) CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notOwner2_reverts() (gas: 73991) CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notOwner_reverts() (gas: 32000) CrossDomainOwnable3_Test:test_crossDomainTransferOwnership_succeeds() (gas: 91548) -CrossDomainOwnable3_Test:test_localOnlyOwner_notOwner_reverts() (gas: 13193) -CrossDomainOwnable3_Test:test_localOnlyOwner_succeeds() (gas: 35220) -CrossDomainOwnable3_Test:test_localTransferOwnership_succeeds() (gas: 52128) +CrossDomainOwnable3_Test:test_localOnlyOwner_notOwner_reverts() (gas: 13215) +CrossDomainOwnable3_Test:test_localOnlyOwner_succeeds() (gas: 35242) +CrossDomainOwnable3_Test:test_localTransferOwnership_succeeds() (gas: 52084) CrossDomainOwnable3_Test:test_transferOwnershipNoLocal_succeeds() (gas: 48610) -CrossDomainOwnable3_Test:test_transferOwnership_noLocalZeroAddress_reverts() (gas: 12015) +CrossDomainOwnable3_Test:test_transferOwnership_noLocalZeroAddress_reverts() (gas: 12037) CrossDomainOwnable3_Test:test_transferOwnership_notOwner_reverts() (gas: 13437) CrossDomainOwnable3_Test:test_transferOwnership_zeroAddress_reverts() (gas: 12081) -CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner_succeeds() (gas: 81416) +CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner_succeeds() (gas: 81394) CrossDomainOwnable_Test:test_onlyOwner_notOwner_reverts() (gas: 10597) CrossDomainOwnable_Test:test_onlyOwner_succeeds() (gas: 34883) DeployerWhitelist_Test:test_owner_succeeds() (gas: 7582) @@ -32,25 +32,30 @@ DisputeGameFactory_SetImplementation_Test:test_setImplementation_notOwner_revert DisputeGameFactory_SetImplementation_Test:test_setImplementation_succeeds() (gas: 44243) DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_notOwner_reverts() (gas: 15950) DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_succeeds() (gas: 18642) -FaultDisputeGame_Test:test_clockTimeExceeded_reverts() (gas: 26496) -FaultDisputeGame_Test:test_defendRoot_reverts() (gas: 13236) -FaultDisputeGame_Test:test_duplicateClaim_reverts() (gas: 103425) -FaultDisputeGame_Test:test_extraData_succeeds() (gas: 17478) -FaultDisputeGame_Test:test_gameData_succeeds() (gas: 17859) -FaultDisputeGame_Test:test_gameDepthExceeded_reverts() (gas: 5907231) +FaultDisputeGame_ResolvesCorrectly_CorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 497198) +FaultDisputeGame_ResolvesCorrectly_CorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 499064) +FaultDisputeGame_ResolvesCorrectly_CorrectRoot:test_resolvesCorrectly_succeeds() (gas: 489092) +FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 494067) +FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 495933) +FaultDisputeGame_ResolvesCorrectly_IncorrectRoot:test_resolvesCorrectly_succeeds() (gas: 485961) +FaultDisputeGame_Test:test_defendRoot_invalidMove_reverts() (gas: 13250) +FaultDisputeGame_Test:test_extraData_succeeds() (gas: 17409) +FaultDisputeGame_Test:test_gameData_succeeds() (gas: 17834) FaultDisputeGame_Test:test_gameStart_succeeds() (gas: 10337) -FaultDisputeGame_Test:test_gameType_succeeds() (gas: 8259) -FaultDisputeGame_Test:test_initialRootClaimData_succeeds() (gas: 17624) -FaultDisputeGame_Test:test_moveAgainstNonexistentParent_reverts() (gas: 24632) -FaultDisputeGame_Test:test_move_gameNotInProgress_reverts() (gas: 10945) -FaultDisputeGame_Test:test_resolve_challengeContested() (gas: 222383) -FaultDisputeGame_Test:test_resolve_reverts() (gas: 27121) -FaultDisputeGame_Test:test_resolve_rootContested() (gas: 107225) -FaultDisputeGame_Test:test_resolve_rootUncontested() (gas: 24459) -FaultDisputeGame_Test:test_resolve_teamDeathmatch() (gas: 393609) -FaultDisputeGame_Test:test_rootClaim_succeeds() (gas: 8169) -FaultDisputeGame_Test:test_simpleAttack_succeeds() (gas: 107389) -FaultDisputeGame_Test:test_version_succeeds() (gas: 9780) +FaultDisputeGame_Test:test_gameType_succeeds() (gas: 8216) +FaultDisputeGame_Test:test_initialRootClaimData_succeeds() (gas: 17691) +FaultDisputeGame_Test:test_move_clockTimeExceeded_reverts() (gas: 26410) +FaultDisputeGame_Test:test_move_duplicateClaim_reverts() (gas: 103231) +FaultDisputeGame_Test:test_move_gameDepthExceeded_reverts() (gas: 407967) +FaultDisputeGame_Test:test_move_gameNotInProgress_reverts() (gas: 10923) +FaultDisputeGame_Test:test_move_nonExistentParent_reverts() (gas: 24632) +FaultDisputeGame_Test:test_resolve_challengeContested() (gas: 221074) +FaultDisputeGame_Test:test_resolve_notInProgress_reverts() (gas: 9657) +FaultDisputeGame_Test:test_resolve_rootContested() (gas: 106120) +FaultDisputeGame_Test:test_resolve_rootUncontested() (gas: 23630) +FaultDisputeGame_Test:test_resolve_teamDeathmatch() (gas: 391731) +FaultDisputeGame_Test:test_rootClaim_succeeds() (gas: 8203) +FaultDisputeGame_Test:test_simpleAttack_succeeds() (gas: 107322) FeeVault_Test:test_constructor_succeeds() (gas: 18185) GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 352135) GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2950342) @@ -91,69 +96,69 @@ L1BlockTest:test_number_succeeds() (gas: 7629) L1BlockTest:test_sequenceNumber_succeeds() (gas: 7630) L1BlockTest:test_timestamp_succeeds() (gas: 7640) L1BlockTest:test_updateValues_succeeds() (gas: 60482) -L1CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 24738) +L1CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 24803) L1CrossDomainMessenger_Test:test_relayMessage_legacyOldReplay_reverts() (gas: 49395) -L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterFailureThenSuccess_reverts() (gas: 209744) -L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterFailure_succeeds() (gas: 203642) +L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterFailureThenSuccess_reverts() (gas: 209722) +L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterFailure_succeeds() (gas: 203620) L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterSuccess_reverts() (gas: 124002) -L1CrossDomainMessenger_Test:test_relayMessage_legacy_succeeds() (gas: 77316) -L1CrossDomainMessenger_Test:test_relayMessage_retryAfterFailure_succeeds() (gas: 197549) +L1CrossDomainMessenger_Test:test_relayMessage_legacy_succeeds() (gas: 77294) +L1CrossDomainMessenger_Test:test_relayMessage_retryAfterFailure_succeeds() (gas: 197594) L1CrossDomainMessenger_Test:test_relayMessage_succeeds() (gas: 74252) -L1CrossDomainMessenger_Test:test_relayMessage_toSystemContract_reverts() (gas: 56518) -L1CrossDomainMessenger_Test:test_relayMessage_v2_reverts() (gas: 12365) +L1CrossDomainMessenger_Test:test_relayMessage_toSystemContract_reverts() (gas: 56496) +L1CrossDomainMessenger_Test:test_relayMessage_v2_reverts() (gas: 12343) L1CrossDomainMessenger_Test:test_replayMessage_withValue_reverts() (gas: 31063) L1CrossDomainMessenger_Test:test_sendMessage_succeeds() (gas: 390823) -L1CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 1666686) +L1CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 1666664) L1CrossDomainMessenger_Test:test_xDomainMessageSender_reset_succeeds() (gas: 84694) L1CrossDomainMessenger_Test:test_xDomainSender_notSet_reverts() (gas: 24253) L1ERC721Bridge_Test:test_bridgeERC721To_localTokenZeroAddress_reverts() (gas: 52707) -L1ERC721Bridge_Test:test_bridgeERC721To_remoteTokenZeroAddress_reverts() (gas: 27310) +L1ERC721Bridge_Test:test_bridgeERC721To_remoteTokenZeroAddress_reverts() (gas: 27288) L1ERC721Bridge_Test:test_bridgeERC721To_succeeds() (gas: 445272) -L1ERC721Bridge_Test:test_bridgeERC721To_wrongOwner_reverts() (gas: 60934) +L1ERC721Bridge_Test:test_bridgeERC721To_wrongOwner_reverts() (gas: 61000) L1ERC721Bridge_Test:test_bridgeERC721_fromContract_reverts() (gas: 25666) L1ERC721Bridge_Test:test_bridgeERC721_localTokenZeroAddress_reverts() (gas: 50564) -L1ERC721Bridge_Test:test_bridgeERC721_remoteTokenZeroAddress_reverts() (gas: 25124) -L1ERC721Bridge_Test:test_bridgeERC721_succeeds() (gas: 442852) -L1ERC721Bridge_Test:test_bridgeERC721_wrongOwner_reverts() (gas: 60830) -L1ERC721Bridge_Test:test_constructor_succeeds() (gas: 10200) -L1ERC721Bridge_Test:test_finalizeBridgeERC721_notEscrowed_reverts() (gas: 22119) -L1ERC721Bridge_Test:test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() (gas: 19797) +L1ERC721Bridge_Test:test_bridgeERC721_remoteTokenZeroAddress_reverts() (gas: 25189) +L1ERC721Bridge_Test:test_bridgeERC721_succeeds() (gas: 442830) +L1ERC721Bridge_Test:test_bridgeERC721_wrongOwner_reverts() (gas: 60808) +L1ERC721Bridge_Test:test_constructor_succeeds() (gas: 10178) +L1ERC721Bridge_Test:test_finalizeBridgeERC721_notEscrowed_reverts() (gas: 22097) +L1ERC721Bridge_Test:test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() (gas: 19842) L1ERC721Bridge_Test:test_finalizeBridgeERC721_notViaLocalMessenger_reverts() (gas: 16049) L1ERC721Bridge_Test:test_finalizeBridgeERC721_selfToken_reverts() (gas: 17615) L1ERC721Bridge_Test:test_finalizeBridgeERC721_succeeds() (gas: 414364) -L1StandardBridge_BridgeETHTo_Test:test_bridgeETHTo_succeeds() (gas: 510416) +L1StandardBridge_BridgeETHTo_Test:test_bridgeETHTo_succeeds() (gas: 510482) L1StandardBridge_BridgeETH_Test:test_bridgeETH_succeeds() (gas: 497637) -L1StandardBridge_DepositERC20To_Test:test_depositERC20To_succeeds() (gas: 715714) +L1StandardBridge_DepositERC20To_Test:test_depositERC20To_succeeds() (gas: 715692) L1StandardBridge_DepositERC20_Test:test_depositERC20_succeeds() (gas: 713415) -L1StandardBridge_DepositERC20_TestFail:test_depositERC20_notEoa_reverts() (gas: 22320) +L1StandardBridge_DepositERC20_TestFail:test_depositERC20_notEoa_reverts() (gas: 22298) L1StandardBridge_DepositETHTo_Test:test_depositETHTo_succeeds() (gas: 510493) L1StandardBridge_DepositETH_Test:test_depositETH_succeeds() (gas: 497731) -L1StandardBridge_DepositETH_TestFail:test_depositETH_notEoa_reverts() (gas: 40780) -L1StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 51674) +L1StandardBridge_DepositETH_TestFail:test_depositETH_notEoa_reverts() (gas: 40758) +L1StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 51652) L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 34204) -L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 34310) +L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 34288) L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 34279) -L1StandardBridge_FinalizeERC20Withdrawal_Test:test_finalizeERC20Withdrawal_succeeds() (gas: 496123) +L1StandardBridge_FinalizeERC20Withdrawal_Test:test_finalizeERC20Withdrawal_succeeds() (gas: 496114) L1StandardBridge_FinalizeERC20Withdrawal_TestFail:test_finalizeERC20Withdrawal_notMessenger_reverts() (gas: 31206) L1StandardBridge_FinalizeERC20Withdrawal_TestFail:test_finalizeERC20Withdrawal_notOtherBridge_reverts() (gas: 31562) L1StandardBridge_FinalizeETHWithdrawal_Test:test_finalizeETHWithdrawal_succeeds() (gas: 61722) -L1StandardBridge_Getter_Test:test_getters_succeeds() (gas: 32173) +L1StandardBridge_Getter_Test:test_getters_succeeds() (gas: 32875) L1StandardBridge_Initialize_Test:test_initialize_succeeds() (gas: 22050) L1StandardBridge_Receive_Test:test_receive_succeeds() (gas: 610719) -L2CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 8434) -L2CrossDomainMessenger_Test:test_relayMessage_retry_succeeds() (gas: 163771) +L2CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 8477) +L2CrossDomainMessenger_Test:test_relayMessage_retry_succeeds() (gas: 163815) L2CrossDomainMessenger_Test:test_relayMessage_succeeds() (gas: 48946) -L2CrossDomainMessenger_Test:test_relayMessage_toSystemContract_reverts() (gas: 29021) -L2CrossDomainMessenger_Test:test_relayMessage_v2_reverts() (gas: 11711) +L2CrossDomainMessenger_Test:test_relayMessage_toSystemContract_reverts() (gas: 29066) +L2CrossDomainMessenger_Test:test_relayMessage_v2_reverts() (gas: 11689) L2CrossDomainMessenger_Test:test_sendMessage_succeeds() (gas: 123768) -L2CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 135456) +L2CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 135434) L2CrossDomainMessenger_Test:test_xDomainMessageSender_reset_succeeds() (gas: 48422) -L2CrossDomainMessenger_Test:test_xDomainSender_senderNotSet_reverts() (gas: 10612) +L2CrossDomainMessenger_Test:test_xDomainSender_senderNotSet_reverts() (gas: 10590) L2ERC721Bridge_Test:test_bridgeERC721To_localTokenZeroAddress_reverts() (gas: 26431) L2ERC721Bridge_Test:test_bridgeERC721To_remoteTokenZeroAddress_reverts() (gas: 21814) L2ERC721Bridge_Test:test_bridgeERC721To_succeeds() (gas: 147356) L2ERC721Bridge_Test:test_bridgeERC721To_wrongOwner_reverts() (gas: 29449) -L2ERC721Bridge_Test:test_bridgeERC721_fromContract_reverts() (gas: 22148) +L2ERC721Bridge_Test:test_bridgeERC721_fromContract_reverts() (gas: 22170) L2ERC721Bridge_Test:test_bridgeERC721_localTokenZeroAddress_reverts() (gas: 24310) L2ERC721Bridge_Test:test_bridgeERC721_remoteTokenZeroAddress_reverts() (gas: 19628) L2ERC721Bridge_Test:test_bridgeERC721_succeeds() (gas: 144958) @@ -162,55 +167,55 @@ L2ERC721Bridge_Test:test_constructor_succeeds() (gas: 10110) L2ERC721Bridge_Test:test_finalizeBridgeERC721_alreadyExists_reverts() (gas: 29218) L2ERC721Bridge_Test:test_finalizeBridgeERC721_interfaceNotCompliant_reverts() (gas: 236327) L2ERC721Bridge_Test:test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() (gas: 19874) -L2ERC721Bridge_Test:test_finalizeBridgeERC721_notViaLocalMessenger_reverts() (gas: 16104) -L2ERC721Bridge_Test:test_finalizeBridgeERC721_selfToken_reverts() (gas: 17659) +L2ERC721Bridge_Test:test_finalizeBridgeERC721_notViaLocalMessenger_reverts() (gas: 16126) +L2ERC721Bridge_Test:test_finalizeBridgeERC721_selfToken_reverts() (gas: 17681) L2ERC721Bridge_Test:test_finalizeBridgeERC721_succeeds() (gas: 169375) -L2OutputOracleTest:test_computeL2Timestamp_succeeds() (gas: 37298) -L2OutputOracleTest:test_constructor_badTimestamp_reverts() (gas: 70991) -L2OutputOracleTest:test_constructor_l2BlockTimeZero_reverts() (gas: 45954) -L2OutputOracleTest:test_constructor_submissionInterval_reverts() (gas: 45942) -L2OutputOracleTest:test_constructor_succeeds() (gas: 33805) -L2OutputOracleTest:test_deleteL2Outputs_afterLatest_reverts() (gas: 212306) -L2OutputOracleTest:test_deleteL2Outputs_finalized_reverts() (gas: 108990) -L2OutputOracleTest:test_deleteL2Outputs_ifNotChallenger_reverts() (gas: 18918) -L2OutputOracleTest:test_deleteL2Outputs_nonExistent_reverts() (gas: 107339) -L2OutputOracleTest:test_deleteOutputs_multipleOutputs_succeeds() (gas: 302462) -L2OutputOracleTest:test_deleteOutputs_singleOutput_succeeds() (gas: 181016) -L2OutputOracleTest:test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() (gas: 267098) -L2OutputOracleTest:test_getL2OutputIndexAfter_noOutputsExis_reverts() (gas: 17937) -L2OutputOracleTest:test_getL2OutputIndexAfter_previousBlock_succeeds() (gas: 96044) -L2OutputOracleTest:test_getL2OutputIndexAfter_sameBlock_succeeds() (gas: 95973) -L2OutputOracleTest:test_getL2Output_succeeds() (gas: 101612) -L2OutputOracleTest:test_latestBlockNumber_succeeds() (gas: 96940) -L2OutputOracleTest:test_nextBlockNumber_succeeds() (gas: 17468) -L2OutputOracleTest:test_proposeL2Output_emptyOutput_reverts() (gas: 26668) -L2OutputOracleTest:test_proposeL2Output_futureTimetamp_reverts() (gas: 28647) -L2OutputOracleTest:test_proposeL2Output_notProposer_reverts() (gas: 25806) -L2OutputOracleTest:test_proposeL2Output_proposeAnotherOutput_succeeds() (gas: 101006) -L2OutputOracleTest:test_proposeL2Output_unexpectedBlockNumber_reverts() (gas: 28381) -L2OutputOracleTest:test_proposeL2Output_unmatchedBlockhash_reverts() (gas: 29404) -L2OutputOracleTest:test_proposeL2Output_wrongFork_reverts() (gas: 28984) -L2OutputOracleTest:test_proposeWithBlockhashAndHeight_succeeds() (gas: 95253) L2OutputOracleUpgradeable_Test:test_initValuesOnProxy_succeeds() (gas: 26208) L2OutputOracleUpgradeable_Test:test_initializeImpl_alreadyInitialized_reverts() (gas: 15149) L2OutputOracleUpgradeable_Test:test_initializeProxy_alreadyInitialized_reverts() (gas: 20175) L2OutputOracleUpgradeable_Test:test_upgrading_succeeds() (gas: 180481) +L2OutputOracle_constructor_Test:test_constructor_badTimestamp_reverts() (gas: 70927) +L2OutputOracle_constructor_Test:test_constructor_l2BlockTimeZero_reverts() (gas: 45912) +L2OutputOracle_constructor_Test:test_constructor_submissionInterval_reverts() (gas: 45922) +L2OutputOracle_constructor_Test:test_constructor_succeeds() (gas: 33783) +L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_afterLatest_reverts() (gas: 212239) +L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_finalized_reverts() (gas: 108968) +L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_ifNotChallenger_reverts() (gas: 18895) +L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_nonExistent_reverts() (gas: 107316) +L2OutputOracle_deleteOutputs_Test:test_deleteOutputs_multipleOutputs_succeeds() (gas: 302439) +L2OutputOracle_deleteOutputs_Test:test_deleteOutputs_singleOutput_succeeds() (gas: 181016) +L2OutputOracle_getter_Test:test_computeL2Timestamp_succeeds() (gas: 37253) +L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() (gas: 267098) +L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_noOutputsExis_reverts() (gas: 17914) +L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_previousBlock_succeeds() (gas: 96043) +L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_sameBlock_succeeds() (gas: 95951) +L2OutputOracle_getter_Test:test_getL2Output_succeeds() (gas: 101612) +L2OutputOracle_getter_Test:test_latestBlockNumber_succeeds() (gas: 96917) +L2OutputOracle_getter_Test:test_nextBlockNumber_succeeds() (gas: 17424) +L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_emptyOutput_reverts() (gas: 26645) +L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_futureTimetamp_reverts() (gas: 28625) +L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_notProposer_reverts() (gas: 25761) +L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_proposeAnotherOutput_succeeds() (gas: 101030) +L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_unexpectedBlockNumber_reverts() (gas: 28359) +L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_unmatchedBlockhash_reverts() (gas: 29359) +L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_wrongFork_reverts() (gas: 28962) +L2OutputOracle_proposeL2Output_Test:test_proposeWithBlockhashAndHeight_succeeds() (gas: 95275) L2StandardBridge_BridgeERC20To_Test:test_bridgeERC20To_succeeds() (gas: 390272) L2StandardBridge_BridgeERC20To_Test:test_withdrawTo_withdrawingERC20_succeeds() (gas: 390505) L2StandardBridge_BridgeERC20_Test:test_bridgeERC20_succeeds() (gas: 385779) L2StandardBridge_BridgeERC20_Test:test_bridgeLegacyERC20_succeeds() (gas: 394052) -L2StandardBridge_BridgeERC20_Test:test_withdrawLegacyERC20_succeeds() (gas: 394377) +L2StandardBridge_BridgeERC20_Test:test_withdrawLegacyERC20_succeeds() (gas: 394360) L2StandardBridge_BridgeERC20_Test:test_withdraw_notEOA_reverts() (gas: 251753) L2StandardBridge_BridgeERC20_Test:test_withdraw_withdrawingERC20_succeeds() (gas: 386007) L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 23843) -L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 23982) +L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 24005) L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 23870) L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingERC20_succeeds() (gas: 93824) -L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingETH_succeeds() (gas: 92700) -L2StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 43155) +L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingETH_succeeds() (gas: 92678) +L2StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 43133) L2StandardBridge_Test:test_initialize_succeeds() (gas: 24292) L2StandardBridge_Test:test_receive_succeeds() (gas: 174641) -L2StandardBridge_Test:test_withdraw_ether_succeeds() (gas: 140793) +L2StandardBridge_Test:test_withdraw_ether_succeeds() (gas: 140815) L2StandardBridge_Test:test_withdraw_insufficientValue_reverts() (gas: 16485) L2ToL1MessagePasserTest:test_burn_succeeds() (gas: 112572) L2ToL1MessagePasserTest:test_initiateWithdrawal_fromContract_succeeds() (gas: 70445) @@ -225,6 +230,7 @@ LegacyERC20ETH_Test:test_mint_doesNotExist_reverts() (gas: 10627) LegacyERC20ETH_Test:test_transferFrom_doesNotExist_reverts() (gas: 12957) LegacyERC20ETH_Test:test_transfer_doesNotExist_reverts() (gas: 10755) LegacyMessagePasser_Test:test_passMessageToL1_succeeds() (gas: 34524) +LibPosition_Test:test_pos_correctness_succeeds() (gas: 38711) MerkleTrie_get_Test:test_get_corruptedProof_reverts() (gas: 5736) MerkleTrie_get_Test:test_get_extraProofElements_reverts() (gas: 58975) MerkleTrie_get_Test:test_get_invalidDataRemainder_reverts() (gas: 35852) @@ -255,26 +261,26 @@ MintManager_mint_Test:test_mint_moreThanCap_reverts() (gas: 142523) MintManager_upgrade_Test:test_upgrade_fromNotOwner_reverts() (gas: 10974) MintManager_upgrade_Test:test_upgrade_fromOwner_succeeds() (gas: 23434) MintManager_upgrade_Test:test_upgrade_toZeroAddress_reverts() (gas: 11003) -OptimismMintableERC20_Test:test_bridge_succeeds() (gas: 7643) +OptimismMintableERC20_Test:test_bridge_succeeds() (gas: 7621) OptimismMintableERC20_Test:test_burn_notBridge_reverts() (gas: 11164) OptimismMintableERC20_Test:test_burn_succeeds() (gas: 50996) -OptimismMintableERC20_Test:test_erc165_supportsInterface_succeeds() (gas: 7809) +OptimismMintableERC20_Test:test_erc165_supportsInterface_succeeds() (gas: 7787) OptimismMintableERC20_Test:test_l1Token_succeeds() (gas: 7621) OptimismMintableERC20_Test:test_l2Bridge_succeeds() (gas: 7621) -OptimismMintableERC20_Test:test_legacy_succeeds() (gas: 14344) -OptimismMintableERC20_Test:test_mint_notBridge_reverts() (gas: 11121) -OptimismMintableERC20_Test:test_mint_succeeds() (gas: 63566) -OptimismMintableERC20_Test:test_remoteToken_succeeds() (gas: 7689) +OptimismMintableERC20_Test:test_legacy_succeeds() (gas: 14322) +OptimismMintableERC20_Test:test_mint_notBridge_reverts() (gas: 11165) +OptimismMintableERC20_Test:test_mint_succeeds() (gas: 63544) +OptimismMintableERC20_Test:test_remoteToken_succeeds() (gas: 7667) OptimismMintableERC20_Test:test_semver_succeeds() (gas: 8812) -OptimismMintableERC721Factory_Test:test_constructor_succeeds() (gas: 8285) -OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_succeeds() (gas: 2321842) +OptimismMintableERC721Factory_Test:test_constructor_succeeds() (gas: 8351) +OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_succeeds() (gas: 2321820) OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_zeroRemoteToken_reverts() (gas: 9418) OptimismMintableERC721_Test:test_burn_notBridge_reverts() (gas: 136966) OptimismMintableERC721_Test:test_burn_succeeds() (gas: 118832) -OptimismMintableERC721_Test:test_constructor_succeeds() (gas: 29003) -OptimismMintableERC721_Test:test_safeMint_notBridge_reverts() (gas: 11143) -OptimismMintableERC721_Test:test_safeMint_succeeds() (gas: 140524) -OptimismMintableERC721_Test:test_supportsInterfaces_succeeds() (gas: 9027) +OptimismMintableERC721_Test:test_constructor_succeeds() (gas: 28981) +OptimismMintableERC721_Test:test_safeMint_notBridge_reverts() (gas: 11121) +OptimismMintableERC721_Test:test_safeMint_succeeds() (gas: 140547) +OptimismMintableERC721_Test:test_supportsInterfaces_succeeds() (gas: 9005) OptimismMintableERC721_Test:test_tokenURI_succeeds() (gas: 163441) OptimismMintableTokenFactory_Test:test_bridge_succeeds() (gas: 7580) OptimismMintableTokenFactory_Test:test_createStandardL2Token_remoteIsZero_succeeds() (gas: 9390) @@ -305,8 +311,8 @@ OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayPro OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProve_reverts() (gas: 166424) OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() (gas: 154362) OptimismPortal_Test:test_constructor_succeeds() (gas: 19402) -OptimismPortal_Test:test_depositTransaction_contractCreation_reverts() (gas: 14342) -OptimismPortal_Test:test_depositTransaction_createWithZeroValueForContract_succeeds() (gas: 76726) +OptimismPortal_Test:test_depositTransaction_contractCreation_reverts() (gas: 14320) +OptimismPortal_Test:test_depositTransaction_createWithZeroValueForContract_succeeds() (gas: 76791) OptimismPortal_Test:test_depositTransaction_createWithZeroValueForEOA_succeeds() (gas: 77264) OptimismPortal_Test:test_depositTransaction_largeData_reverts() (gas: 512221) OptimismPortal_Test:test_depositTransaction_noValueContract_succeeds() (gas: 76916) @@ -314,12 +320,12 @@ OptimismPortal_Test:test_depositTransaction_noValueEOA_succeeds() (gas: 77261) OptimismPortal_Test:test_depositTransaction_smallGasLimit_reverts() (gas: 14556) OptimismPortal_Test:test_depositTransaction_withEthValueAndContractContractCreation_succeeds() (gas: 83750) OptimismPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation_succeeds() (gas: 75906) -OptimismPortal_Test:test_depositTransaction_withEthValueFromContract_succeeds() (gas: 83602) +OptimismPortal_Test:test_depositTransaction_withEthValueFromContract_succeeds() (gas: 83625) OptimismPortal_Test:test_depositTransaction_withEthValueFromEOA_succeeds() (gas: 84218) OptimismPortal_Test:test_isOutputFinalized_succeeds() (gas: 121831) OptimismPortal_Test:test_minimumGasLimit_succeeds() (gas: 17650) OptimismPortal_Test:test_pause_onlyGuardian_reverts() (gas: 22196) -OptimismPortal_Test:test_pause_succeeds() (gas: 42175) +OptimismPortal_Test:test_pause_succeeds() (gas: 42153) OptimismPortal_Test:test_receive_succeeds() (gas: 127513) OptimismPortal_Test:test_simple_isOutputFinalized_succeeds() (gas: 32971) OptimismPortal_Test:test_unpause_onlyGuardian_reverts() (gas: 46098) @@ -435,15 +441,15 @@ SafeCall_Test:test_callWithMinGas_noLeakageLow_succeeds() (gas: 1095190710) Semver_Test:test_behindProxy_succeeds() (gas: 506748) Semver_Test:test_version_succeeds() (gas: 9418) SequencerFeeVault_L2Withdrawal_Test:test_withdraw_toL2_succeeds() (gas: 78286) -SequencerFeeVault_Test:test_constructor_succeeds() (gas: 5548) +SequencerFeeVault_Test:test_constructor_succeeds() (gas: 5526) SequencerFeeVault_Test:test_minWithdrawalAmount_succeeds() (gas: 5464) SequencerFeeVault_Test:test_receive_succeeds() (gas: 17373) -SequencerFeeVault_Test:test_withdraw_notEnough_reverts() (gas: 9353) +SequencerFeeVault_Test:test_withdraw_notEnough_reverts() (gas: 9331) SequencerFeeVault_Test:test_withdraw_toL1_succeeds() (gas: 169242) SetPrevBaseFee_Test:test_setPrevBaseFee_succeeds() (gas: 11515) StandardBridge_Stateless_Test:test_isCorrectTokenPair_succeeds() (gas: 49936) StandardBridge_Stateless_Test:test_isOptimismMintableERC20_succeeds() (gas: 33072) -SystemConfig_Initialize_TestFail:test_initialize_lowGasLimit_reverts() (gas: 148848) +SystemConfig_Initialize_TestFail:test_initialize_lowGasLimit_reverts() (gas: 148851) SystemConfig_Setters_TestFail:test_setBatcherHash_notOwner_reverts() (gas: 10546) SystemConfig_Setters_TestFail:test_setGasConfig_notOwner_reverts() (gas: 10622) SystemConfig_Setters_TestFail:test_setGasLimit_notOwner_reverts() (gas: 10615) diff --git a/packages/contracts-bedrock/contracts/L1/L1CrossDomainMessenger.sol b/packages/contracts-bedrock/contracts/L1/L1CrossDomainMessenger.sol index 796a7c853ba9..42b2fed3bd79 100644 --- a/packages/contracts-bedrock/contracts/L1/L1CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/contracts/L1/L1CrossDomainMessenger.sol @@ -6,42 +6,32 @@ import { OptimismPortal } from "./OptimismPortal.sol"; import { CrossDomainMessenger } from "../universal/CrossDomainMessenger.sol"; import { Semver } from "../universal/Semver.sol"; -/** - * @custom:proxied - * @title L1CrossDomainMessenger - * @notice The L1CrossDomainMessenger is a message passing interface between L1 and L2 responsible - * for sending and receiving data on the L1 side. Users are encouraged to use this - * interface instead of interacting with lower-level contracts directly. - */ +/// @custom:proxied +/// @title L1CrossDomainMessenger +/// @notice The L1CrossDomainMessenger is a message passing interface between L1 and L2 responsible +/// for sending and receiving data on the L1 side. Users are encouraged to use this +/// interface instead of interacting with lower-level contracts directly. contract L1CrossDomainMessenger is CrossDomainMessenger, Semver { - /** - * @notice Address of the OptimismPortal. - */ + /// @notice Address of the OptimismPortal. OptimismPortal public immutable PORTAL; - /** - * @custom:semver 1.4.0 - * - * @param _portal Address of the OptimismPortal contract on this network. - */ + /// @custom:semver 1.4.1 + /// @notice Constructs the L1CrossDomainMessenger contract. + /// @param _portal Address of the OptimismPortal contract on this network. constructor(OptimismPortal _portal) - Semver(1, 4, 0) + Semver(1, 4, 1) CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER) { PORTAL = _portal; initialize(); } - /** - * @notice Initializer. - */ + /// @notice Initializes the contract. function initialize() public initializer { __CrossDomainMessenger_init(); } - /** - * @inheritdoc CrossDomainMessenger - */ + /// @inheritdoc CrossDomainMessenger function _sendMessage( address _to, uint64 _gasLimit, @@ -51,16 +41,12 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, Semver { PORTAL.depositTransaction{ value: _value }(_to, _value, _gasLimit, false, _data); } - /** - * @inheritdoc CrossDomainMessenger - */ + /// @inheritdoc CrossDomainMessenger function _isOtherMessenger() internal view override returns (bool) { return msg.sender == address(PORTAL) && PORTAL.l2Sender() == OTHER_MESSENGER; } - /** - * @inheritdoc CrossDomainMessenger - */ + /// @inheritdoc CrossDomainMessenger function _isUnsafeTarget(address _target) internal view override returns (bool) { return _target == address(this) || _target == address(PORTAL); } diff --git a/packages/contracts-bedrock/contracts/L1/L1ERC721Bridge.sol b/packages/contracts-bedrock/contracts/L1/L1ERC721Bridge.sol index 4d9d329f7d96..af3a38d80c56 100644 --- a/packages/contracts-bedrock/contracts/L1/L1ERC721Bridge.sol +++ b/packages/contracts-bedrock/contracts/L1/L1ERC721Bridge.sol @@ -6,43 +6,34 @@ import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import { L2ERC721Bridge } from "../L2/L2ERC721Bridge.sol"; import { Semver } from "../universal/Semver.sol"; -/** - * @title L1ERC721Bridge - * @notice The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to - * make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract - * acts as an escrow for ERC721 tokens deposited into L2. - */ +/// @title L1ERC721Bridge +/// @notice The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to +/// make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract +/// acts as an escrow for ERC721 tokens deposited into L2. contract L1ERC721Bridge is ERC721Bridge, Semver { - /** - * @notice Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token - * by ID was deposited for a given L2 token. - */ + /// @notice Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token + /// by ID was deposited for a given L2 token. mapping(address => mapping(address => mapping(uint256 => bool))) public deposits; - /** - * @custom:semver 1.1.1 - * - * @param _messenger Address of the CrossDomainMessenger on this network. - * @param _otherBridge Address of the ERC721 bridge on the other network. - */ + /// @custom:semver 1.1.2 + /// @notice Constructs the L1ERC721Bridge contract. + /// @param _messenger Address of the CrossDomainMessenger on this network. + /// @param _otherBridge Address of the ERC721 bridge on the other network. constructor(address _messenger, address _otherBridge) - Semver(1, 1, 1) + Semver(1, 1, 2) ERC721Bridge(_messenger, _otherBridge) {} - /** - * @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the - * recipient on this domain. - * - * @param _localToken Address of the ERC721 token on this domain. - * @param _remoteToken Address of the ERC721 token on the other domain. - * @param _from Address that triggered the bridge on the other domain. - * @param _to Address to receive the token on this domain. - * @param _tokenId ID of the token being deposited. - * @param _extraData Optional data to forward to L2. Data supplied here will not be used to - * execute any code on L2 and is only emitted as extra data for the - * convenience of off-chain tooling. - */ + /// @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the + /// recipient on this domain. + /// @param _localToken Address of the ERC721 token on this domain. + /// @param _remoteToken Address of the ERC721 token on the other domain. + /// @param _from Address that triggered the bridge on the other domain. + /// @param _to Address to receive the token on this domain. + /// @param _tokenId ID of the token being deposited. + /// @param _extraData Optional data to forward to L2. + /// Data supplied here will not be used to execute any code on L2 and is + /// only emitted as extra data for the convenience of off-chain tooling. function finalizeBridgeERC721( address _localToken, address _remoteToken, @@ -71,9 +62,7 @@ contract L1ERC721Bridge is ERC721Bridge, Semver { emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData); } - /** - * @inheritdoc ERC721Bridge - */ + /// @inheritdoc ERC721Bridge function _initiateBridgeERC721( address _localToken, address _remoteToken, diff --git a/packages/contracts-bedrock/contracts/L1/L1StandardBridge.sol b/packages/contracts-bedrock/contracts/L1/L1StandardBridge.sol index 3cfb1bba02df..78a35199a6a8 100644 --- a/packages/contracts-bedrock/contracts/L1/L1StandardBridge.sol +++ b/packages/contracts-bedrock/contracts/L1/L1StandardBridge.sol @@ -5,28 +5,23 @@ import { Predeploys } from "../libraries/Predeploys.sol"; import { StandardBridge } from "../universal/StandardBridge.sol"; import { Semver } from "../universal/Semver.sol"; -/** - * @custom:proxied - * @title L1StandardBridge - * @notice The L1StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and - * L2. In the case that an ERC20 token is native to L1, it will be escrowed within this - * contract. If the ERC20 token is native to L2, it will be burnt. Before Bedrock, ETH was - * stored within this contract. After Bedrock, ETH is instead stored inside the - * OptimismPortal contract. - * NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples - * of some token types that may not be properly supported by this contract include, but are - * not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists. - */ +/// @custom:proxied +/// @title L1StandardBridge +/// @notice The L1StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and +/// L2. In the case that an ERC20 token is native to L1, it will be escrowed within this +/// contract. If the ERC20 token is native to L2, it will be burnt. Before Bedrock, ETH was +/// stored within this contract. After Bedrock, ETH is instead stored inside the +/// OptimismPortal contract. +/// NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples +/// of some token types that may not be properly supported by this contract include, but are +/// not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists. contract L1StandardBridge is StandardBridge, Semver { - /** - * @custom:legacy - * @notice Emitted whenever a deposit of ETH from L1 into L2 is initiated. - * - * @param from Address of the depositor. - * @param to Address of the recipient on L2. - * @param amount Amount of ETH deposited. - * @param extraData Extra data attached to the deposit. - */ + /// @custom:legacy + /// @notice Emitted whenever a deposit of ETH from L1 into L2 is initiated. + /// @param from Address of the depositor. + /// @param to Address of the recipient on L2. + /// @param amount Amount of ETH deposited. + /// @param extraData Extra data attached to the deposit. event ETHDepositInitiated( address indexed from, address indexed to, @@ -34,15 +29,12 @@ contract L1StandardBridge is StandardBridge, Semver { bytes extraData ); - /** - * @custom:legacy - * @notice Emitted whenever a withdrawal of ETH from L2 to L1 is finalized. - * - * @param from Address of the withdrawer. - * @param to Address of the recipient on L1. - * @param amount Amount of ETH withdrawn. - * @param extraData Extra data attached to the withdrawal. - */ + /// @custom:legacy + /// @notice Emitted whenever a withdrawal of ETH from L2 to L1 is finalized. + /// @param from Address of the withdrawer. + /// @param to Address of the recipient on L1. + /// @param amount Amount of ETH withdrawn. + /// @param extraData Extra data attached to the withdrawal. event ETHWithdrawalFinalized( address indexed from, address indexed to, @@ -50,17 +42,14 @@ contract L1StandardBridge is StandardBridge, Semver { bytes extraData ); - /** - * @custom:legacy - * @notice Emitted whenever an ERC20 deposit is initiated. - * - * @param l1Token Address of the token on L1. - * @param l2Token Address of the corresponding token on L2. - * @param from Address of the depositor. - * @param to Address of the recipient on L2. - * @param amount Amount of the ERC20 deposited. - * @param extraData Extra data attached to the deposit. - */ + /// @custom:legacy + /// @notice Emitted whenever an ERC20 deposit is initiated. + /// @param l1Token Address of the token on L1. + /// @param l2Token Address of the corresponding token on L2. + /// @param from Address of the depositor. + /// @param to Address of the recipient on L2. + /// @param amount Amount of the ERC20 deposited. + /// @param extraData Extra data attached to the deposit. event ERC20DepositInitiated( address indexed l1Token, address indexed l2Token, @@ -70,17 +59,14 @@ contract L1StandardBridge is StandardBridge, Semver { bytes extraData ); - /** - * @custom:legacy - * @notice Emitted whenever an ERC20 withdrawal is finalized. - * - * @param l1Token Address of the token on L1. - * @param l2Token Address of the corresponding token on L2. - * @param from Address of the withdrawer. - * @param to Address of the recipient on L1. - * @param amount Amount of the ERC20 withdrawn. - * @param extraData Extra data attached to the withdrawal. - */ + /// @custom:legacy + /// @notice Emitted whenever an ERC20 withdrawal is finalized. + /// @param l1Token Address of the token on L1. + /// @param l2Token Address of the corresponding token on L2. + /// @param from Address of the withdrawer. + /// @param to Address of the recipient on L1. + /// @param amount Amount of the ERC20 withdrawn. + /// @param extraData Extra data attached to the withdrawal. event ERC20WithdrawalFinalized( address indexed l1Token, address indexed l2Token, @@ -90,50 +76,40 @@ contract L1StandardBridge is StandardBridge, Semver { bytes extraData ); - /** - * @custom:semver 1.1.0 - * - * @param _messenger Address of the L1CrossDomainMessenger. - */ + /// @custom:semver 1.1.1 + /// @notice Constructs the L1StandardBridge contract. + /// @param _messenger Address of the L1CrossDomainMessenger. constructor(address payable _messenger) - Semver(1, 1, 0) + Semver(1, 1, 1) StandardBridge(_messenger, payable(Predeploys.L2_STANDARD_BRIDGE)) {} - /** - * @notice Allows EOAs to bridge ETH by sending directly to the bridge. - */ + /// @notice Allows EOAs to bridge ETH by sending directly to the bridge. receive() external payable override onlyEOA { _initiateETHDeposit(msg.sender, msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes("")); } - /** - * @custom:legacy - * @notice Deposits some amount of ETH into the sender's account on L2. - * - * @param _minGasLimit Minimum gas limit for the deposit message on L2. - * @param _extraData Optional data to forward to L2. Data supplied here will not be used to - * execute any code on L2 and is only emitted as extra data for the - * convenience of off-chain tooling. - */ + /// @custom:legacy + /// @notice Deposits some amount of ETH into the sender's account on L2. + /// @param _minGasLimit Minimum gas limit for the deposit message on L2. + /// @param _extraData Optional data to forward to L2. + /// Data supplied here will not be used to execute any code on L2 and is + /// only emitted as extra data for the convenience of off-chain tooling. function depositETH(uint32 _minGasLimit, bytes calldata _extraData) external payable onlyEOA { _initiateETHDeposit(msg.sender, msg.sender, _minGasLimit, _extraData); } - /** - * @custom:legacy - * @notice Deposits some amount of ETH into a target account on L2. - * Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will - * be locked in the L2StandardBridge. ETH may be recoverable if the call can be - * successfully replayed by increasing the amount of gas supplied to the call. If the - * call will fail for any amount of gas, then the ETH will be locked permanently. - * - * @param _to Address of the recipient on L2. - * @param _minGasLimit Minimum gas limit for the deposit message on L2. - * @param _extraData Optional data to forward to L2. Data supplied here will not be used to - * execute any code on L2 and is only emitted as extra data for the - * convenience of off-chain tooling. - */ + /// @custom:legacy + /// @notice Deposits some amount of ETH into a target account on L2. + /// Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will + /// be locked in the L2StandardBridge. ETH may be recoverable if the call can be + /// successfully replayed by increasing the amount of gas supplied to the call. If the + /// call will fail for any amount of gas, then the ETH will be locked permanently. + /// @param _to Address of the recipient on L2. + /// @param _minGasLimit Minimum gas limit for the deposit message on L2. + /// @param _extraData Optional data to forward to L2. + /// Data supplied here will not be used to execute any code on L2 and is + /// only emitted as extra data for the convenience of off-chain tooling. function depositETHTo( address _to, uint32 _minGasLimit, @@ -142,18 +118,15 @@ contract L1StandardBridge is StandardBridge, Semver { _initiateETHDeposit(msg.sender, _to, _minGasLimit, _extraData); } - /** - * @custom:legacy - * @notice Deposits some amount of ERC20 tokens into the sender's account on L2. - * - * @param _l1Token Address of the L1 token being deposited. - * @param _l2Token Address of the corresponding token on L2. - * @param _amount Amount of the ERC20 to deposit. - * @param _minGasLimit Minimum gas limit for the deposit message on L2. - * @param _extraData Optional data to forward to L2. Data supplied here will not be used to - * execute any code on L2 and is only emitted as extra data for the - * convenience of off-chain tooling. - */ + /// @custom:legacy + /// @notice Deposits some amount of ERC20 tokens into the sender's account on L2. + /// @param _l1Token Address of the L1 token being deposited. + /// @param _l2Token Address of the corresponding token on L2. + /// @param _amount Amount of the ERC20 to deposit. + /// @param _minGasLimit Minimum gas limit for the deposit message on L2. + /// @param _extraData Optional data to forward to L2. + /// Data supplied here will not be used to execute any code on L2 and is + /// only emitted as extra data for the convenience of off-chain tooling. function depositERC20( address _l1Token, address _l2Token, @@ -172,19 +145,16 @@ contract L1StandardBridge is StandardBridge, Semver { ); } - /** - * @custom:legacy - * @notice Deposits some amount of ERC20 tokens into a target account on L2. - * - * @param _l1Token Address of the L1 token being deposited. - * @param _l2Token Address of the corresponding token on L2. - * @param _to Address of the recipient on L2. - * @param _amount Amount of the ERC20 to deposit. - * @param _minGasLimit Minimum gas limit for the deposit message on L2. - * @param _extraData Optional data to forward to L2. Data supplied here will not be used to - * execute any code on L2 and is only emitted as extra data for the - * convenience of off-chain tooling. - */ + /// @custom:legacy + /// @notice Deposits some amount of ERC20 tokens into a target account on L2. + /// @param _l1Token Address of the L1 token being deposited. + /// @param _l2Token Address of the corresponding token on L2. + /// @param _to Address of the recipient on L2. + /// @param _amount Amount of the ERC20 to deposit. + /// @param _minGasLimit Minimum gas limit for the deposit message on L2. + /// @param _extraData Optional data to forward to L2. + /// Data supplied here will not be used to execute any code on L2 and is + /// only emitted as extra data for the convenience of off-chain tooling. function depositERC20To( address _l1Token, address _l2Token, @@ -204,15 +174,12 @@ contract L1StandardBridge is StandardBridge, Semver { ); } - /** - * @custom:legacy - * @notice Finalizes a withdrawal of ETH from L2. - * - * @param _from Address of the withdrawer on L2. - * @param _to Address of the recipient on L1. - * @param _amount Amount of ETH to withdraw. - * @param _extraData Optional data forwarded from L2. - */ + /// @custom:legacy + /// @notice Finalizes a withdrawal of ETH from L2. + /// @param _from Address of the withdrawer on L2. + /// @param _to Address of the recipient on L1. + /// @param _amount Amount of ETH to withdraw. + /// @param _extraData Optional data forwarded from L2. function finalizeETHWithdrawal( address _from, address _to, @@ -222,17 +189,14 @@ contract L1StandardBridge is StandardBridge, Semver { finalizeBridgeETH(_from, _to, _amount, _extraData); } - /** - * @custom:legacy - * @notice Finalizes a withdrawal of ERC20 tokens from L2. - * - * @param _l1Token Address of the token on L1. - * @param _l2Token Address of the corresponding token on L2. - * @param _from Address of the withdrawer on L2. - * @param _to Address of the recipient on L1. - * @param _amount Amount of the ERC20 to withdraw. - * @param _extraData Optional data forwarded from L2. - */ + /// @custom:legacy + /// @notice Finalizes a withdrawal of ERC20 tokens from L2. + /// @param _l1Token Address of the token on L1. + /// @param _l2Token Address of the corresponding token on L2. + /// @param _from Address of the withdrawer on L2. + /// @param _to Address of the recipient on L1. + /// @param _amount Amount of the ERC20 to withdraw. + /// @param _extraData Optional data forwarded from L2. function finalizeERC20Withdrawal( address _l1Token, address _l2Token, @@ -244,24 +208,18 @@ contract L1StandardBridge is StandardBridge, Semver { finalizeBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _extraData); } - /** - * @custom:legacy - * @notice Retrieves the access of the corresponding L2 bridge contract. - * - * @return Address of the corresponding L2 bridge contract. - */ + /// @custom:legacy + /// @notice Retrieves the access of the corresponding L2 bridge contract. + /// @return Address of the corresponding L2 bridge contract. function l2TokenBridge() external view returns (address) { return address(OTHER_BRIDGE); } - /** - * @notice Internal function for initiating an ETH deposit. - * - * @param _from Address of the sender on L1. - * @param _to Address of the recipient on L2. - * @param _minGasLimit Minimum gas limit for the deposit message on L2. - * @param _extraData Optional data to forward to L2. - */ + /// @notice Internal function for initiating an ETH deposit. + /// @param _from Address of the sender on L1. + /// @param _to Address of the recipient on L2. + /// @param _minGasLimit Minimum gas limit for the deposit message on L2. + /// @param _extraData Optional data to forward to L2. function _initiateETHDeposit( address _from, address _to, @@ -271,17 +229,14 @@ contract L1StandardBridge is StandardBridge, Semver { _initiateBridgeETH(_from, _to, msg.value, _minGasLimit, _extraData); } - /** - * @notice Internal function for initiating an ERC20 deposit. - * - * @param _l1Token Address of the L1 token being deposited. - * @param _l2Token Address of the corresponding token on L2. - * @param _from Address of the sender on L1. - * @param _to Address of the recipient on L2. - * @param _amount Amount of the ERC20 to deposit. - * @param _minGasLimit Minimum gas limit for the deposit message on L2. - * @param _extraData Optional data to forward to L2. - */ + /// @notice Internal function for initiating an ERC20 deposit. + /// @param _l1Token Address of the L1 token being deposited. + /// @param _l2Token Address of the corresponding token on L2. + /// @param _from Address of the sender on L1. + /// @param _to Address of the recipient on L2. + /// @param _amount Amount of the ERC20 to deposit. + /// @param _minGasLimit Minimum gas limit for the deposit message on L2. + /// @param _extraData Optional data to forward to L2. function _initiateERC20Deposit( address _l1Token, address _l2Token, @@ -294,12 +249,9 @@ contract L1StandardBridge is StandardBridge, Semver { _initiateBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _minGasLimit, _extraData); } - /** - * @notice Emits the legacy ETHDepositInitiated event followed by the ETHBridgeInitiated event. - * This is necessary for backwards compatibility with the legacy bridge. - * - * @inheritdoc StandardBridge - */ + /// @inheritdoc StandardBridge + /// @notice Emits the legacy ETHDepositInitiated event followed by the ETHBridgeInitiated event. + /// This is necessary for backwards compatibility with the legacy bridge. function _emitETHBridgeInitiated( address _from, address _to, @@ -310,12 +262,9 @@ contract L1StandardBridge is StandardBridge, Semver { super._emitETHBridgeInitiated(_from, _to, _amount, _extraData); } - /** - * @notice Emits the legacy ETHWithdrawalFinalized event followed by the ETHBridgeFinalized - * event. This is necessary for backwards compatibility with the legacy bridge. - * - * @inheritdoc StandardBridge - */ + /// @inheritdoc StandardBridge + /// @notice Emits the legacy ERC20DepositInitiated event followed by the ERC20BridgeInitiated + /// event. This is necessary for backwards compatibility with the legacy bridge. function _emitETHBridgeFinalized( address _from, address _to, @@ -326,12 +275,9 @@ contract L1StandardBridge is StandardBridge, Semver { super._emitETHBridgeFinalized(_from, _to, _amount, _extraData); } - /** - * @notice Emits the legacy ERC20DepositInitiated event followed by the ERC20BridgeInitiated - * event. This is necessary for backwards compatibility with the legacy bridge. - * - * @inheritdoc StandardBridge - */ + /// @inheritdoc StandardBridge + /// @notice Emits the legacy ERC20WithdrawalFinalized event followed by the ERC20BridgeFinalized + /// event. This is necessary for backwards compatibility with the legacy bridge. function _emitERC20BridgeInitiated( address _localToken, address _remoteToken, @@ -344,12 +290,9 @@ contract L1StandardBridge is StandardBridge, Semver { super._emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData); } - /** - * @notice Emits the legacy ERC20WithdrawalFinalized event followed by the ERC20BridgeFinalized - * event. This is necessary for backwards compatibility with the legacy bridge. - * - * @inheritdoc StandardBridge - */ + /// @inheritdoc StandardBridge + /// @notice Emits the legacy ERC20WithdrawalFinalized event followed by the ERC20BridgeFinalized + /// event. This is necessary for backwards compatibility with the legacy bridge. function _emitERC20BridgeFinalized( address _localToken, address _remoteToken, diff --git a/packages/contracts-bedrock/contracts/L1/L2OutputOracle.sol b/packages/contracts-bedrock/contracts/L1/L2OutputOracle.sol index e9a243796f46..f53fa939546f 100644 --- a/packages/contracts-bedrock/contracts/L1/L2OutputOracle.sol +++ b/packages/contracts-bedrock/contracts/L1/L2OutputOracle.sol @@ -5,63 +5,43 @@ import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable import { Semver } from "../universal/Semver.sol"; import { Types } from "../libraries/Types.sol"; -/** - * @custom:proxied - * @title L2OutputOracle - * @notice The L2OutputOracle contains an array of L2 state outputs, where each output is a - * commitment to the state of the L2 chain. Other contracts like the OptimismPortal use - * these outputs to verify information about the state of L2. - */ +/// @custom:proxied +/// @title L2OutputOracle +/// @notice The L2OutputOracle contains an array of L2 state outputs, where each output is a +/// commitment to the state of the L2 chain. Other contracts like the OptimismPortal use +/// these outputs to verify information about the state of L2. contract L2OutputOracle is Initializable, Semver { - /** - * @notice The interval in L2 blocks at which checkpoints must be submitted. Although this is - * immutable, it can safely be modified by upgrading the implementation contract. - */ + /// @notice The interval in L2 blocks at which checkpoints must be submitted. + /// Although this is immutable, it can safely be modified by upgrading the + /// implementation contract. uint256 public immutable SUBMISSION_INTERVAL; - /** - * @notice The time between L2 blocks in seconds. Once set, this value MUST NOT be modified. - */ + /// @notice The time between L2 blocks in seconds. Once set, this value MUST NOT be modified. uint256 public immutable L2_BLOCK_TIME; - /** - * @notice The address of the challenger. Can be updated via upgrade. - */ + /// @notice The address of the challenger. Can be updated via upgrade. address public immutable CHALLENGER; - /** - * @notice The address of the proposer. Can be updated via upgrade. - */ + /// @notice The address of the proposer. Can be updated via upgrade. address public immutable PROPOSER; - /** - * @notice Minimum time (in seconds) that must elapse before a withdrawal can be finalized. - */ + /// @notice The minimum time (in seconds) that must elapse before a withdrawal can be finalized. uint256 public immutable FINALIZATION_PERIOD_SECONDS; - /** - * @notice The number of the first L2 block recorded in this contract. - */ + /// @notice The number of the first L2 block recorded in this contract. uint256 public startingBlockNumber; - /** - * @notice The timestamp of the first L2 block recorded in this contract. - */ + /// @notice The timestamp of the first L2 block recorded in this contract. uint256 public startingTimestamp; - /** - * @notice Array of L2 output proposals. - */ + /// @notice An array of L2 output proposals. Types.OutputProposal[] internal l2Outputs; - /** - * @notice Emitted when an output is proposed. - * - * @param outputRoot The output root. - * @param l2OutputIndex The index of the output in the l2Outputs array. - * @param l2BlockNumber The L2 block number of the output root. - * @param l1Timestamp The L1 timestamp when proposed. - */ + /// @notice Emitted when an output is proposed. + /// @param outputRoot The output root. + /// @param l2OutputIndex The index of the output in the l2Outputs array. + /// @param l2BlockNumber The L2 block number of the output root. + /// @param l1Timestamp The L1 timestamp when proposed. event OutputProposed( bytes32 indexed outputRoot, uint256 indexed l2OutputIndex, @@ -69,24 +49,19 @@ contract L2OutputOracle is Initializable, Semver { uint256 l1Timestamp ); - /** - * @notice Emitted when outputs are deleted. - * - * @param prevNextOutputIndex Next L2 output index before the deletion. - * @param newNextOutputIndex Next L2 output index after the deletion. - */ + /// @notice Emitted when outputs are deleted. + /// @param prevNextOutputIndex Next L2 output index before the deletion. + /// @param newNextOutputIndex Next L2 output index after the deletion. event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex); - /** - * @custom:semver 1.3.0 - * - * @param _submissionInterval Interval in blocks at which checkpoints must be submitted. - * @param _l2BlockTime The time per L2 block, in seconds. - * @param _startingBlockNumber The number of the first L2 block. - * @param _startingTimestamp The timestamp of the first L2 block. - * @param _proposer The address of the proposer. - * @param _challenger The address of the challenger. - */ + /// @custom:semver 1.3.1 + /// @notice Constructs the L2OutputOracle contract. + /// @param _submissionInterval Interval in blocks at which checkpoints must be submitted. + /// @param _l2BlockTime The time per L2 block, in seconds. + /// @param _startingBlockNumber The number of the first L2 block. + /// @param _startingTimestamp The timestamp of the first L2 block. + /// @param _proposer The address of the proposer. + /// @param _challenger The address of the challenger. constructor( uint256 _submissionInterval, uint256 _l2BlockTime, @@ -95,7 +70,7 @@ contract L2OutputOracle is Initializable, Semver { address _proposer, address _challenger, uint256 _finalizationPeriodSeconds - ) Semver(1, 3, 0) { + ) Semver(1, 3, 1) { require(_l2BlockTime > 0, "L2OutputOracle: L2 block time must be greater than 0"); require( _submissionInterval > 0, @@ -111,12 +86,9 @@ contract L2OutputOracle is Initializable, Semver { initialize(_startingBlockNumber, _startingTimestamp); } - /** - * @notice Initializer. - * - * @param _startingBlockNumber Block number for the first recoded L2 block. - * @param _startingTimestamp Timestamp for the first recoded L2 block. - */ + /// @notice Initializer. + /// @param _startingBlockNumber Block number for the first recoded L2 block. + /// @param _startingTimestamp Timestamp for the first recoded L2 block. function initialize(uint256 _startingBlockNumber, uint256 _startingTimestamp) public initializer @@ -130,13 +102,10 @@ contract L2OutputOracle is Initializable, Semver { startingBlockNumber = _startingBlockNumber; } - /** - * @notice Deletes all output proposals after and including the proposal that corresponds to - * the given output index. Only the challenger address can delete outputs. - * - * @param _l2OutputIndex Index of the first L2 output to be deleted. All outputs after this - * output will also be deleted. - */ + /// @notice Deletes all output proposals after and including the proposal that corresponds to + /// the given output index. Only the challenger address can delete outputs. + /// @param _l2OutputIndex Index of the first L2 output to be deleted. + /// All outputs after this output will also be deleted. // solhint-disable-next-line ordering function deleteL2Outputs(uint256 _l2OutputIndex) external { require( @@ -166,16 +135,13 @@ contract L2OutputOracle is Initializable, Semver { emit OutputsDeleted(prevNextL2OutputIndex, _l2OutputIndex); } - /** - * @notice Accepts an outputRoot and the timestamp of the corresponding L2 block. The timestamp - * must be equal to the current value returned by `nextTimestamp()` in order to be - * accepted. This function may only be called by the Proposer. - * - * @param _outputRoot The L2 output of the checkpoint block. - * @param _l2BlockNumber The L2 block number that resulted in _outputRoot. - * @param _l1BlockHash A block hash which must be included in the current chain. - * @param _l1BlockNumber The block number with the specified block hash. - */ + /// @notice Accepts an outputRoot and the timestamp of the corresponding L2 block. + /// The timestamp must be equal to the current value returned by `nextTimestamp()` in + /// order to be accepted. This function may only be called by the Proposer. + /// @param _outputRoot The L2 output of the checkpoint block. + /// @param _l2BlockNumber The L2 block number that resulted in _outputRoot. + /// @param _l1BlockHash A block hash which must be included in the current chain. + /// @param _l1BlockNumber The block number with the specified block hash. function proposeL2Output( bytes32 _outputRoot, uint256 _l2BlockNumber, @@ -228,14 +194,9 @@ contract L2OutputOracle is Initializable, Semver { ); } - /** - * @notice Returns an output by index. Exists because Solidity's array access will return a - * tuple instead of a struct. - * - * @param _l2OutputIndex Index of the output to return. - * - * @return The output at the given index. - */ + /// @notice Returns an output by index. Needed to return a struct instead of a tuple. + /// @param _l2OutputIndex Index of the output to return. + /// @return The output at the given index. function getL2Output(uint256 _l2OutputIndex) external view @@ -244,14 +205,11 @@ contract L2OutputOracle is Initializable, Semver { return l2Outputs[_l2OutputIndex]; } - /** - * @notice Returns the index of the L2 output that checkpoints a given L2 block number. Uses a - * binary search to find the first output greater than or equal to the given block. - * - * @param _l2BlockNumber L2 block number to find a checkpoint for. - * - * @return Index of the first checkpoint that commits to the given L2 block number. - */ + /// @notice Returns the index of the L2 output that checkpoints a given L2 block number. + /// Uses a binary search to find the first output greater than or equal to the given + /// block. + /// @param _l2BlockNumber L2 block number to find a checkpoint for. + /// @return Index of the first checkpoint that commits to the given L2 block number. function getL2OutputIndexAfter(uint256 _l2BlockNumber) public view returns (uint256) { // Make sure an output for this block number has actually been proposed. require( @@ -280,14 +238,11 @@ contract L2OutputOracle is Initializable, Semver { return lo; } - /** - * @notice Returns the L2 output proposal that checkpoints a given L2 block number. Uses a - * binary search to find the first output greater than or equal to the given block. - * - * @param _l2BlockNumber L2 block number to find a checkpoint for. - * - * @return First checkpoint that commits to the given L2 block number. - */ + /// @notice Returns the L2 output proposal that checkpoints a given L2 block number. + /// Uses a binary search to find the first output greater than or equal to the given + /// block. + /// @param _l2BlockNumber L2 block number to find a checkpoint for. + /// @return First checkpoint that commits to the given L2 block number. function getL2OutputAfter(uint256 _l2BlockNumber) external view @@ -296,31 +251,23 @@ contract L2OutputOracle is Initializable, Semver { return l2Outputs[getL2OutputIndexAfter(_l2BlockNumber)]; } - /** - * @notice Returns the number of outputs that have been proposed. Will revert if no outputs - * have been proposed yet. - * - * @return The number of outputs that have been proposed. - */ + /// @notice Returns the number of outputs that have been proposed. + /// Will revert if no outputs have been proposed yet. + /// @return The number of outputs that have been proposed. function latestOutputIndex() external view returns (uint256) { return l2Outputs.length - 1; } - /** - * @notice Returns the index of the next output to be proposed. - * - * @return The index of the next output to be proposed. - */ + /// @notice Returns the index of the next output to be proposed. + /// @return The index of the next output to be proposed. function nextOutputIndex() public view returns (uint256) { return l2Outputs.length; } - /** - * @notice Returns the block number of the latest submitted L2 output proposal. If no proposals - * been submitted yet then this function will return the starting block number. - * - * @return Latest submitted L2 block number. - */ + /// @notice Returns the block number of the latest submitted L2 output proposal. + /// If no proposals been submitted yet then this function will return the starting + /// block number. + /// @return Latest submitted L2 block number. function latestBlockNumber() public view returns (uint256) { return l2Outputs.length == 0 @@ -328,22 +275,15 @@ contract L2OutputOracle is Initializable, Semver { : l2Outputs[l2Outputs.length - 1].l2BlockNumber; } - /** - * @notice Computes the block number of the next L2 block that needs to be checkpointed. - * - * @return Next L2 block number. - */ + /// @notice Computes the block number of the next L2 block that needs to be checkpointed. + /// @return Next L2 block number. function nextBlockNumber() public view returns (uint256) { return latestBlockNumber() + SUBMISSION_INTERVAL; } - /** - * @notice Returns the L2 timestamp corresponding to a given L2 block number. - * - * @param _l2BlockNumber The L2 block number of the target block. - * - * @return L2 timestamp of the given block. - */ + /// @notice Returns the L2 timestamp corresponding to a given L2 block number. + /// @param _l2BlockNumber The L2 block number of the target block. + /// @return L2 timestamp of the given block. function computeL2Timestamp(uint256 _l2BlockNumber) public view returns (uint256) { return startingTimestamp + ((_l2BlockNumber - startingBlockNumber) * L2_BLOCK_TIME); } diff --git a/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol b/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol index c42dd1c5b737..21adfed44c16 100644 --- a/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol +++ b/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol @@ -13,84 +13,60 @@ import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol"; import { ResourceMetering } from "./ResourceMetering.sol"; import { Semver } from "../universal/Semver.sol"; -/** - * @custom:proxied - * @title OptimismPortal - * @notice The OptimismPortal is a low-level contract responsible for passing messages between L1 - * and L2. Messages sent directly to the OptimismPortal have no form of replayability. - * Users are encouraged to use the L1CrossDomainMessenger for a higher-level interface. - */ +/// @custom:proxied +/// @title OptimismPortal +/// @notice The OptimismPortal is a low-level contract responsible for passing messages between L1 +/// and L2. Messages sent directly to the OptimismPortal have no form of replayability. +/// Users are encouraged to use the L1CrossDomainMessenger for a higher-level interface. contract OptimismPortal is Initializable, ResourceMetering, Semver { - /** - * @notice Represents a proven withdrawal. - * - * @custom:field outputRoot Root of the L2 output this was proven against. - * @custom:field timestamp Timestamp at whcih the withdrawal was proven. - * @custom:field l2OutputIndex Index of the output this was proven against. - */ + /// @notice Represents a proven withdrawal. + /// @custom:field outputRoot Root of the L2 output this was proven against. + /// @custom:field timestamp Timestamp at whcih the withdrawal was proven. + /// @custom:field l2OutputIndex Index of the output this was proven against. struct ProvenWithdrawal { bytes32 outputRoot; uint128 timestamp; uint128 l2OutputIndex; } - /** - * @notice Version of the deposit event. - */ + /// @notice Version of the deposit event. uint256 internal constant DEPOSIT_VERSION = 0; - /** - * @notice The L2 gas limit set when eth is deposited using the receive() function. - */ + /// @notice The L2 gas limit set when eth is deposited using the receive() function. uint64 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000; - /** - * @notice Address of the L2OutputOracle contract. - */ + /// @notice Address of the L2OutputOracle contract. L2OutputOracle public immutable L2_ORACLE; - /** - * @notice Address of the SystemConfig contract. - */ + /// @notice Address of the SystemConfig contract. SystemConfig public immutable SYSTEM_CONFIG; - /** - * @notice Address that has the ability to pause and unpause withdrawals. - */ + /// @notice Address that has the ability to pause and unpause withdrawals. address public immutable GUARDIAN; - /** - * @notice Address of the L2 account which initiated a withdrawal in this transaction. If the - * of this variable is the default L2 sender address, then we are NOT inside of a call - * to finalizeWithdrawalTransaction. - */ + /// @notice Address of the L2 account which initiated a withdrawal in this transaction. + /// If the of this variable is the default L2 sender address, then we are NOT inside of + /// a call to finalizeWithdrawalTransaction. address public l2Sender; - /** - * @notice A list of withdrawal hashes which have been successfully finalized. - */ + /// @notice A list of withdrawal hashes which have been successfully finalized. mapping(bytes32 => bool) public finalizedWithdrawals; - /** - * @notice A mapping of withdrawal hashes to `ProvenWithdrawal` data. - */ + /// @notice A mapping of withdrawal hashes to `ProvenWithdrawal` data. mapping(bytes32 => ProvenWithdrawal) public provenWithdrawals; - /** - * @notice Determines if cross domain messaging is paused. When set to true, - * withdrawals are paused. This may be removed in the future. - */ + /// @notice Determines if cross domain messaging is paused. + /// When set to true, withdrawals are paused. + /// This may be removed in the future. bool public paused; - /** - * @notice Emitted when a transaction is deposited from L1 to L2. The parameters of this event - * are read by the rollup node and used to derive deposit transactions on L2. - * - * @param from Address that triggered the deposit transaction. - * @param to Address that the deposit transaction is directed to. - * @param version Version of this deposit transaction event. - * @param opaqueData ABI encoded deposit data to be parsed off-chain. - */ + /// @notice Emitted when a transaction is deposited from L1 to L2. + /// The parameters of this event are read by the rollup node and used to derive deposit + /// transactions on L2. + /// @param from Address that triggered the deposit transaction. + /// @param to Address that the deposit transaction is directed to. + /// @param version Version of this deposit transaction event. + /// @param opaqueData ABI encoded deposit data to be parsed off-chain. event TransactionDeposited( address indexed from, address indexed to, @@ -98,130 +74,105 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { bytes opaqueData ); - /** - * @notice Emitted when a withdrawal transaction is proven. - * - * @param withdrawalHash Hash of the withdrawal transaction. - */ + /// @notice Emitted when a withdrawal transaction is proven. + /// @param withdrawalHash Hash of the withdrawal transaction. + /// @param from Address that triggered the withdrawal transaction. + /// @param to Address that the withdrawal transaction is directed to. event WithdrawalProven( bytes32 indexed withdrawalHash, address indexed from, address indexed to ); - /** - * @notice Emitted when a withdrawal transaction is finalized. - * - * @param withdrawalHash Hash of the withdrawal transaction. - * @param success Whether the withdrawal transaction was successful. - */ + /// @notice Emitted when a withdrawal transaction is finalized. + /// @param withdrawalHash Hash of the withdrawal transaction. + /// @param success Whether the withdrawal transaction was successful. event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success); - /** - * @notice Emitted when the pause is triggered. - * - * @param account Address of the account triggering the pause. - */ + /// @notice Emitted when the pause is triggered. + /// @param account Address of the account triggering the pause. event Paused(address account); - /** - * @notice Emitted when the pause is lifted. - * - * @param account Address of the account triggering the unpause. - */ + /// @notice Emitted when the pause is lifted. + /// @param account Address of the account triggering the unpause. event Unpaused(address account); - /** - * @notice Reverts when paused. - */ + /// @notice Reverts when paused. modifier whenNotPaused() { require(paused == false, "OptimismPortal: paused"); _; } - /** - * @custom:semver 1.7.0 - * - * @param _l2Oracle Address of the L2OutputOracle contract. - * @param _guardian Address that can pause deposits and withdrawals. - * @param _paused Sets the contract's pausability state. - * @param _config Address of the SystemConfig contract. - */ + /// @custom:semver 1.7.1 + /// @notice Constructs the OptimismPortal contract. + /// @param _l2Oracle Address of the L2OutputOracle contract. + /// @param _guardian Address that can pause deposits and withdrawals. + /// @param _paused Sets the contract's pausability state. + /// @param _config Address of the SystemConfig contract. constructor( L2OutputOracle _l2Oracle, address _guardian, bool _paused, SystemConfig _config - ) Semver(1, 7, 0) { + ) Semver(1, 7, 1) { L2_ORACLE = _l2Oracle; GUARDIAN = _guardian; SYSTEM_CONFIG = _config; initialize(_paused); } - /** - * @notice Initializer. - */ + /// @notice Initializer. function initialize(bool _paused) public initializer { l2Sender = Constants.DEFAULT_L2_SENDER; paused = _paused; __ResourceMetering_init(); } - /** - * @notice Pause deposits and withdrawals. - */ + /// @notice Pauses deposits and withdrawals. function pause() external { require(msg.sender == GUARDIAN, "OptimismPortal: only guardian can pause"); paused = true; emit Paused(msg.sender); } - /** - * @notice Unpause deposits and withdrawals. - */ + /// @notice Unpauses deposits and withdrawals. function unpause() external { require(msg.sender == GUARDIAN, "OptimismPortal: only guardian can unpause"); paused = false; emit Unpaused(msg.sender); } - /** - * @notice Computes the minimum gas limit for a deposit. The minimum gas limit - * linearly increases based on the size of the calldata. This is to prevent - * users from creating L2 resource usage without paying for it. This function - * can be used when interacting with the portal to ensure forwards compatibility. - * - */ + /// @notice Computes the minimum gas limit for a deposit. + /// The minimum gas limit linearly increases based on the size of the calldata. + /// This is to prevent users from creating L2 resource usage without paying for it. + /// This function can be used when interacting with the portal to ensure forwards + /// compatibility. + /// @param _byteCount Number of bytes in the calldata. + /// @return The minimum gas limit for a deposit. function minimumGasLimit(uint64 _byteCount) public pure returns (uint64) { return _byteCount * 16 + 21000; } - /** - * @notice Accepts value so that users can send ETH directly to this contract and have the - * funds be deposited to their address on L2. This is intended as a convenience - * function for EOAs. Contracts should call the depositTransaction() function directly - * otherwise any deposited funds will be lost due to address aliasing. - */ + /// @notice Accepts value so that users can send ETH directly to this contract and have the + /// funds be deposited to their address on L2. This is intended as a convenience + /// function for EOAs. Contracts should call the depositTransaction() function directly + /// otherwise any deposited funds will be lost due to address aliasing. // solhint-disable-next-line ordering receive() external payable { depositTransaction(msg.sender, msg.value, RECEIVE_DEFAULT_GAS_LIMIT, false, bytes("")); } - /** - * @notice Accepts ETH value without triggering a deposit to L2. This function mainly exists - * for the sake of the migration between the legacy Optimism system and Bedrock. - */ + /// @notice Accepts ETH value without triggering a deposit to L2. + /// This function mainly exists for the sake of the migration between the legacy + /// Optimism system and Bedrock. function donateETH() external payable { // Intentionally empty. } - /** - * @notice Getter for the resource config. Used internally by the ResourceMetering - * contract. The SystemConfig is the source of truth for the resource config. - * - * @return ResourceMetering.ResourceConfig - */ + /// @notice Getter for the resource config. + /// Used internally by the ResourceMetering contract. + /// The SystemConfig is the source of truth for the resource config. + /// @return ResourceMetering ResourceConfig function _resourceConfig() internal view @@ -231,14 +182,11 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { return SYSTEM_CONFIG.resourceConfig(); } - /** - * @notice Proves a withdrawal transaction. - * - * @param _tx Withdrawal transaction to finalize. - * @param _l2OutputIndex L2 output index to prove against. - * @param _outputRootProof Inclusion proof of the L2ToL1MessagePasser contract's storage root. - * @param _withdrawalProof Inclusion proof of the withdrawal in L2ToL1MessagePasser contract. - */ + /// @notice Proves a withdrawal transaction. + /// @param _tx Withdrawal transaction to finalize. + /// @param _l2OutputIndex L2 output index to prove against. + /// @param _outputRootProof Inclusion proof of the L2ToL1MessagePasser contract's storage root. + /// @param _withdrawalProof Inclusion proof of the withdrawal in L2ToL1MessagePasser contract. function proveWithdrawalTransaction( Types.WithdrawalTransaction memory _tx, uint256 _l2OutputIndex, @@ -317,11 +265,8 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { emit WithdrawalProven(withdrawalHash, _tx.sender, _tx.target); } - /** - * @notice Finalizes a withdrawal transaction. - * - * @param _tx Withdrawal transaction to finalize. - */ + /// @notice Finalizes a withdrawal transaction. + /// @param _tx Withdrawal transaction to finalize. function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external whenNotPaused @@ -419,18 +364,15 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { } } - /** - * @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in - * deriving deposit transactions. Note that if a deposit is made by a contract, its - * address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider - * using the CrossDomainMessenger contracts for a simpler developer experience. - * - * @param _to Target address on L2. - * @param _value ETH value to send to the recipient. - * @param _gasLimit Minimum L2 gas limit (can be greater than or equal to this value). - * @param _isCreation Whether or not the transaction is a contract creation. - * @param _data Data to trigger the recipient with. - */ + /// @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in + /// deriving deposit transactions. Note that if a deposit is made by a contract, its + /// address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider + /// using the CrossDomainMessenger contracts for a simpler developer experience. + /// @param _to Target address on L2. + /// @param _value ETH value to send to the recipient. + /// @param _gasLimit Minimum L2 gas limit (can be greater than or equal to this value). + /// @param _isCreation Whether or not the transaction is a contract creation. + /// @param _data Data to trigger the recipient with. function depositTransaction( address _to, uint256 _value, @@ -482,25 +424,19 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData); } - /** - * @notice Determine if a given output is finalized. Reverts if the call to - * L2_ORACLE.getL2Output reverts. Returns a boolean otherwise. - * - * @param _l2OutputIndex Index of the L2 output to check. - * - * @return Whether or not the output is finalized. - */ + /// @notice Determine if a given output is finalized. + /// Reverts if the call to L2_ORACLE.getL2Output reverts. + /// Returns a boolean otherwise. + /// @param _l2OutputIndex Index of the L2 output to check. + /// @return Whether or not the output is finalized. function isOutputFinalized(uint256 _l2OutputIndex) external view returns (bool) { return _isFinalizationPeriodElapsed(L2_ORACLE.getL2Output(_l2OutputIndex).timestamp); } - /** - * @notice Determines whether the finalization period has elapsed w/r/t a given timestamp. - * - * @param _timestamp Timestamp to check. - * - * @return Whether or not the finalization period has elapsed. - */ + /// @notice Determines whether the finalization period has elapsed with respect to + /// the provided block timestamp. + /// @param _timestamp Timestamp to check. + /// @return Whether or not the finalization period has elapsed. function _isFinalizationPeriodElapsed(uint256 _timestamp) internal view returns (bool) { return block.timestamp > _timestamp + L2_ORACLE.FINALIZATION_PERIOD_SECONDS(); } diff --git a/packages/contracts-bedrock/contracts/L1/ResourceMetering.sol b/packages/contracts-bedrock/contracts/L1/ResourceMetering.sol index 8a50079a662c..4896090da2d0 100644 --- a/packages/contracts-bedrock/contracts/L1/ResourceMetering.sol +++ b/packages/contracts-bedrock/contracts/L1/ResourceMetering.sol @@ -6,48 +6,40 @@ import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { Burn } from "../libraries/Burn.sol"; import { Arithmetic } from "../libraries/Arithmetic.sol"; -/** - * @custom:upgradeable - * @title ResourceMetering - * @notice ResourceMetering implements an EIP-1559 style resource metering system where pricing - * updates automatically based on current demand. - */ +/// @custom:upgradeable +/// @title ResourceMetering +/// @notice ResourceMetering implements an EIP-1559 style resource metering system where pricing +/// updates automatically based on current demand. abstract contract ResourceMetering is Initializable { - /** - * @notice Represents the various parameters that control the way in which resources are - * metered. Corresponds to the EIP-1559 resource metering system. - * - * @custom:field prevBaseFee Base fee from the previous block(s). - * @custom:field prevBoughtGas Amount of gas bought so far in the current block. - * @custom:field prevBlockNum Last block number that the base fee was updated. - */ + /// @notice Represents the various parameters that control the way in which resources are + /// metered. Corresponds to the EIP-1559 resource metering system. + /// @custom:field prevBaseFee Base fee from the previous block(s). + /// @custom:field prevBoughtGas Amount of gas bought so far in the current block. + /// @custom:field prevBlockNum Last block number that the base fee was updated. struct ResourceParams { uint128 prevBaseFee; uint64 prevBoughtGas; uint64 prevBlockNum; } - /** - * @notice Represents the configuration for the EIP-1559 based curve for the deposit gas - * market. These values should be set with care as it is possible to set them in - * a way that breaks the deposit gas market. The target resource limit is defined as - * maxResourceLimit / elasticityMultiplier. This struct was designed to fit within a - * single word. There is additional space for additions in the future. - * - * @custom:field maxResourceLimit Represents the maximum amount of deposit gas that - * can be purchased per block. - * @custom:field elasticityMultiplier Determines the target resource limit along with - * the resource limit. - * @custom:field baseFeeMaxChangeDenominator Determines max change on fee per block. - * @custom:field minimumBaseFee The min deposit base fee, it is clamped to this - * value. - * @custom:field systemTxMaxGas The amount of gas supplied to the system - * transaction. This should be set to the same number - * that the op-node sets as the gas limit for the - * system transaction. - * @custom:field maximumBaseFee The max deposit base fee, it is clamped to this - * value. - */ + /// @notice Represents the configuration for the EIP-1559 based curve for the deposit gas + /// market. These values should be set with care as it is possible to set them in + /// a way that breaks the deposit gas market. The target resource limit is defined as + /// maxResourceLimit / elasticityMultiplier. This struct was designed to fit within a + /// single word. There is additional space for additions in the future. + /// @custom:field maxResourceLimit Represents the maximum amount of deposit gas that + /// can be purchased per block. + /// @custom:field elasticityMultiplier Determines the target resource limit along with + /// the resource limit. + /// @custom:field baseFeeMaxChangeDenominator Determines max change on fee per block. + /// @custom:field minimumBaseFee The min deposit base fee, it is clamped to this + /// value. + /// @custom:field systemTxMaxGas The amount of gas supplied to the system + /// transaction. This should be set to the same + /// number that the op-node sets as the gas limit + /// for the system transaction. + /// @custom:field maximumBaseFee The max deposit base fee, it is clamped to this + /// value. struct ResourceConfig { uint32 maxResourceLimit; uint8 elasticityMultiplier; @@ -57,21 +49,14 @@ abstract contract ResourceMetering is Initializable { uint128 maximumBaseFee; } - /** - * @notice EIP-1559 style gas parameters. - */ + /// @notice EIP-1559 style gas parameters. ResourceParams public params; - /** - * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades. - */ + /// @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades. uint256[48] private __gap; - /** - * @notice Meters access to a function based an amount of a requested resource. - * - * @param _amount Amount of the resource requested. - */ + /// @notice 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(); @@ -83,12 +68,9 @@ abstract contract ResourceMetering is Initializable { _metered(_amount, initialGas); } - /** - * @notice An internal function that holds all of the logic for metering a resource. - * - * @param _amount Amount of the resource requested. - * @param _initialGas The amount of gas before any modifier execution. - */ + /// @notice An internal function that holds all of the logic for metering a resource. + /// @param _amount Amount of the resource requested. + /// @param _initialGas The amount of gas before any modifier execution. function _metered(uint64 _amount, uint256 _initialGas) internal { // Update block number and base fee if necessary. uint256 blockDiff = block.number - params.prevBlockNum; @@ -163,18 +145,14 @@ abstract contract ResourceMetering is Initializable { } } - /** - * @notice Virtual function that returns the resource config. Contracts that inherit this - * contract must implement this function. - * - * @return ResourceConfig - */ + /// @notice Virtual function that returns the resource config. + /// Contracts that inherit this contract must implement this function. + /// @return ResourceConfig function _resourceConfig() internal virtual returns (ResourceConfig memory); - /** - * @notice Sets initial resource parameter values. This function must either be called by the - * initializer function of an upgradeable child contract. - */ + /// @notice Sets initial resource parameter values. + /// This function must either be called by the initializer function of an upgradeable + /// child contract. // solhint-disable-next-line func-name-mixedcase function __ResourceMetering_init() internal onlyInitializing { params = ResourceParams({ diff --git a/packages/contracts-bedrock/contracts/L1/SystemConfig.sol b/packages/contracts-bedrock/contracts/L1/SystemConfig.sol index e97e743b124d..2cb02b12bb67 100644 --- a/packages/contracts-bedrock/contracts/L1/SystemConfig.sol +++ b/packages/contracts-bedrock/contracts/L1/SystemConfig.sol @@ -7,22 +7,17 @@ import { import { Semver } from "../universal/Semver.sol"; import { ResourceMetering } from "./ResourceMetering.sol"; -/** - * @title SystemConfig - * @notice The SystemConfig contract is used to manage configuration of an Optimism network. All - * configuration is stored on L1 and picked up by L2 as part of the derviation of the L2 - * chain. - */ +/// @title SystemConfig +/// @notice The SystemConfig contract is used to manage configuration of an Optimism network. +/// All configuration is stored on L1 and picked up by L2 as part of the derviation of +/// the L2 chain. contract SystemConfig is OwnableUpgradeable, Semver { - /** - * @notice Enum representing different types of updates. - * - * @custom:value BATCHER Represents an update to the batcher hash. - * @custom:value GAS_CONFIG Represents an update to txn fee config on L2. - * @custom:value GAS_LIMIT Represents an update to gas limit on L2. - * @custom:value UNSAFE_BLOCK_SIGNER Represents an update to the signer key for unsafe - * block distrubution. - */ + /// @notice Enum representing different types of updates. + /// @custom:value BATCHER Represents an update to the batcher hash. + /// @custom:value GAS_CONFIG Represents an update to txn fee config on L2. + /// @custom:value GAS_LIMIT Represents an update to gas limit on L2. + /// @custom:value UNSAFE_BLOCK_SIGNER Represents an update to the signer key for unsafe + /// block distrubution. enum UpdateType { BATCHER, GAS_CONFIG, @@ -30,66 +25,49 @@ contract SystemConfig is OwnableUpgradeable, Semver { UNSAFE_BLOCK_SIGNER } - /** - * @notice Version identifier, used for upgrades. - */ + /// @notice Version identifier, used for upgrades. uint256 public constant VERSION = 0; - /** - * @notice Storage slot that the unsafe block signer is stored at. Storing it at this - * deterministic storage slot allows for decoupling the storage layout from the way - * that `solc` lays out storage. The `op-node` uses a storage proof to fetch this value. - */ + /// @notice Storage slot that the unsafe block signer is stored at. + /// Storing it at this deterministic storage slot allows for decoupling the storage + /// layout from the way that `solc` lays out storage. The `op-node` uses a storage + /// proof to fetch this value. bytes32 public constant UNSAFE_BLOCK_SIGNER_SLOT = keccak256("systemconfig.unsafeblocksigner"); - /** - * @notice Fixed L2 gas overhead. Used as part of the L2 fee calculation. - */ + /// @notice Fixed L2 gas overhead. Used as part of the L2 fee calculation. uint256 public overhead; - /** - * @notice Dynamic L2 gas overhead. Used as part of the L2 fee calculation. - */ + /// @notice Dynamic L2 gas overhead. Used as part of the L2 fee calculation. uint256 public scalar; - /** - * @notice Identifier for the batcher. For version 1 of this configuration, this is represented - * as an address left-padded with zeros to 32 bytes. - */ + /// @notice Identifier for the batcher. + /// For version 1 of this configuration, this is represented as an address left-padded + /// with zeros to 32 bytes. bytes32 public batcherHash; - /** - * @notice L2 block gas limit. - */ + /// @notice L2 block gas limit. uint64 public gasLimit; - /** - * @notice The configuration for the deposit fee market. Used by the OptimismPortal - * to meter the cost of buying L2 gas on L1. Set as internal and wrapped with a getter - * so that the struct is returned instead of a tuple. - */ + /// @notice The configuration for the deposit fee market. + /// Used by the OptimismPortal to meter the cost of buying L2 gas on L1. + /// Set as internal with a getter so that the struct is returned instead of a tuple. ResourceMetering.ResourceConfig internal _resourceConfig; - /** - * @notice Emitted when configuration is updated - * - * @param version SystemConfig version. - * @param updateType Type of update. - * @param data Encoded update data. - */ + /// @notice Emitted when configuration is updated. + /// @param version SystemConfig version. + /// @param updateType Type of update. + /// @param data Encoded update data. event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); - /** - * @custom:semver 1.3.0 - * - * @param _owner Initial owner of the contract. - * @param _overhead Initial overhead value. - * @param _scalar Initial scalar value. - * @param _batcherHash Initial batcher hash. - * @param _gasLimit Initial gas limit. - * @param _unsafeBlockSigner Initial unsafe block signer address. - * @param _config Initial resource config. - */ + /// @custom:semver 1.3.1 + /// @notice Constructs the SystemConfig contract. + /// @param _owner Initial owner of the contract. + /// @param _overhead Initial overhead value. + /// @param _scalar Initial scalar value. + /// @param _batcherHash Initial batcher hash. + /// @param _gasLimit Initial gas limit. + /// @param _unsafeBlockSigner Initial unsafe block signer address. + /// @param _config Initial resource config. constructor( address _owner, uint256 _overhead, @@ -98,7 +76,7 @@ contract SystemConfig is OwnableUpgradeable, Semver { uint64 _gasLimit, address _unsafeBlockSigner, ResourceMetering.ResourceConfig memory _config - ) Semver(1, 3, 0) { + ) Semver(1, 3, 1) { initialize({ _owner: _owner, _overhead: _overhead, @@ -110,18 +88,15 @@ contract SystemConfig is OwnableUpgradeable, Semver { }); } - /** - * @notice Initializer. The resource config must be set before the - * require check. - * - * @param _owner Initial owner of the contract. - * @param _overhead Initial overhead value. - * @param _scalar Initial scalar value. - * @param _batcherHash Initial batcher hash. - * @param _gasLimit Initial gas limit. - * @param _unsafeBlockSigner Initial unsafe block signer address. - * @param _config Initial ResourceConfig. - */ + /// @notice Initializer. + /// The resource config must be set before the require check. + /// @param _owner Initial owner of the contract. + /// @param _overhead Initial overhead value. + /// @param _scalar Initial scalar value. + /// @param _batcherHash Initial batcher hash. + /// @param _gasLimit Initial gas limit. + /// @param _unsafeBlockSigner Initial unsafe block signer address. + /// @param _config Initial ResourceConfig. function initialize( address _owner, uint256 _overhead, @@ -142,26 +117,20 @@ contract SystemConfig is OwnableUpgradeable, Semver { require(_gasLimit >= minimumGasLimit(), "SystemConfig: gas limit too low"); } - /** - * @notice Returns the minimum L2 gas limit that can be safely set for the system to - * operate. The L2 gas limit must be larger than or equal to the amount of - * gas that is allocated for deposits per block plus the amount of gas that - * is allocated for the system transaction. - * This function is used to determine if changes to parameters are safe. - * - * @return uint64 - */ + /// @notice Returns the minimum L2 gas limit that can be safely set for the system to + /// operate. The L2 gas limit must be larger than or equal to the amount of + /// gas that is allocated for deposits per block plus the amount of gas that + /// is allocated for the system transaction. + /// This function is used to determine if changes to parameters are safe. + /// @return uint64 Minimum gas limit. function minimumGasLimit() public view returns (uint64) { return uint64(_resourceConfig.maxResourceLimit) + uint64(_resourceConfig.systemTxMaxGas); } - /** - * @notice High level getter for the unsafe block signer address. Unsafe blocks can be - * propagated across the p2p network if they are signed by the key corresponding to - * this address. - * - * @return Address of the unsafe block signer. - */ + /// @notice High level getter for the unsafe block signer address. + /// Unsafe blocks can be propagated across the p2p network if they are signed by the + /// key corresponding to this address. + /// @return Address of the unsafe block signer. // solhint-disable-next-line ordering function unsafeBlockSigner() external view returns (address) { address addr; @@ -172,11 +141,8 @@ contract SystemConfig is OwnableUpgradeable, Semver { return addr; } - /** - * @notice Updates the unsafe block signer address. - * - * @param _unsafeBlockSigner New unsafe block signer address. - */ + /// @notice Updates the unsafe block signer address. + /// @param _unsafeBlockSigner New unsafe block signer address. function setUnsafeBlockSigner(address _unsafeBlockSigner) external onlyOwner { _setUnsafeBlockSigner(_unsafeBlockSigner); @@ -184,11 +150,8 @@ contract SystemConfig is OwnableUpgradeable, Semver { emit ConfigUpdate(VERSION, UpdateType.UNSAFE_BLOCK_SIGNER, data); } - /** - * @notice Updates the batcher hash. - * - * @param _batcherHash New batcher hash. - */ + /// @notice Updates the batcher hash. + /// @param _batcherHash New batcher hash. function setBatcherHash(bytes32 _batcherHash) external onlyOwner { batcherHash = _batcherHash; @@ -196,12 +159,9 @@ contract SystemConfig is OwnableUpgradeable, Semver { emit ConfigUpdate(VERSION, UpdateType.BATCHER, data); } - /** - * @notice Updates gas config. - * - * @param _overhead New overhead value. - * @param _scalar New scalar value. - */ + /// @notice Updates gas config. + /// @param _overhead New overhead value. + /// @param _scalar New scalar value. function setGasConfig(uint256 _overhead, uint256 _scalar) external onlyOwner { overhead = _overhead; scalar = _scalar; @@ -210,11 +170,8 @@ contract SystemConfig is OwnableUpgradeable, Semver { emit ConfigUpdate(VERSION, UpdateType.GAS_CONFIG, data); } - /** - * @notice Updates the L2 gas limit. - * - * @param _gasLimit New gas limit. - */ + /// @notice Updates the L2 gas limit. + /// @param _gasLimit New gas limit. function setGasLimit(uint64 _gasLimit) external onlyOwner { require(_gasLimit >= minimumGasLimit(), "SystemConfig: gas limit too low"); gasLimit = _gasLimit; @@ -223,12 +180,10 @@ contract SystemConfig is OwnableUpgradeable, Semver { emit ConfigUpdate(VERSION, UpdateType.GAS_LIMIT, data); } - /** - * @notice Low level setter for the unsafe block signer address. This function exists to - * deduplicate code around storing the unsafeBlockSigner address in storage. - * - * @param _unsafeBlockSigner New unsafeBlockSigner value. - */ + /// @notice Low level setter for the unsafe block signer address. + /// This function exists to deduplicate code around storing the unsafeBlockSigner + /// address in storage. + /// @param _unsafeBlockSigner New unsafeBlockSigner value. function _setUnsafeBlockSigner(address _unsafeBlockSigner) internal { bytes32 slot = UNSAFE_BLOCK_SIGNER_SLOT; assembly { @@ -236,33 +191,24 @@ contract SystemConfig is OwnableUpgradeable, Semver { } } - /** - * @notice A getter for the resource config. Ensures that the struct is - * returned instead of a tuple. - * - * @return ResourceConfig - */ + /// @notice A getter for the resource config. + /// Ensures that the struct is returned instead of a tuple. + /// @return ResourceConfig function resourceConfig() external view returns (ResourceMetering.ResourceConfig memory) { return _resourceConfig; } - /** - * @notice An external setter for the resource config. In the future, this - * method may emit an event that the `op-node` picks up for when the - * resource config is changed. - * - * @param _config The new resource config values. - */ + /// @notice An external setter for the resource config. + /// In the future, this method may emit an event that the `op-node` picks up + /// for when the resource config is changed. + /// @param _config The new resource config values. function setResourceConfig(ResourceMetering.ResourceConfig memory _config) external onlyOwner { _setResourceConfig(_config); } - /** - * @notice An internal setter for the resource config. Ensures that the - * config is sane before storing it by checking for invariants. - * - * @param _config The new resource config. - */ + /// @notice An internal setter for the resource config. + /// Ensures that the config is sane before storing it by checking for invariants. + /// @param _config The new resource config. function _setResourceConfig(ResourceMetering.ResourceConfig memory _config) internal { // Min base fee must be less than or equal to max base fee. require( diff --git a/packages/contracts-bedrock/contracts/dispute/DisputeGameFactory.sol b/packages/contracts-bedrock/contracts/dispute/DisputeGameFactory.sol index 42ed4875a7a5..0582620c5532 100644 --- a/packages/contracts-bedrock/contracts/dispute/DisputeGameFactory.sol +++ b/packages/contracts-bedrock/contracts/dispute/DisputeGameFactory.sol @@ -13,73 +13,53 @@ import { IDisputeGame } from "./interfaces/IDisputeGame.sol"; import { IDisputeGameFactory } from "./interfaces/IDisputeGameFactory.sol"; import { IVersioned } from "./interfaces/IVersioned.sol"; -/** - * @title DisputeGameFactory - * @notice A factory contract for creating `IDisputeGame` contracts. All created dispute games - * are stored in both a mapping and an append only array. The timestamp of the creation - * time of the dispute game is packed tightly into the storage slot with the address of - * the dispute game. This is to make offchain discoverability of playable dispute games - * easier. - */ +/// @title DisputeGameFactory +/// @notice A factory contract for creating `IDisputeGame` contracts. All created dispute games +/// are stored in both a mapping and an append only array. The timestamp of the creation +/// time of the dispute game is packed tightly into the storage slot with the address of +/// the dispute game. This is to make offchain discoverability of playable dispute games +/// easier. contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersioned { - /** - * @dev Allows for the creation of clone proxies with immutable arguments. - */ + /// @dev Allows for the creation of clone proxies with immutable arguments. using ClonesWithImmutableArgs for address; - /** - * @inheritdoc IDisputeGameFactory - */ + /// @inheritdoc IDisputeGameFactory mapping(GameType => IDisputeGame) public gameImpls; - /** - * @notice Mapping of a hash of `gameType || rootClaim || extraData` to - * the deployed `IDisputeGame` clone. - * @dev Note: `||` denotes concatenation. - */ + /// @notice Mapping of a hash of `gameType || rootClaim || extraData` to + /// the deployed `IDisputeGame` clone. + /// @dev Note: `||` denotes concatenation. mapping(Hash => GameId) internal _disputeGames; - /** - * @notice An append-only array of disputeGames that have been created. - * @dev This accessor is used by offchain game solvers to efficiently - * track dispute games - */ + /// @notice an append-only array of disputeGames that have been created. + /// @dev this accessor is used by offchain game solvers to efficiently + /// track dispute games GameId[] internal _disputeGameList; - /** - * @notice Constructs a new DisputeGameFactory contract. - */ + /// @notice constructs a new DisputeGameFactory contract. constructor() OwnableUpgradeable() { initialize(address(0)); } - /** - * @notice Initializes the contract. - * @param _owner The owner of the contract. - */ + /// @notice Initializes the contract. + /// @param _owner The owner of the contract. function initialize(address _owner) public initializer { __Ownable_init(); _transferOwnership(_owner); } - /** - * @inheritdoc IVersioned - * @custom:semver 0.0.2 - */ + /// @inheritdoc IVersioned + /// @custom:semver 0.0.2 function version() external pure returns (string memory) { return "0.0.2"; } - /** - * @inheritdoc IDisputeGameFactory - */ + /// @inheritdoc IDisputeGameFactory function gameCount() external view returns (uint256 gameCount_) { gameCount_ = _disputeGameList.length; } - /** - * @inheritdoc IDisputeGameFactory - */ + /// @inheritdoc IDisputeGameFactory function games( GameType _gameType, Claim _rootClaim, @@ -92,9 +72,7 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion timestamp_ = timestamp; } - /** - * @inheritdoc IDisputeGameFactory - */ + /// @inheritdoc IDisputeGameFactory function gameAtIndex(uint256 _index) external view @@ -106,9 +84,7 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion timestamp_ = timestamp; } - /** - * @inheritdoc IDisputeGameFactory - */ + /// @inheritdoc IDisputeGameFactory function create( GameType gameType, Claim rootClaim, @@ -142,9 +118,7 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion emit DisputeGameCreated(address(proxy), gameType, rootClaim); } - /** - * @inheritdoc IDisputeGameFactory - */ + /// @inheritdoc IDisputeGameFactory function getGameUUID( GameType gameType, Claim rootClaim, @@ -181,27 +155,21 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, IVersion } } - /** - * @inheritdoc IDisputeGameFactory - */ + /// @inheritdoc IDisputeGameFactory function setImplementation(GameType gameType, IDisputeGame impl) external onlyOwner { gameImpls[gameType] = impl; emit ImplementationSet(address(impl), gameType); } - /** - * @dev Packs an address and a uint256 into a single bytes32 slot. This - * is only safe for up to uint96 values. - */ + /// @dev Packs an address and a uint256 into a single bytes32 slot. This + /// is only safe for up to uint96 values. function _packSlot(address _addr, uint256 _num) internal pure returns (GameId slot_) { assembly { slot_ := or(shl(0xa0, _num), _addr) } } - /** - * @dev Unpacks an address and a uint256 from a single bytes32 slot. - */ + /// @dev Unpacks an address and a uint256 from a single bytes32 slot. function _unpackSlot(GameId _slot) internal pure returns (address addr_, uint256 num_) { assembly { addr_ := and(_slot, 0xffffffffffffffffffffffffffffffffffffffff) diff --git a/packages/contracts-bedrock/contracts/dispute/FaultDisputeGame.sol b/packages/contracts-bedrock/contracts/dispute/FaultDisputeGame.sol index 8b8646dd104f..2eac348fa435 100644 --- a/packages/contracts-bedrock/contracts/dispute/FaultDisputeGame.sol +++ b/packages/contracts-bedrock/contracts/dispute/FaultDisputeGame.sol @@ -15,101 +15,147 @@ import { LibClock } from "./lib/LibClock.sol"; import "../libraries/DisputeTypes.sol"; import "../libraries/DisputeErrors.sol"; -/** - * @title FaultDisputeGame - * @notice An implementation of the `IFaultDisputeGame` interface. - */ +/// @title FaultDisputeGame +/// @notice An implementation of the `IFaultDisputeGame` interface. contract FaultDisputeGame is IFaultDisputeGame, Clone { //////////////////////////////////////////////////////////////// // State Vars // //////////////////////////////////////////////////////////////// - /** - * @notice The current Semver of the FaultDisputeGame implementation. - */ - string internal constant VERSION = "0.0.1"; + /// @notice The absolute prestate of the instruction trace. This is a constant that is defined + /// by the program that is being used to execute the trace. + Claim public immutable ABSOLUTE_PRESTATE; - /** - * @notice The max depth of the game. - */ - uint256 internal constant MAX_GAME_DEPTH = 63; + /// @notice The max depth of the game. + uint256 public immutable MAX_GAME_DEPTH; - /** - * @notice The duration of the game. - * @dev TODO: Account for resolution buffer. (?) - */ + /// @notice The duration of the game. + /// @dev TODO: Account for resolution buffer. (?) Duration internal constant GAME_DURATION = Duration.wrap(7 days); - /** - * @notice The root claim's position is always at gindex 1. - */ + /// @notice The root claim's position is always at gindex 1. Position internal constant ROOT_POSITION = Position.wrap(1); - /** - * @notice The starting timestamp of the game - */ + /// @notice The current Semver of the FaultDisputeGame implementation. + string internal constant VERSION = "0.0.2"; + + /// @notice The starting timestamp of the game Timestamp public gameStart; - /** - * @inheritdoc IDisputeGame - */ + /// @inheritdoc IDisputeGame GameStatus public status; - /** - * @inheritdoc IDisputeGame - */ + /// @inheritdoc IDisputeGame IBondManager public bondManager; - /** - * @notice An append-only array of all claims made during the dispute game. - */ + /// @notice An append-only array of all claims made during the dispute game. ClaimData[] public claimData; - /** - * @notice An internal mapping to allow for constant-time lookups of existing claims. - */ + /// @notice An internal mapping to allow for constant-time lookups of existing claims. mapping(ClaimHash => bool) internal claims; + /// @param _absolutePrestate The absolute prestate of the instruction trace. + constructor(Claim _absolutePrestate, uint256 _maxGameDepth) { + ABSOLUTE_PRESTATE = _absolutePrestate; + MAX_GAME_DEPTH = _maxGameDepth; + } + //////////////////////////////////////////////////////////////// // External Logic // //////////////////////////////////////////////////////////////// - /** - * @inheritdoc IFaultDisputeGame - */ + /// @inheritdoc IFaultDisputeGame function attack(uint256 _parentIndex, Claim _pivot) external payable { _move(_parentIndex, _pivot, true); } - /** - * @inheritdoc IFaultDisputeGame - */ + /// @inheritdoc IFaultDisputeGame function defend(uint256 _parentIndex, Claim _pivot) external payable { _move(_parentIndex, _pivot, false); } - /** - * @inheritdoc IFaultDisputeGame - */ + /// @inheritdoc IFaultDisputeGame function step( - uint256 _prestateIndex, - uint256 _parentIndex, - bytes calldata _stateData, - bytes calldata _proof + uint256 _stateIndex, + uint256 _claimIndex, + bool _isAttack, + bytes calldata, + bytes calldata ) external { - // TODO - Call the VM to perform the execution step. + // Steps cannot be made unless the game is currently in progress. + if (status != GameStatus.IN_PROGRESS) { + revert GameNotInProgress(); + } + + // Get the parent. If it does not exist, the call will revert with OOB. + ClaimData storage parent = claimData[_claimIndex]; + + // Pull the parent position out of storage. + Position parentPos = parent.position; + // Determine the position of the step. + Position stepPos = parentPos.move(_isAttack); + + // Ensure that the step position is 1 deeper than the maximum game depth. + if (stepPos.depth() != MAX_GAME_DEPTH + 1) { + revert InvalidParent(); + } + + // Determine the expected pre & post states of the step. + Claim preStateClaim; + Claim postStateClaim; + if (stepPos.indexAtDepth() == 0) { + // If the step position's index at depth is 0, the prestate is the absolute prestate + // and the post state is the parent claim. + preStateClaim = ABSOLUTE_PRESTATE; + postStateClaim = claimData[_claimIndex].claim; + } else { + Position preStatePos; + Position postStatePos; + if (_isAttack) { + // If the step is an attack, the prestate exists elsewhere in the game state, + // and the parent claim is the expected post-state. + preStatePos = claimData[_stateIndex].position; + preStateClaim = claimData[_stateIndex].claim; + postStatePos = parentPos; + postStateClaim = parent.claim; + } else { + // If the step is a defense, the poststate exists elsewhere in the game state, + // and the parent claim is the expected pre-state. + preStatePos = parent.position; + preStateClaim = parent.claim; + postStatePos = claimData[_stateIndex].position; + postStateClaim = claimData[_stateIndex].claim; + } + + // Assert that the given prestate commits to the instruction at `gindex - 1`. + if ( + Position.unwrap(preStatePos.rightIndex(MAX_GAME_DEPTH)) != + Position.unwrap(postStatePos.rightIndex(MAX_GAME_DEPTH)) - 1 + ) { + revert InvalidPrestate(); + } + } + + // TODO: Call `MIPS.sol#step` to verify the step. + // For now, we just use a simple state transition function that increments the prestate, + // `s_p`, by 1. + if (uint256(Claim.unwrap(preStateClaim)) + 1 == uint256(Claim.unwrap(postStateClaim))) { + revert ValidStep(); + } + + // Set the parent claim as countered. We do not need to append a new claim to the game; + // instead, we can just set the existing parent as countered. + parent.countered = true; } //////////////////////////////////////////////////////////////// // Internal Logic // //////////////////////////////////////////////////////////////// - /** - * @notice Internal move function, used by both `attack` and `defend`. - * @param _challengeIndex The index of the claim being moved against. - * @param _pivot The claim at the next logical position in the game. - * @param _isAttack Whether or not the move is an attack or defense. - */ + /// @notice Internal move function, used by both `attack` and `defend`. + /// @param _challengeIndex The index of the claim being moved against. + /// @param _pivot The claim at the next logical position in the game. + /// @param _isAttack Whether or not the move is an attack or defense. function _move( uint256 _challengeIndex, Claim _pivot, @@ -136,12 +182,12 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone { // Compute the position that the claim commits to. Because the parent's position is already // known, we can compute the next position by moving left or right depending on whether // or not the move is an attack or defense. - Position nextPosition = _isAttack ? parent.position.attack() : parent.position.defend(); + Position nextPosition = parent.position.move(_isAttack); // At the leaf nodes of the game, the only option is to run a step to prove or disprove // the above claim. At this depth, the parent claim commits to the state after a single // instruction step. - if (nextPosition.depth() >= MAX_GAME_DEPTH) { + if (nextPosition.depth() > MAX_GAME_DEPTH) { revert GameDepthExceeded(); } @@ -197,39 +243,38 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone { emit Move(_challengeIndex, _pivot, msg.sender); } + /// @inheritdoc IFaultDisputeGame + function l2BlockNumber() public pure returns (uint256 l2BlockNumber_) { + l2BlockNumber_ = _getArgUint256(0x20); + } + //////////////////////////////////////////////////////////////// // `IDisputeGame` impl // //////////////////////////////////////////////////////////////// - /** - * @inheritdoc IDisputeGame - */ + /// @inheritdoc IDisputeGame function gameType() public pure override returns (GameType gameType_) { gameType_ = GameTypes.FAULT; } - /** - * @inheritdoc IDisputeGame - */ + /// @inheritdoc IDisputeGame function createdAt() external view returns (Timestamp createdAt_) { createdAt_ = gameStart; } - /** - * @inheritdoc IDisputeGame - */ + /// @inheritdoc IDisputeGame function resolve() external returns (GameStatus status_) { + // TODO: Do not allow resolution before clocks run out. + if (status != GameStatus.IN_PROGRESS) { + // If the game is not in progress, it cannot be resolved. revert GameNotInProgress(); } // Search for the left-most dangling non-bottom node // The most recent claim is always a dangling, non-bottom node so we start with that uint256 leftMostIndex = claimData.length - 1; - uint256 leftMostTraceIndex = LibPosition.rightIndex( - claimData[leftMostIndex].position, - MAX_GAME_DEPTH - ); + Position leftMostTraceIndex = Position.wrap(type(uint128).max); for (uint256 i = leftMostIndex; i < type(uint64).max; ) { // Fetch the claim at the current index. ClaimData storage claim = claimData[i]; @@ -243,24 +288,29 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone { // If the claim is not a dangling node above the bottom of the tree, // we can skip over it. These nodes are not relevant to the game resolution. Position claimPos = claim.position; - if (LibPosition.depth(claimPos) == MAX_GAME_DEPTH || claim.countered) { + if (claim.countered) { continue; } // If the claim is a dangling node, we can check if it is the left-most // dangling node we've come across so far. If it is, we can update the // left-most trace index. - uint256 traceIndex = LibPosition.rightIndex(claimPos, MAX_GAME_DEPTH); - if (traceIndex < leftMostTraceIndex) { + Position traceIndex = claimPos.rightIndex(MAX_GAME_DEPTH); + if (Position.unwrap(traceIndex) < Position.unwrap(leftMostTraceIndex)) { leftMostTraceIndex = traceIndex; - leftMostIndex = i + 1; + unchecked { + leftMostIndex = i + 1; + } } } // If the left-most dangling node is at an even depth, the defender wins. // Otherwise, the challenger wins and the root claim is deemed invalid. - // slither-disable-next-line weak-prng - if (LibPosition.depth(claimData[leftMostIndex].position) % 2 == 0) { + if ( + // slither-disable-next-line weak-prng + claimData[leftMostIndex].position.depth() % 2 == 0 && + Position.unwrap(leftMostTraceIndex) != type(uint128).max + ) { status_ = GameStatus.DEFENDER_WINS; } else { status_ = GameStatus.CHALLENGER_WINS; @@ -271,16 +321,12 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone { emit Resolved(status_); } - /** - * @inheritdoc IDisputeGame - */ + /// @inheritdoc IDisputeGame function rootClaim() public pure returns (Claim rootClaim_) { rootClaim_ = Claim.wrap(_getArgFixedBytes(0x00)); } - /** - * @inheritdoc IDisputeGame - */ + /// @inheritdoc IDisputeGame function extraData() public pure returns (bytes memory extraData_) { // The extra data starts at the second word within the cwia calldata. // TODO: What data do we need to pass along to this contract from the factory? @@ -288,9 +334,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone { extraData_ = _getArgDynBytes(0x20, 0x20); } - /** - * @inheritdoc IDisputeGame - */ + /// @inheritdoc IDisputeGame function gameData() external pure @@ -305,9 +349,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone { extraData_ = extraData(); } - /** - * @inheritdoc IInitializable - */ + /// @inheritdoc IInitializable function initialize() external { // Set the game start gameStart = Timestamp.wrap(uint64(block.timestamp)); @@ -326,9 +368,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone { ); } - /** - * @inheritdoc IVersioned - */ + /// @inheritdoc IVersioned function version() external pure override returns (string memory version_) { version_ = VERSION; } diff --git a/packages/contracts-bedrock/contracts/dispute/interfaces/IBondManager.sol b/packages/contracts-bedrock/contracts/dispute/interfaces/IBondManager.sol index 5be6777b8383..f033a9d46c45 100644 --- a/packages/contracts-bedrock/contracts/dispute/interfaces/IBondManager.sol +++ b/packages/contracts-bedrock/contracts/dispute/interfaces/IBondManager.sol @@ -1,70 +1,55 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.15; -/** - * @title IBondManager - * @notice The Bond Manager holds ether posted as a bond for a bond id. - */ +/// @title IBondManager +/// @notice The Bond Manager holds ether posted as a bond for a bond id. interface IBondManager { - /** - * @notice BondPosted is emitted when a bond is posted. - * @param bondId is the id of the bond. - * @param owner is the address that owns the bond. - * @param expiration is the time at which the bond expires. - * @param amount is the amount of the bond. - */ + /// @notice BondPosted is emitted when a bond is posted. + /// @param bondId is the id of the bond. + /// @param owner is the address that owns the bond. + /// @param expiration is the time at which the bond expires. + /// @param amount is the amount of the bond. event BondPosted(bytes32 bondId, address owner, uint256 expiration, uint256 amount); - /** - * @notice BondSeized is emitted when a bond is seized. - * @param bondId is the id of the bond. - * @param owner is the address that owns the bond. - * @param seizer is the address that seized the bond. - * @param amount is the amount of the bond. - */ + /// @notice BondSeized is emitted when a bond is seized. + /// @param bondId is the id of the bond. + /// @param owner is the address that owns the bond. + /// @param seizer is the address that seized the bond. + /// @param amount is the amount of the bond. event BondSeized(bytes32 bondId, address owner, address seizer, uint256 amount); - /** - * @notice BondReclaimed is emitted when a bond is reclaimed by the owner. - * @param bondId is the id of the bond. - * @param claiment is the address that reclaimed the bond. - * @param amount is the amount of the bond. - */ + /// @notice BondReclaimed is emitted when a bond is reclaimed by the owner. + /// @param bondId is the id of the bond. + /// @param claiment is the address that reclaimed the bond. + /// @param amount is the amount of the bond. event BondReclaimed(bytes32 bondId, address claiment, uint256 amount); - /** - * @notice Post a bond with a given id and owner. - * @dev This function will revert if the provided bondId is already in use. - * @param _bondId is the id of the bond. - * @param _bondOwner is the address that owns the bond. - * @param _minClaimHold is the minimum amount of time the owner - * must wait before reclaiming their bond. - */ + /// @notice Post a bond with a given id and owner. + /// @dev This function will revert if the provided bondId is already in use. + /// @param _bondId is the id of the bond. + /// @param _bondOwner is the address that owns the bond. + /// @param _minClaimHold is the minimum amount of time the owner + /// must wait before reclaiming their bond. function post( bytes32 _bondId, address _bondOwner, uint128 _minClaimHold ) external payable; - /** - * @notice Seizes the bond with the given id. - * @dev This function will revert if there is no bond at the given id. - * @param _bondId is the id of the bond. - */ + /// @notice Seizes the bond with the given id. + /// @dev This function will revert if there is no bond at the given id. + /// @param _bondId is the id of the bond. function seize(bytes32 _bondId) external; - /** - * @notice Seizes the bond with the given id and distributes it to recipients. - * @dev This function will revert if there is no bond at the given id. - * @param _bondId is the id of the bond. - * @param _claimRecipients is a set of addresses to split the bond amongst. - */ + /// @notice Seizes the bond with the given id and distributes it to recipients. + /// @dev This function will revert if there is no bond at the given id. + /// @param _bondId is the id of the bond. + /// @param _claimRecipients is a set of addresses to split the bond amongst. + /// function seizeAndSplit(bytes32 _bondId, address[] calldata _claimRecipients) external; - /** - * @notice Reclaims the bond of the bond owner. - * @dev This function will revert if there is no bond at the given id. - * @param _bondId is the id of the bond. - */ + /// @notice Reclaims the bond of the bond owner. + /// @dev This function will revert if there is no bond at the given id. + /// @param _bondId is the id of the bond. function reclaim(bytes32 _bondId) external; } diff --git a/packages/contracts-bedrock/contracts/dispute/interfaces/IDisputeGame.sol b/packages/contracts-bedrock/contracts/dispute/interfaces/IDisputeGame.sol index 885de2d6bc74..991bb4579cc3 100644 --- a/packages/contracts-bedrock/contracts/dispute/interfaces/IDisputeGame.sol +++ b/packages/contracts-bedrock/contracts/dispute/interfaces/IDisputeGame.sol @@ -7,77 +7,57 @@ import { IVersioned } from "./IVersioned.sol"; import { IBondManager } from "./IBondManager.sol"; import { IInitializable } from "./IInitializable.sol"; -/** - * @title IDisputeGame - * @notice The generic interface for a DisputeGame contract. - */ +/// @title IDisputeGame +/// @notice The generic interface for a DisputeGame contract. interface IDisputeGame is IInitializable, IVersioned { - /** - * @notice Emitted when the game is resolved. - * @param status The status of the game after resolution. - */ + /// @notice Emitted when the game is resolved. + /// @param status The status of the game after resolution. event Resolved(GameStatus indexed status); - /** - * @notice Returns the timestamp that the DisputeGame contract was created at. - * @return createdAt_ The timestamp that the DisputeGame contract was created at. - */ + /// @notice Returns the timestamp that the DisputeGame contract was created at. + /// @return createdAt_ The timestamp that the DisputeGame contract was created at. function createdAt() external view returns (Timestamp createdAt_); - /** - * @notice Returns the current status of the game. - * @return status_ The current status of the game. - */ + /// @notice Returns the current status of the game. + /// @return status_ The current status of the game. function status() external view returns (GameStatus status_); - /** - * @notice Getter for the game type. - * @dev `clones-with-immutable-args` argument #1 - * @dev The reference impl should be entirely different depending on the type (fault, validity) - * i.e. The game type should indicate the security model. - * @return gameType_ The type of proof system being used. - */ + /// @notice Getter for the game type. + /// @dev `clones-with-immutable-args` argument #1 + /// @dev The reference impl should be entirely different depending on the type (fault, validity) + /// i.e. The game type should indicate the security model. + /// @return gameType_ The type of proof system being used. function gameType() external pure returns (GameType gameType_); - /** - * @notice Getter for the root claim. - * @dev `clones-with-immutable-args` argument #2 - * @return rootClaim_ The root claim of the DisputeGame. - */ + /// @notice Getter for the root claim. + /// @dev `clones-with-immutable-args` argument #2 + /// @return rootClaim_ The root claim of the DisputeGame. function rootClaim() external pure returns (Claim rootClaim_); - /** - * @notice Getter for the extra data. - * @dev `clones-with-immutable-args` argument #3 - * @return extraData_ Any extra data supplied to the dispute game contract by the creator. - */ + /// @notice Getter for the extra data. + /// @dev `clones-with-immutable-args` argument #3 + /// @return extraData_ Any extra data supplied to the dispute game contract by the creator. function extraData() external pure returns (bytes memory extraData_); - /** - * @notice Returns the address of the `BondManager` used. - * @return bondManager_ The address of the `BondManager` used. - */ + /// @notice Returns the address of the `BondManager` used. + /// @return bondManager_ The address of the `BondManager` used. function bondManager() external view returns (IBondManager bondManager_); - /** - * @notice If all necessary information has been gathered, this function should mark the game - * status as either `CHALLENGER_WINS` or `DEFENDER_WINS` and return the status of - * the resolved game. It is at this stage that the bonds should be awarded to the - * necessary parties. - * @dev May only be called if the `status` is `IN_PROGRESS`. - * @return status_ The status of the game after resolution. - */ + /// @notice If all necessary information has been gathered, this function should mark the game + /// status as either `CHALLENGER_WINS` or `DEFENDER_WINS` and return the status of + /// the resolved game. It is at this stage that the bonds should be awarded to the + /// necessary parties. + /// @dev May only be called if the `status` is `IN_PROGRESS`. + /// @return status_ The status of the game after resolution. function resolve() external returns (GameStatus status_); - /** - * @notice A compliant implementation of this interface should return the components of the - * game UUID's preimage provided in the cwia payload. The preimage of the UUID is - * constructed as `keccak256(gameType . rootClaim . extraData)` where `.` denotes - * concatenation. - * @return gameType_ The type of proof system being used. - * @return rootClaim_ The root claim of the DisputeGame. - * @return extraData_ Any extra data supplied to the dispute game contract by the creator. - */ + /// @notice A compliant implementation of this interface should return the components of the + /// game UUID's preimage provided in the cwia payload. The preimage of the UUID is + /// constructed as `keccak256(gameType . rootClaim . extraData)` where `.` denotes + /// concatenation. + /// @return gameType_ The type of proof system being used. + /// @return rootClaim_ The root claim of the DisputeGame. + /// @return extraData_ Any extra data supplied to the dispute game contract by the creator. function gameData() external pure diff --git a/packages/contracts-bedrock/contracts/dispute/interfaces/IDisputeGameFactory.sol b/packages/contracts-bedrock/contracts/dispute/interfaces/IDisputeGameFactory.sol index a970db08a8e9..76d25d981008 100644 --- a/packages/contracts-bedrock/contracts/dispute/interfaces/IDisputeGameFactory.sol +++ b/packages/contracts-bedrock/contracts/dispute/interfaces/IDisputeGameFactory.sol @@ -5,105 +5,85 @@ import "../../libraries/DisputeTypes.sol"; import { IDisputeGame } from "./IDisputeGame.sol"; -/** - * @title IDisputeGameFactory - * @notice The interface for a DisputeGameFactory contract. - */ +/// @title IDisputeGameFactory +/// @notice The interface for a DisputeGameFactory contract. interface IDisputeGameFactory { - /** - * @notice Emitted when a new dispute game is created - * @param disputeProxy The address of the dispute game proxy - * @param gameType The type of the dispute game proxy's implementation - * @param rootClaim The root claim of the dispute game - */ + /// @notice Emitted when a new dispute game is created + /// @param disputeProxy The address of the dispute game proxy + /// @param gameType The type of the dispute game proxy's implementation + /// @param rootClaim The root claim of the dispute game event DisputeGameCreated( address indexed disputeProxy, GameType indexed gameType, Claim indexed rootClaim ); - /** - * @notice Emitted when a new game implementation added to the factory - * @param impl The implementation contract for the given `GameType`. - * @param gameType The type of the DisputeGame. - */ + /// @notice Emitted when a new game implementation added to the factory + /// @param impl The implementation contract for the given `GameType`. + /// @param gameType The type of the DisputeGame. event ImplementationSet(address indexed impl, GameType indexed gameType); - /** - * @notice the total number of dispute games created by this factory. - * @return _gameCount The total number of dispute games created by this factory. - */ + /// @notice The total number of dispute games created by this factory. + /// @return _gameCount The total number of dispute games created by this factory. function gameCount() external view returns (uint256 _gameCount); - /** - * @notice `games` queries an internal a mapping that maps the hash of - * `gameType ++ rootClaim ++ extraData` to the deployed `DisputeGame` clone. - * @dev `++` equates to concatenation. - * @param gameType The type of the DisputeGame - used to decide the proxy implementation - * @param rootClaim The root claim of the DisputeGame. - * @param extraData Any extra data that should be provided to the created dispute game. - * @return _proxy The clone of the `DisputeGame` created with the given parameters. - * Returns `address(0)` if nonexistent. - * @return _timestamp The timestamp of the creation of the dispute game. - */ + /// @notice `games` queries an internal mapping that maps the hash of + /// `gameType ++ rootClaim ++ extraData` to the deployed `DisputeGame` clone. + /// @dev `++` equates to concatenation. + /// @param gameType The type of the DisputeGame - used to decide the proxy implementation + /// @param rootClaim The root claim of the DisputeGame. + /// @param extraData Any extra data that should be provided to the created dispute game. + /// @return _proxy The clone of the `DisputeGame` created with the given parameters. + /// Returns `address(0)` if nonexistent. + /// @return _timestamp The timestamp of the creation of the dispute game. function games( GameType gameType, Claim rootClaim, bytes calldata extraData ) external view returns (IDisputeGame _proxy, uint256 _timestamp); - /** - * @notice `gameAtIndex` returns the dispute game contract address and its creation timestamp - * at the given index. Each created dispute game increments the underlying index. - * @param _index The index of the dispute game. - * @return _proxy The clone of the `DisputeGame` created with the given parameters. - * Returns `address(0)` if nonexistent. - * @return _timestamp The timestamp of the creation of the dispute game. - */ + /// @notice `gameAtIndex` returns the dispute game contract address and its creation timestamp + /// at the given index. Each created dispute game increments the underlying index. + /// @param _index The index of the dispute game. + /// @return _proxy The clone of the `DisputeGame` created with the given parameters. + /// Returns `address(0)` if nonexistent. + /// @return _timestamp The timestamp of the creation of the dispute game. function gameAtIndex(uint256 _index) external view returns (IDisputeGame _proxy, uint256 _timestamp); - /** - * @notice `gameImpls` is a mapping that maps `GameType`s to their respective - * `IDisputeGame` implementations. - * @param gameType The type of the dispute game. - * @return _impl The address of the implementation of the game type. - * Will be cloned on creation of a new dispute game with the given `gameType`. - */ + /// @notice `gameImpls` is a mapping that maps `GameType`s to their respective + /// `IDisputeGame` implementations. + /// @param gameType The type of the dispute game. + /// @return _impl The address of the implementation of the game type. + /// Will be cloned on creation of a new dispute game with the given `gameType`. function gameImpls(GameType gameType) external view returns (IDisputeGame _impl); - /** - * @notice Creates a new DisputeGame proxy contract. - * @param gameType The type of the DisputeGame - used to decide the proxy implementation - * @param rootClaim The root claim of the DisputeGame. - * @param extraData Any extra data that should be provided to the created dispute game. - * @return proxy The address of the created DisputeGame proxy. - */ + /// @notice Creates a new DisputeGame proxy contract. + /// @param gameType The type of the DisputeGame - used to decide the proxy implementation. + /// @param rootClaim The root claim of the DisputeGame. + /// @param extraData Any extra data that should be provided to the created dispute game. + /// @return proxy The address of the created DisputeGame proxy. function create( GameType gameType, Claim rootClaim, bytes calldata extraData ) external returns (IDisputeGame proxy); - /** - * @notice Sets the implementation contract for a specific `GameType`. - * @dev May only be called by the `owner`. - * @param gameType The type of the DisputeGame. - * @param impl The implementation contract for the given `GameType`. - */ + /// @notice Sets the implementation contract for a specific `GameType`. + /// @dev May only be called by the `owner`. + /// @param gameType The type of the DisputeGame. + /// @param impl The implementation contract for the given `GameType`. function setImplementation(GameType gameType, IDisputeGame impl) external; - /** - * @notice Returns a unique identifier for the given dispute game parameters. - * @dev Hashes the concatenation of `gameType . rootClaim . extraData` - * without expanding memory. - * @param gameType The type of the DisputeGame. - * @param rootClaim The root claim of the DisputeGame. - * @param extraData Any extra data that should be provided to the created dispute game. - * @return _uuid The unique identifier for the given dispute game parameters. - */ + /// @notice Returns a unique identifier for the given dispute game parameters. + /// @dev Hashes the concatenation of `gameType . rootClaim . extraData` + /// without expanding memory. + /// @param gameType The type of the DisputeGame. + /// @param rootClaim The root claim of the DisputeGame. + /// @param extraData Any extra data that should be provided to the created dispute game. + /// @return _uuid The unique identifier for the given dispute game parameters. function getGameUUID( GameType gameType, Claim rootClaim, diff --git a/packages/contracts-bedrock/contracts/dispute/interfaces/IFaultDisputeGame.sol b/packages/contracts-bedrock/contracts/dispute/interfaces/IFaultDisputeGame.sol index dcfb22bf71a1..34ebeaa2b06f 100644 --- a/packages/contracts-bedrock/contracts/dispute/interfaces/IFaultDisputeGame.sol +++ b/packages/contracts-bedrock/contracts/dispute/interfaces/IFaultDisputeGame.sol @@ -5,16 +5,11 @@ import "../../libraries/DisputeTypes.sol"; import { IDisputeGame } from "./IDisputeGame.sol"; -/** - * @title IFaultDisputeGame - * @notice The interface for a fault proof backed dispute game. - */ +/// @title IFaultDisputeGame +/// @notice The interface for a fault proof backed dispute game. interface IFaultDisputeGame is IDisputeGame { - /** - * @notice The `ClaimData` struct represents the data associated with a Claim. - * @dev TODO: Pack `Clock` and `Position` into the same slot. Should require 4 64 bit arms. - * @dev TODO: Add bond ID information. - */ + /// @notice The `ClaimData` struct represents the data associated with a Claim. + /// @dev TODO: Add bond ID information. struct ClaimData { uint32 parentIndex; bool countered; @@ -23,43 +18,42 @@ interface IFaultDisputeGame is IDisputeGame { Clock clock; } - /** - * @notice Emitted when a new claim is added to the DAG by `claimant` - * @param parentIndex The index within the `claimData` array of the parent claim - * @param pivot The claim being added - * @param claimant The address of the claimant - */ + /// @notice Emitted when a new claim is added to the DAG by `claimant` + /// @param parentIndex The index within the `claimData` array of the parent claim + /// @param pivot The claim being added + /// @param claimant The address of the claimant event Move(uint256 indexed parentIndex, Claim indexed pivot, address indexed claimant); - /** - * @notice Attack a disagreed upon `Claim`. - * @param _parentIndex Index of the `Claim` to attack in `claimData`. - * @param _pivot The `Claim` at the relative attack position. - */ + /// @notice Attack a disagreed upon `Claim`. + /// @param _parentIndex Index of the `Claim` to attack in `claimData`. + /// @param _pivot The `Claim` at the relative attack position. function attack(uint256 _parentIndex, Claim _pivot) external payable; - /** - * @notice Defend an agreed upon `Claim`. - * @param _parentIndex Index of the claim to defend in `claimData`. - * @param _pivot The `Claim` at the relative defense position. - */ + /// @notice Defend an agreed upon `Claim`. + /// @param _parentIndex Index of the claim to defend in `claimData`. + /// @param _pivot The `Claim` at the relative defense position. function defend(uint256 _parentIndex, Claim _pivot) external payable; - /** - * @notice Perform the final step via an on-chain fault proof processor - * @dev This function should point to a fault proof processor in order to execute - * a step in the fault proof program on-chain. The interface of the fault proof - * processor contract should be generic enough such that we can use different - * fault proof VMs (MIPS, RiscV5, etc.) - * @param _prestateIndex The index of the prestate of the step within `claimData`. - * @param _parentIndex The index of the parent claim within `claimData`. - * @param _stateData The stateData of the step is the preimage of the claim @ `prestateIndex` - * @param _proof Proof to access memory leaf nodes in the VM. - */ + /// @notice Perform the final step via an on-chain fault proof processor + /// @dev This function should point to a fault proof processor in order to execute + /// a step in the fault proof program on-chain. The interface of the fault proof + /// processor contract should be generic enough such that we can use different + /// fault proof VMs (MIPS, RiscV5, etc.) + /// @param _stateIndex The index of the pre/post state of the step within `claimData`. + /// @param _claimIndex The index of the challenged claim within `claimData`. + /// @param _isAttack Whether or not the step is an attack or a defense. + /// @param _stateData The stateData of the step is the preimage of the claim @ `prestateIndex` + /// @param _proof Proof to access memory leaf nodes in the VM. function step( - uint256 _prestateIndex, - uint256 _parentIndex, + uint256 _stateIndex, + uint256 _claimIndex, + bool _isAttack, bytes calldata _stateData, bytes calldata _proof ) external; + + /// @notice The l2BlockNumber that the `rootClaim` commits to. The trace being bisected within + /// the game is from `l2BlockNumber - 1` -> `l2BlockNumber`. + /// @return l2BlockNumber_ The l2BlockNumber that the `rootClaim` commits to. + function l2BlockNumber() external view returns (uint256 l2BlockNumber_); } diff --git a/packages/contracts-bedrock/contracts/dispute/interfaces/IInitializable.sol b/packages/contracts-bedrock/contracts/dispute/interfaces/IInitializable.sol index 7cd9b04e3ce9..1609647c1ea8 100644 --- a/packages/contracts-bedrock/contracts/dispute/interfaces/IInitializable.sol +++ b/packages/contracts-bedrock/contracts/dispute/interfaces/IInitializable.sol @@ -1,14 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.15; -/** - * @title IInitializable - * @notice An interface for initializable contracts. - */ +/// @title IInitializable +/// @notice An interface for initializable contracts. interface IInitializable { - /** - * @notice Initializes the contract. - * @dev This function may only be called once. - */ + /// @notice Initializes the contract. + /// @dev This function may only be called once. function initialize() external; } diff --git a/packages/contracts-bedrock/contracts/dispute/interfaces/IVersioned.sol b/packages/contracts-bedrock/contracts/dispute/interfaces/IVersioned.sol index 8b9a2d473db6..a2dd4fd2ed80 100644 --- a/packages/contracts-bedrock/contracts/dispute/interfaces/IVersioned.sol +++ b/packages/contracts-bedrock/contracts/dispute/interfaces/IVersioned.sol @@ -1,14 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.15; -/** - * @title IVersioned - * @notice An interface for semantically versioned contracts. - */ +/// @title IVersioned +/// @notice An interface for semantically versioned contracts. interface IVersioned { - /** - * @notice Returns the semantic version of the contract - * @return _version The semantic version of the contract - */ + /// @notice Returns the semantic version of the contract + /// @return _version The semantic version of the contract function version() external pure returns (string memory _version); } diff --git a/packages/contracts-bedrock/contracts/dispute/lib/LibClock.sol b/packages/contracts-bedrock/contracts/dispute/lib/LibClock.sol index 353d1ba1f8eb..a912da1ab525 100644 --- a/packages/contracts-bedrock/contracts/dispute/lib/LibClock.sol +++ b/packages/contracts-bedrock/contracts/dispute/lib/LibClock.sol @@ -3,28 +3,22 @@ pragma solidity ^0.8.15; import "../../libraries/DisputeTypes.sol"; -/** - * @title LibClock - * @notice This library contains helper functions for working with the `Clock` type. - */ +/// @title LibClock +/// @notice This library contains helper functions for working with the `Clock` type. library LibClock { - /** - * @notice Packs a `Duration` and `Timestamp` into a `Clock` type. - * @param _duration The `Duration` to pack into the `Clock` type. - * @param _timestamp The `Timestamp` to pack into the `Clock` type. - * @return clock_ The `Clock` containing the `_duration` and `_timestamp`. - */ + /// @notice Packs a `Duration` and `Timestamp` into a `Clock` type. + /// @param _duration The `Duration` to pack into the `Clock` type. + /// @param _timestamp The `Timestamp` to pack into the `Clock` type. + /// @return clock_ The `Clock` containing the `_duration` and `_timestamp`. function wrap(Duration _duration, Timestamp _timestamp) internal pure returns (Clock clock_) { assembly { clock_ := or(shl(0x40, _duration), _timestamp) } } - /** - * @notice Pull the `Duration` out of a `Clock` type. - * @param _clock The `Clock` type to pull the `Duration` out of. - * @return duration_ The `Duration` pulled out of `_clock`. - */ + /// @notice Pull the `Duration` out of a `Clock` type. + /// @param _clock The `Clock` type to pull the `Duration` out of. + /// @return duration_ The `Duration` pulled out of `_clock`. function duration(Clock _clock) internal pure returns (Duration duration_) { // Shift the high-order 64 bits into the low-order 64 bits, leaving only the `duration`. assembly { @@ -32,11 +26,9 @@ library LibClock { } } - /** - * @notice Pull the `Timestamp` out of a `Clock` type. - * @param _clock The `Clock` type to pull the `Timestamp` out of. - * @return timestamp_ The `Timestamp` pulled out of `_clock`. - */ + /// @notice Pull the `Timestamp` out of a `Clock` type. + /// @param _clock The `Clock` type to pull the `Timestamp` out of. + /// @return timestamp_ The `Timestamp` pulled out of `_clock`. function timestamp(Clock _clock) internal pure returns (Timestamp timestamp_) { // Clean the high-order 192 bits by shifting the clock left and then right again, leaving // only the `timestamp`. diff --git a/packages/contracts-bedrock/contracts/dispute/lib/LibHashing.sol b/packages/contracts-bedrock/contracts/dispute/lib/LibHashing.sol index 5adf94f4e3a9..0e64ddd31dc3 100644 --- a/packages/contracts-bedrock/contracts/dispute/lib/LibHashing.sol +++ b/packages/contracts-bedrock/contracts/dispute/lib/LibHashing.sol @@ -3,17 +3,14 @@ pragma solidity ^0.8.15; import "../../libraries/DisputeTypes.sol"; -/** - * @title Hashing - * @notice This library contains all of the hashing utilities used in the Cannon contracts. - */ +/// @title Hashing +/// @notice This library contains all of the hashing utilities used in the Cannon contracts. library LibHashing { - /** - * @notice Hashes a claim and a position together. - * @param _claim A Claim type. - * @param _position The position of `claim`. - * @return claimHash_ A hash of abi.encodePacked(claim, position); - */ + + /// @notice Hashes a claim and a position together. + /// @param _claim A Claim type. + /// @param _position The position of `claim`. + /// @return claimHash_ A hash of abi.encodePacked(claim, position); function hashClaimPos(Claim _claim, Position _position) internal pure returns (ClaimHash claimHash_) { assembly { mstore(0x00, _claim) diff --git a/packages/contracts-bedrock/contracts/dispute/lib/LibPosition.sol b/packages/contracts-bedrock/contracts/dispute/lib/LibPosition.sol index cf938aa029ed..17132aa2b527 100644 --- a/packages/contracts-bedrock/contracts/dispute/lib/LibPosition.sol +++ b/packages/contracts-bedrock/contracts/dispute/lib/LibPosition.sol @@ -3,25 +3,27 @@ pragma solidity ^0.8.15; import "../../libraries/DisputeTypes.sol"; -/** - * @title LibPosition - * @notice This library contains helper functions for working with the `Position` type. - */ +/// @title LibPosition +/// @notice This library contains helper functions for working with the `Position` type. library LibPosition { + + /// @notice Computes a generalized index (2^{depth} + indexAtDepth). + /// @param _depth The depth of the position. + /// @param _indexAtDepth The index at the depth of the position. + /// @return position_ The computed generalized index. function wrap(uint64 _depth, uint64 _indexAtDepth) internal pure returns (Position position_) { assembly { + // gindex = 2^{_depth} + _indexAtDepth position_ := add(shl(_depth, 1), _indexAtDepth) } } - /** - * @notice Pulls the `depth` out of a packed `Position` type. - * @param _position The position to get the `depth` of. - * @return depth_ The `depth` of the `position`. - * @custom:attribution Solady - */ + /// @notice Pulls the `depth` out of a `Position` type. + /// @param _position The generalized index to get the `depth` of. + /// @return depth_ The `depth` of the `position` gindex. + /// @custom:attribution Solady function depth(Position _position) internal pure returns (uint64 depth_) { - // Return the most significant bit position + // Return the most significant bit offset, which signifies the depth of the gindex. assembly { depth_ := or(depth_, shl(6, lt(0xffffffffffffffff, shr(depth_, _position)))) depth_ := or(depth_, shl(5, lt(0xffffffff, shr(depth_, _position)))) @@ -44,93 +46,73 @@ library LibPosition { } } - /** - * @notice Pulls the `indexAtDepth` out of a packed `Position` type. - * @param _position The position to get the `indexAtDepth` of. - * @return indexAtDepth_ The `indexAtDepth` of the `position`. - */ + /// @notice Pulls the `indexAtDepth` out of a `Position` type. + /// The `indexAtDepth` is the left/right index of a position at a specific depth within + /// the binary tree, starting from index 0. For example, at gindex 2, the `depth` = 1 + /// and the `indexAtDepth` = 0. + /// @param _position The generalized index to get the `indexAtDepth` of. + /// @return indexAtDepth_ The `indexAtDepth` of the `position` gindex. function indexAtDepth(Position _position) internal pure returns (uint64 indexAtDepth_) { - // Return bits p_{msb-1}...p_{0} + // Return bits p_{msb-1}...p_{0}. This effectively pulls the 2^{depth} out of the gindex, + // leaving only the `indexAtDepth`. uint256 msb = depth(_position); assembly { indexAtDepth_ := sub(_position, shl(msb, 1)) } } - /** - * @notice Get the position to the left of `position`. - * @param _position The position to get the left position of. - * @return left_ The position to the left of `position`. - */ + /// @notice Get the left child of `_position`. + /// @param _position The position to get the left position of. + /// @return left_ The position to the left of `position`. function left(Position _position) internal pure returns (Position left_) { assembly { left_ := shl(1, _position) } } - /** - * @notice Get the position to the right of `position`. - * @param _position The position to get the right position of. - * @return right_ The position to the right of `position`. - */ + /// @notice Get the right child of `_position` + /// @param _position The position to get the right position of. + /// @return right_ The position to the right of `position`. function right(Position _position) internal pure returns (Position right_) { assembly { - right_ := add(1, shl(1, _position)) + right_ := or(1, shl(1, _position)) } } - /** - * @notice Get the parent position of `position`. - * @param _position The position to get the parent position of. - * @return parent_ The parent position of `position`. - */ + /// @notice Get the parent position of `_position`. + /// @param _position The position to get the parent position of. + /// @return parent_ The parent position of `position`. function parent(Position _position) internal pure returns (Position parent_) { assembly { parent_ := shr(1, _position) } } - /** - * @notice Get the deepest, right most index relative to the `position`. - * @param _position The position to get the relative deepest, right most index of. - * @param _maxDepth The maximum depth of the game. - * @return rightIndex_ The deepest, right most index relative to the `position`. - */ + /// @notice Get the deepest, right most gindex relative to the `position`. This is equivalent to + /// calling `right` on a position until the maximum depth is reached. + /// @param _position The position to get the relative deepest, right most gindex of. + /// @param _maxDepth The maximum depth of the game. + /// @return rightIndex_ The deepest, right most gindex relative to the `position`. function rightIndex( Position _position, uint256 _maxDepth - ) internal pure returns (uint64 rightIndex_) { + ) internal pure returns (Position rightIndex_) { uint256 msb = depth(_position); assembly { - switch eq(msb, _maxDepth) - case true { - rightIndex_ := _position - } - default { - let remaining := sub(_maxDepth, msb) - rightIndex_ := or(shl(remaining, _position), sub(shl(remaining, 1), 1)) - } - rightIndex_ := sub(rightIndex_, shl(_maxDepth, 1)) + let remaining := sub(_maxDepth, msb) + rightIndex_ := or(shl(remaining, _position), sub(shl(remaining, 1), 1)) } } - /** - * @notice Get the attack position relative to `position`. - * @param _position The position to get the relative attack position of. - * @return attack_ The attack position relative to `position`. - */ - function attack(Position _position) internal pure returns (Position attack_) { - return left(_position); - } - - /** - * @notice Get the defense position relative to `position`. - * @param _position The position to get the relative defense position of. - * @return defense_ The defense position relative to `position`. - */ - function defend(Position _position) internal pure returns (Position defense_) { + /// @notice Get the move position of `_position`, which is the left child of: + /// 1. `_position + 1` if `_isAttack` is true. + /// 1. `_position` if `_isAttack` is false. + /// @param _position The position to get the relative attack/defense position of. + /// @param _isAttack Whether or not the move is an attack move. + /// @return move_ The move position relative to `position`. + function move(Position _position, bool _isAttack) internal pure returns (Position move_) { assembly { - defense_ := shl(1, add(1, shl(1, shr(1, _position)))) + move_ := shl(1, or(iszero(_isAttack), _position)) } } } diff --git a/packages/contracts-bedrock/contracts/libraries/DisputeErrors.sol b/packages/contracts-bedrock/contracts/libraries/DisputeErrors.sol index 9b0911aaa8b7..5b9cbcb0ccf4 100644 --- a/packages/contracts-bedrock/contracts/libraries/DisputeErrors.sol +++ b/packages/contracts-bedrock/contracts/libraries/DisputeErrors.sol @@ -7,80 +7,65 @@ import "./DisputeTypes.sol"; // `DisputeGameFactory` Errors // //////////////////////////////////////////////////////////////// -/** - * @notice Thrown when a dispute game is attempted to be created with an unsupported game type. - * @param gameType The unsupported game type. - */ +/// @notice Thrown when a dispute game is attempted to be created with an unsupported game type. +/// @param gameType The unsupported game type. error NoImplementation(GameType gameType); -/** - * @notice Thrown when a dispute game that already exists is attempted to be created. - * @param uuid The UUID of the dispute game that already exists. - */ +/// @notice Thrown when a dispute game that already exists is attempted to be created. +/// @param uuid The UUID of the dispute game that already exists. error GameAlreadyExists(Hash uuid); //////////////////////////////////////////////////////////////// // `DisputeGame_Fault.sol` Errors // //////////////////////////////////////////////////////////////// -/** - * @notice Thrown when a supplied bond is too low to cover the - * cost of the next possible counter claim. - */ +/// @notice Thrown when a supplied bond is too low to cover the +/// cost of the next possible counter claim. error BondTooLow(); -/** - * @notice Thrown when a defense against the root claim is attempted. - */ +/// @notice Thrown when a defense against the root claim is attempted. error CannotDefendRootClaim(); -/** - * @notice Thrown when a claim is attempting to be made that already exists. - */ +/// @notice Thrown when a claim is attempting to be made that already exists. error ClaimAlreadyExists(); -/** - * @notice Thrown when a given claim is invalid (0). - */ +/// @notice Thrown when a given claim is invalid (0). error InvalidClaim(); -/** - * @notice Thrown when an action that requires the game to be `IN_PROGRESS` is invoked when - * the game is not in progress. - */ +/// @notice Thrown when an action that requires the game to be `IN_PROGRESS` is invoked when +/// the game is not in progress. error GameNotInProgress(); -/** - * @notice Thrown when a move is attempted to be made after the clock has timed out. - */ +/// @notice Thrown when a move is attempted to be made after the clock has timed out. error ClockTimeExceeded(); -/** - * @notice Thrown when a move is attempted to be made at or greater than the max depth of the game. - */ +/// @notice Thrown when a move is attempted to be made at or greater than the max depth of the game. error GameDepthExceeded(); +/// @notice Thrown when a step is attempted above the maximum game depth. +error InvalidParent(); + +/// @notice Thrown when an invalid prestate is supplied to `step`. +error InvalidPrestate(); + +/// @notice Thrown when a step is made that computes the expected post state correctly. +error ValidStep(); + //////////////////////////////////////////////////////////////// // `AttestationDisputeGame` Errors // //////////////////////////////////////////////////////////////// -/** - * @notice Thrown when an invalid signature is submitted to `challenge`. - */ +/// @notice Thrown when an invalid signature is submitted to `challenge`. error InvalidSignature(); -/** - * @notice Thrown when a signature that has already been used to support the - * `rootClaim` is submitted to `challenge`. - */ +/// @notice Thrown when a signature that has already been used to support the +/// `rootClaim` is submitted to `challenge`. error AlreadyChallenged(); //////////////////////////////////////////////////////////////// // `Ownable` Errors // //////////////////////////////////////////////////////////////// -/** - * @notice Thrown when a function that is protected by the `onlyOwner` modifier - * is called from an account other than the owner. - */ +/// @notice Thrown when a function that is protected by the `onlyOwner` modifier +/// is called from an account other than the owner. error NotOwner(); diff --git a/packages/contracts-bedrock/contracts/libraries/DisputeTypes.sol b/packages/contracts-bedrock/contracts/libraries/DisputeTypes.sol index e72df1f356f2..d13d96cf269b 100644 --- a/packages/contracts-bedrock/contracts/libraries/DisputeTypes.sol +++ b/packages/contracts-bedrock/contracts/libraries/DisputeTypes.sol @@ -9,79 +9,57 @@ using LibHashing for Claim global; using LibPosition for Position global; using LibClock for Clock global; -/** - * @notice A custom type for a generic hash. - */ +/// @notice A custom type for a generic hash. type Hash is bytes32; -/** - * @notice A claim represents an MPT root representing the state of the fault proof program. - */ +/// @notice A claim represents an MPT root representing the state of the fault proof program. type Claim is bytes32; -/** - * @notice A claim hash represents a hash of a claim and a position within the game tree. - * @dev Keccak hash of abi.encodePacked(Claim, Position); - */ +/// @notice A claim hash represents a hash of a claim and a position within the game tree. +/// @dev Keccak hash of abi.encodePacked(Claim, Position); type ClaimHash is bytes32; -/** - * @notice A bondamount represents the amount of collateral that a user has locked up in a claim. - */ +/// @notice A bondamount represents the amount of collateral that a user has locked up in a claim. type BondAmount is uint256; -/** - * @notice A dedicated timestamp type. - */ +/// @notice A dedicated timestamp type. type Timestamp is uint64; -/** - * @notice A dedicated duration type. - * @dev Unit: seconds - */ +/// @notice A dedicated duration type. +/// @dev Unit: seconds type Duration is uint64; -/** - * @notice A `GameId` represents a packed 12 byte timestamp and a 20 byte address. - * @dev The packed layout of this type is as follows: - * ┌────────────┬────────────────┐ - * │ Bits │ Value │ - * ├────────────┼────────────────┤ - * │ [0, 96) │ Timestamp │ - * │ [96, 256) │ Address │ - * └────────────┴────────────────┘ - */ +/// @notice A `GameId` represents a packed 12 byte timestamp and a 20 byte address. +/// @dev The packed layout of this type is as follows: +/// ┌────────────┬────────────────┐ +/// │ Bits │ Value │ +/// ├────────────┼────────────────┤ +/// │ [0, 96) │ Timestamp │ +/// │ [96, 256) │ Address │ +/// └────────────┴────────────────┘ type GameId is bytes32; -/** - * @notice A `Clock` represents a packed `Duration` and `Timestamp` - * @dev The packed layout of this type is as follows: - * ┌────────────┬────────────────┐ - * │ Bits │ Value │ - * ├────────────┼────────────────┤ - * │ [0, 64) │ Duration │ - * │ [64, 128) │ Timestamp │ - * └────────────┴────────────────┘ - */ +/// @notice A `Clock` represents a packed `Duration` and `Timestamp` +/// @dev The packed layout of this type is as follows: +/// ┌────────────┬────────────────┐ +/// │ Bits │ Value │ +/// ├────────────┼────────────────┤ +/// │ [0, 64) │ Duration │ +/// │ [64, 128) │ Timestamp │ +/// └────────────┴────────────────┘ type Clock is uint128; -/** - * @notice A `Position` represents a position of a claim within the game tree. - * @dev This is represented as a "generalized index" where the high-order bit - * is the level in the tree and the remaining bits is a unique bit pattern, allowing - * a unique identifier for each node in the tree. Mathematically, it is calculated - * as 2^{depth} + indexAtDepth. - */ +/// @notice A `Position` represents a position of a claim within the game tree. +/// @dev This is represented as a "generalized index" where the high-order bit +/// is the level in the tree and the remaining bits is a unique bit pattern, allowing +/// a unique identifier for each node in the tree. Mathematically, it is calculated +/// as 2^{depth} + indexAtDepth. type Position is uint128; -/** - * @notice A `GameType` represents the type of game being played. - */ +/// @notice A `GameType` represents the type of game being played. type GameType is uint8; -/** - * @notice The current status of the dispute game. - */ +/// @notice The current status of the dispute game. enum GameStatus { // The game is currently in progress, and has not been resolved. IN_PROGRESS, @@ -91,23 +69,15 @@ enum GameStatus { DEFENDER_WINS } -/** - * @title GameTypes - * @notice A library that defines the IDs of games that can be played. - */ +/// @title GameTypes +/// @notice A library that defines the IDs of games that can be played. library GameTypes { - /** - * @dev The game will use a `IDisputeGame` implementation that utilizes fault proofs. - */ + /// @dev The game will use a `IDisputeGame` implementation that utilizes fault proofs. GameType internal constant FAULT = GameType.wrap(0); - /** - * @dev The game will use a `IDisputeGame` implementation that utilizes validity proofs. - */ + /// @dev The game will use a `IDisputeGame` implementation that utilizes validity proofs. GameType internal constant VALIDITY = GameType.wrap(1); - /** - * @dev The game will use a `IDisputeGame` implementation that utilizes attestation proofs. - */ + /// @dev The game will use a `IDisputeGame` implementation that utilizes attestation proofs. GameType internal constant ATTESTATION = GameType.wrap(2); } diff --git a/packages/contracts-bedrock/contracts/test/Bytes.t.sol b/packages/contracts-bedrock/contracts/test/Bytes.t.sol index 7a9f2df96b16..324656221689 100644 --- a/packages/contracts-bedrock/contracts/test/Bytes.t.sol +++ b/packages/contracts-bedrock/contracts/test/Bytes.t.sol @@ -70,59 +70,6 @@ contract Bytes_slice_Test is Test { assertEq(Bytes.slice(input, 31, 34), expected); } - /** - * @notice Tests that, when given an input bytes array of length `n`, the `slice` function will - * always revert if `_start + _length > n`. - */ - function testFuzz_slice_outOfBounds_reverts( - bytes memory _input, - uint256 _start, - uint256 _length - ) public { - // We want a valid start index and a length that will not overflow. - vm.assume(_start < _input.length && _length < type(uint256).max - 31); - // But, we want an invalid slice length. - vm.assume(_start + _length > _input.length); - - vm.expectRevert("slice_outOfBounds"); - Bytes.slice(_input, _start, _length); - } - - /** - * @notice Tests that, when given a length `n` that is greater than `type(uint256).max - 31`, - * the `slice` function reverts. - */ - function testFuzz_slice_lengthOverflows_reverts( - bytes memory _input, - uint256 _start, - uint256 _length - ) public { - // Ensure that the `_length` will overflow if a number >= 31 is added to it. - vm.assume(_length > type(uint256).max - 31); - - vm.expectRevert("slice_overflow"); - Bytes.slice(_input, _start, _length); - } - - /** - * @notice Tests that, when given a start index `n` that is greater than - * `type(uint256).max - n`, the `slice` function reverts. - */ - function testFuzz_slice_rangeOverflows_reverts( - bytes memory _input, - uint256 _start, - uint256 _length - ) public { - // Ensure that `_length` is a realistic length of a slice. This is to make sure - // we revert on the correct require statement. - vm.assume(_length < _input.length); - // Ensure that `_start` will overflow if `_length` is added to it. - vm.assume(_start > type(uint256).max - _length); - - vm.expectRevert("slice_overflow"); - Bytes.slice(_input, _start, _length); - } - /** * @notice Tests that the `slice` function correctly updates the free memory pointer depending * on the length of the slice. @@ -181,6 +128,61 @@ contract Bytes_slice_Test is Test { } } +contract Bytes_slice_TestFail is Test { + /** + * @notice Tests that, when given an input bytes array of length `n`, the `slice` function will + * always revert if `_start + _length > n`. + */ + function testFuzz_slice_outOfBounds_reverts( + bytes memory _input, + uint256 _start, + uint256 _length + ) public { + // We want a valid start index and a length that will not overflow. + vm.assume(_start < _input.length && _length < type(uint256).max - 31); + // But, we want an invalid slice length. + vm.assume(_start + _length > _input.length); + + vm.expectRevert("slice_outOfBounds"); + Bytes.slice(_input, _start, _length); + } + + /** + * @notice Tests that, when given a length `n` that is greater than `type(uint256).max - 31`, + * the `slice` function reverts. + */ + function testFuzz_slice_lengthOverflows_reverts( + bytes memory _input, + uint256 _start, + uint256 _length + ) public { + // Ensure that the `_length` will overflow if a number >= 31 is added to it. + vm.assume(_length > type(uint256).max - 31); + + vm.expectRevert("slice_overflow"); + Bytes.slice(_input, _start, _length); + } + + /** + * @notice Tests that, when given a start index `n` that is greater than + * `type(uint256).max - n`, the `slice` function reverts. + */ + function testFuzz_slice_rangeOverflows_reverts( + bytes memory _input, + uint256 _start, + uint256 _length + ) public { + // Ensure that `_length` is a realistic length of a slice. This is to make sure + // we revert on the correct require statement. + vm.assume(_length < _input.length); + // Ensure that `_start` will overflow if `_length` is added to it. + vm.assume(_start > type(uint256).max - _length); + + vm.expectRevert("slice_overflow"); + Bytes.slice(_input, _start, _length); + } +} + contract Bytes_toNibbles_Test is Test { /** * @notice Tests that, given an input of 5 bytes, the `toNibbles` function returns an array of diff --git a/packages/contracts-bedrock/contracts/test/CommonTest.t.sol b/packages/contracts-bedrock/contracts/test/CommonTest.t.sol index 1e5c6d988d7d..5cf1c3d63a1c 100644 --- a/packages/contracts-bedrock/contracts/test/CommonTest.t.sol +++ b/packages/contracts-bedrock/contracts/test/CommonTest.t.sol @@ -124,6 +124,26 @@ contract L2OutputOracle_Initializer is CommonTest { vm.warp(oracle.computeL2Timestamp(_nextBlockNumber) + 1); } + /// @dev Helper function to propose an output. + function proposeAnotherOutput() public { + bytes32 proposedOutput2 = keccak256(abi.encode()); + uint256 nextBlockNumber = oracle.nextBlockNumber(); + uint256 nextOutputIndex = oracle.nextOutputIndex(); + warpToProposeTime(nextBlockNumber); + uint256 proposedNumber = oracle.latestBlockNumber(); + + // Ensure the submissionInterval is enforced + assertEq(nextBlockNumber, proposedNumber + submissionInterval); + + vm.roll(nextBlockNumber + 1); + + vm.expectEmit(true, true, true, true); + emit OutputProposed(proposedOutput2, nextOutputIndex, nextBlockNumber, block.timestamp); + + vm.prank(proposer); + oracle.proposeL2Output(proposedOutput2, nextBlockNumber, 0, 0); + } + function setUp() public virtual override { super.setUp(); guardian = makeAddr("guardian"); diff --git a/packages/contracts-bedrock/contracts/test/DisputeGameFactory.t.sol b/packages/contracts-bedrock/contracts/test/DisputeGameFactory.t.sol index ff289f4d59a4..44a99690509d 100644 --- a/packages/contracts-bedrock/contracts/test/DisputeGameFactory.t.sol +++ b/packages/contracts-bedrock/contracts/test/DisputeGameFactory.t.sol @@ -37,10 +37,8 @@ contract DisputeGameFactory_Init is Test { } contract DisputeGameFactory_Create_Test is DisputeGameFactory_Init { - /** - * @dev Tests that the `create` function succeeds when creating a new dispute game - * with a `GameType` that has an implementation set. - */ + /// @dev Tests that the `create` function succeeds when creating a new dispute game + /// with a `GameType` that has an implementation set. function testFuzz_create_succeeds( uint8 gameType, Claim rootClaim, @@ -70,10 +68,8 @@ contract DisputeGameFactory_Create_Test is DisputeGameFactory_Init { assertEq(timestamp2, block.timestamp); } - /** - * @dev Tests that the `create` function reverts when there is no implementation - * set for the given `GameType`. - */ + /// @dev Tests that the `create` function reverts when there is no implementation + /// set for the given `GameType`. function testFuzz_create_noImpl_reverts( uint8 gameType, Claim rootClaim, @@ -86,9 +82,7 @@ contract DisputeGameFactory_Create_Test is DisputeGameFactory_Init { factory.create(gt, rootClaim, extraData); } - /** - * @dev Tests that the `create` function reverts when there exists a dispute game with the same UUID. - */ + /// @dev Tests that the `create` function reverts when there exists a dispute game with the same UUID. function testFuzz_create_sameUUID_reverts( uint8 gameType, Claim rootClaim, @@ -124,9 +118,7 @@ contract DisputeGameFactory_Create_Test is DisputeGameFactory_Init { } contract DisputeGameFactory_SetImplementation_Test is DisputeGameFactory_Init { - /** - * @dev Tests that the `setImplementation` function properly sets the implementation for a given `GameType`. - */ + /// @dev Tests that the `setImplementation` function properly sets the implementation for a given `GameType`. function test_setImplementation_succeeds() public { // There should be no implementation for the `GameTypes.FAULT` enum value, it has not been set. assertEq(address(factory.gameImpls(GameTypes.FAULT)), address(0)); @@ -141,9 +133,7 @@ contract DisputeGameFactory_SetImplementation_Test is DisputeGameFactory_Init { assertEq(address(factory.gameImpls(GameTypes.FAULT)), address(1)); } - /** - * @dev Tests that the `setImplementation` function reverts when called by a non-owner. - */ + /// @dev Tests that the `setImplementation` function reverts when called by a non-owner. function test_setImplementation_notOwner_reverts() public { // Ensure that the `setImplementation` function reverts when called by a non-owner. vm.prank(address(0)); @@ -153,10 +143,8 @@ contract DisputeGameFactory_SetImplementation_Test is DisputeGameFactory_Init { } contract DisputeGameFactory_GetGameUUID_Test is DisputeGameFactory_Init { - /** - * @dev Tests that the `getGameUUID` function returns the correct hash when comparing - * against the keccak256 hash of the abi-encoded parameters. - */ + /// @dev Tests that the `getGameUUID` function returns the correct hash when comparing + /// against the keccak256 hash of the abi-encoded parameters. function testDiff_getGameUUID_succeeds( uint8 gameType, Claim rootClaim, @@ -173,26 +161,20 @@ contract DisputeGameFactory_GetGameUUID_Test is DisputeGameFactory_Init { } contract DisputeGameFactory_Owner_Test is DisputeGameFactory_Init { - /** - * @dev Tests that the `owner` function returns the correct address after deployment. - */ + /// @dev Tests that the `owner` function returns the correct address after deployment. function test_owner_succeeds() public { assertEq(factory.owner(), address(this)); } } contract DisputeGameFactory_TransferOwnership_Test is DisputeGameFactory_Init { - /** - * @dev Tests that the `transferOwnership` function succeeds when called by the owner. - */ + /// @dev Tests that the `transferOwnership` function succeeds when called by the owner. function test_transferOwnership_succeeds() public { factory.transferOwnership(address(1)); assertEq(factory.owner(), address(1)); } - /** - * @dev Tests that the `transferOwnership` function reverts when called by a non-owner. - */ + /// @dev Tests that the `transferOwnership` function reverts when called by a non-owner. function test_transferOwnership_notOwner_reverts() public { vm.prank(address(0)); vm.expectRevert("Ownable: caller is not the owner"); @@ -200,11 +182,9 @@ contract DisputeGameFactory_TransferOwnership_Test is DisputeGameFactory_Init { } } -/** - * @title PackingTester - * @notice Exposes the internal packing functions so that they can be fuzzed - * in a roundtrip manner. - */ +/// @title PackingTester +/// @notice Exposes the internal packing functions so that they can be fuzzed +/// in a roundtrip manner. contract PackingTester is DisputeGameFactory { function packSlot(address _addr, uint256 _num) external pure returns (GameId) { return _packSlot(_addr, _num); @@ -215,10 +195,8 @@ contract PackingTester is DisputeGameFactory { } } -/** - * @title DisputeGameFactory_PackSlot_Test - * @notice Fuzzes the PackingTester contract - */ +/// @title DisputeGameFactory_PackSlot_Test +/// @notice Fuzzes the PackingTester contract contract DisputeGameFactory_PackSlot_Test is Test { PackingTester tester; @@ -226,9 +204,7 @@ contract DisputeGameFactory_PackSlot_Test is Test { tester = new PackingTester(); } - /** - * @dev Tests that the `packSlot` and `unpackSlot` functions roundtrip correctly. - */ + /// @dev Tests that the `packSlot` and `unpackSlot` functions roundtrip correctly. function testFuzz_packSlot_succeeds(address _addr, uint96 _num) public { GameId slot = tester.packSlot(_addr, uint256(_num)); (address addr, uint256 num) = tester.unpackSlot(slot); @@ -237,9 +213,7 @@ contract DisputeGameFactory_PackSlot_Test is Test { } } -/** - * @dev A fake clone used for testing the `DisputeGameFactory` contract's `create` function. - */ +/// @dev A fake clone used for testing the `DisputeGameFactory` contract's `create` function. contract FakeClone { function initialize() external { // noop diff --git a/packages/contracts-bedrock/contracts/test/FaultDisputeGame.t.sol b/packages/contracts-bedrock/contracts/test/FaultDisputeGame.t.sol index 748411d5e2ed..21b001708b5a 100644 --- a/packages/contracts-bedrock/contracts/test/FaultDisputeGame.t.sol +++ b/packages/contracts-bedrock/contracts/test/FaultDisputeGame.t.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.15; import { Test } from "forge-std/Test.sol"; +import { Vm } from "forge-std/Vm.sol"; import { DisputeGameFactory_Init } from "./DisputeGameFactory.t.sol"; import { DisputeGameFactory } from "../dispute/DisputeGameFactory.sol"; import { FaultDisputeGame } from "../dispute/FaultDisputeGame.sol"; @@ -11,90 +12,68 @@ import "../libraries/DisputeErrors.sol"; import { LibClock } from "../dispute/lib/LibClock.sol"; import { LibPosition } from "../dispute/lib/LibPosition.sol"; -contract FaultDisputeGame_Test is DisputeGameFactory_Init { - /** - * @dev The root claim of the game. - */ - Claim internal constant ROOT_CLAIM = Claim.wrap(bytes32(uint256(10))); - /** - * @dev The extra data passed to the game for initialization. - */ +contract FaultDisputeGame_Init is DisputeGameFactory_Init { + /// @dev The extra data passed to the game for initialization. bytes internal constant EXTRA_DATA = abi.encode(1); - /** - * @dev The type of the game being tested. - */ + /// @dev The type of the game being tested. GameType internal constant GAME_TYPE = GameType.wrap(0); - /** - * @dev The current version of the `FaultDisputeGame` contract. - */ - string internal constant VERSION = "0.0.1"; - - /** - * @dev The implementation of the game. - */ + + /// @dev The implementation of the game. FaultDisputeGame internal gameImpl; - /** - * @dev The `Clone` proxy of the game. - */ + /// @dev The `Clone` proxy of the game. FaultDisputeGame internal gameProxy; event Move(uint256 indexed parentIndex, Claim indexed pivot, address indexed claimant); - function setUp() public override { + function init(Claim rootClaim, Claim absolutePrestate) public { super.setUp(); // Deploy an implementation of the fault game - gameImpl = new FaultDisputeGame(); + gameImpl = new FaultDisputeGame(absolutePrestate, 4); // Register the game implementation with the factory. factory.setImplementation(GAME_TYPE, gameImpl); // Create a new game. - gameProxy = FaultDisputeGame(address(factory.create(GAME_TYPE, ROOT_CLAIM, EXTRA_DATA))); + gameProxy = FaultDisputeGame(address(factory.create(GAME_TYPE, rootClaim, EXTRA_DATA))); // Label the proxy vm.label(address(gameProxy), "FaultDisputeGame_Clone"); } +} + +contract FaultDisputeGame_Test is FaultDisputeGame_Init { + /// @dev The root claim of the game. + Claim internal constant ROOT_CLAIM = Claim.wrap(bytes32(uint256(10))); + /// @dev The absolute prestate of the trace. + Claim internal constant ABSOLUTE_PRESTATE = Claim.wrap(bytes32(uint256(0))); + + function setUp() public override { + super.init(ROOT_CLAIM, ABSOLUTE_PRESTATE); + } //////////////////////////////////////////////////////////////// // `IDisputeGame` Implementation Tests // //////////////////////////////////////////////////////////////// - /** - * @dev Tests that the game's root claim is set correctly. - */ + /// @dev Tests that the game's root claim is set correctly. function test_rootClaim_succeeds() public { assertEq(Claim.unwrap(gameProxy.rootClaim()), Claim.unwrap(ROOT_CLAIM)); } - /** - * @dev Tests that the game's extra data is set correctly. - */ + /// @dev Tests that the game's extra data is set correctly. function test_extraData_succeeds() public { assertEq(gameProxy.extraData(), EXTRA_DATA); } - /** - * @dev Tests that the game's version is set correctly. - */ - function test_version_succeeds() public { - assertEq(gameProxy.version(), VERSION); - } - - /** - * @dev Tests that the game's status is set correctly. - */ + /// @dev Tests that the game's status is set correctly. function test_gameStart_succeeds() public { assertEq(Timestamp.unwrap(gameProxy.gameStart()), block.timestamp); } - /** - * @dev Tests that the game's type is set correctly. - */ + /// @dev Tests that the game's type is set correctly. function test_gameType_succeeds() public { assertEq(GameType.unwrap(gameProxy.gameType()), GameType.unwrap(GAME_TYPE)); } - /** - * @dev Tests that the game's data is set correctly. - */ + /// @dev Tests that the game's data is set correctly. function test_gameData_succeeds() public { (GameType gameType, Claim rootClaim, bytes memory extraData) = gameProxy.gameData(); @@ -107,9 +86,7 @@ contract FaultDisputeGame_Test is DisputeGameFactory_Init { // `IFaultDisputeGame` Implementation Tests // //////////////////////////////////////////////////////////////// - /** - * @dev Tests that the root claim's data is set correctly when the game is initialized. - */ + /// @dev Tests that the root claim's data is set correctly when the game is initialized. function test_initialRootClaimData_succeeds() public { ( uint32 parentIndex, @@ -129,10 +106,8 @@ contract FaultDisputeGame_Test is DisputeGameFactory_Init { ); } - /** - * @dev Tests that a move while the game status is not `IN_PROGRESS` causes the call to revert - * with the `GameNotInProgress` error - */ + /// @dev Tests that a move while the game status is not `IN_PROGRESS` causes the call to revert + /// with the `GameNotInProgress` error function test_move_gameNotInProgress_reverts() public { uint256 chalWins = uint256(GameStatus.CHALLENGER_WINS); @@ -153,19 +128,15 @@ contract FaultDisputeGame_Test is DisputeGameFactory_Init { gameProxy.attack(0, Claim.wrap(0)); } - /** - * @dev Tests that an attempt to defend the root claim reverts with the `CannotDefendRootClaim` error. - */ - function test_defendRoot_reverts() public { + /// @dev Tests that an attempt to defend the root claim reverts with the `CannotDefendRootClaim` error. + function test_defendRoot_invalidMove_reverts() public { vm.expectRevert(CannotDefendRootClaim.selector); gameProxy.defend(0, Claim.wrap(bytes32(uint256(5)))); } - /** - * @dev Tests that an attempt to move against a claim that does not exist reverts with the - * `ParentDoesNotExist` error. - */ - function test_moveAgainstNonexistentParent_reverts() public { + /// @dev Tests that an attempt to move against a claim that does not exist reverts with the + /// `ParentDoesNotExist` error. + function test_move_nonExistentParent_reverts() public { Claim claim = Claim.wrap(bytes32(uint256(5))); // Expect an out of bounds revert for an attack @@ -177,39 +148,35 @@ contract FaultDisputeGame_Test is DisputeGameFactory_Init { gameProxy.defend(1, claim); } - /** - * @dev Tests that an attempt to move at the maximum game depth reverts with the - * `GameDepthExceeded` error. - */ - function test_gameDepthExceeded_reverts() public { + /// @dev Tests that an attempt to move at the maximum game depth reverts with the + /// `GameDepthExceeded` error. + function test_move_gameDepthExceeded_reverts() public { Claim claim = Claim.wrap(bytes32(uint256(5))); - for (uint256 i = 0; i < 63; i++) { + uint256 maxDepth = gameProxy.MAX_GAME_DEPTH(); + + for (uint256 i = 0; i <= maxDepth; i++) { // At the max game depth, the `_move` function should revert with // the `GameDepthExceeded` error. - if (i == 62) { + if (i == maxDepth) { vm.expectRevert(GameDepthExceeded.selector); } gameProxy.attack(i, claim); } } - /** - * @dev Tests that a move made after the clock time has exceeded reverts with the - * `ClockTimeExceeded` error. - */ - function test_clockTimeExceeded_reverts() public { + /// @dev Tests that a move made after the clock time has exceeded reverts with the + /// `ClockTimeExceeded` error. + function test_move_clockTimeExceeded_reverts() public { // Warp ahead past the clock time for the first move (3 1/2 days) vm.warp(block.timestamp + 3 days + 12 hours + 1); vm.expectRevert(ClockTimeExceeded.selector); gameProxy.attack(0, Claim.wrap(bytes32(uint256(5)))); } - /** - * @dev Tests that an identical claim cannot be made twice. The duplicate claim attempt should - * revert with the `ClaimAlreadyExists` error. - */ - function test_duplicateClaim_reverts() public { + /// @dev Tests that an identical claim cannot be made twice. The duplicate claim attempt should + /// revert with the `ClaimAlreadyExists` error. + function test_move_duplicateClaim_reverts() public { Claim claim = Claim.wrap(bytes32(uint256(5))); // Make the first move. This should succeed. @@ -220,9 +187,7 @@ contract FaultDisputeGame_Test is DisputeGameFactory_Init { gameProxy.attack(0, claim); } - /** - * @dev Static unit test for the correctness of an opening attack. - */ + /// @dev Static unit test for the correctness of an opening attack. function test_simpleAttack_succeeds() public { // Warp ahead 5 seconds. vm.warp(block.timestamp + 5); @@ -247,7 +212,7 @@ contract FaultDisputeGame_Test is DisputeGameFactory_Init { assertEq(parentIndex, 0); assertEq(countered, false); assertEq(Claim.unwrap(claim), Claim.unwrap(counter)); - assertEq(Position.unwrap(position), Position.unwrap(Position.wrap(1).attack())); + assertEq(Position.unwrap(position), Position.unwrap(Position.wrap(1).move(true))); assertEq( Clock.unwrap(clock), Clock.unwrap(LibClock.wrap(Duration.wrap(5), Timestamp.wrap(uint64(block.timestamp)))) @@ -269,27 +234,31 @@ contract FaultDisputeGame_Test is DisputeGameFactory_Init { ); } - /** - * @dev Static unit test for the correctness an uncontested root resolution. - */ + /// @dev Static unit test for the correctness an uncontested root resolution. function test_resolve_rootUncontested() public { GameStatus status = gameProxy.resolve(); assertEq(uint8(status), uint8(GameStatus.DEFENDER_WINS)); assertEq(uint8(gameProxy.status()), uint8(GameStatus.DEFENDER_WINS)); } - /** - * @dev Static unit test asserting that resolve reverts when the game is not in progress. - */ - function test_resolve_reverts() public { - gameProxy.resolve(); + /// @dev Static unit test asserting that resolve reverts when the game state is + /// not in progress. + function test_resolve_notInProgress_reverts() public { + uint256 chalWins = uint256(GameStatus.CHALLENGER_WINS); + + // Replace the game status in storage. It exists in slot 0 at offset 8. + uint256 slot = uint256(vm.load(address(gameProxy), bytes32(0))); + uint256 offset = (8 << 3); + uint256 mask = 0xFF << offset; + // Replace the byte in the slot value with the challenger wins status. + slot = (slot & ~mask) | (chalWins << offset); + + vm.store(address(gameProxy), bytes32(uint256(0)), bytes32(slot)); vm.expectRevert(GameNotInProgress.selector); gameProxy.resolve(); } - /** - * @dev Static unit test for the correctness of resolving a single attack game state. - */ + /// @dev Static unit test for the correctness of resolving a single attack game state. function test_resolve_rootContested() public { gameProxy.attack(0, Claim.wrap(bytes32(uint256(5)))); @@ -298,9 +267,7 @@ contract FaultDisputeGame_Test is DisputeGameFactory_Init { assertEq(uint8(gameProxy.status()), uint8(GameStatus.CHALLENGER_WINS)); } - /** - * @dev Static unit test for the correctness of resolving a game with a contested challenge claim. - */ + /// @dev Static unit test for the correctness of resolving a game with a contested challenge claim. function test_resolve_challengeContested() public { gameProxy.attack(0, Claim.wrap(bytes32(uint256(5)))); gameProxy.defend(1, Claim.wrap(bytes32(uint256(6)))); @@ -310,9 +277,7 @@ contract FaultDisputeGame_Test is DisputeGameFactory_Init { assertEq(uint8(gameProxy.status()), uint8(GameStatus.DEFENDER_WINS)); } - /** - * @dev Static unit test for the correctness of resolving a game with multiplayer moves. - */ + /// @dev Static unit test for the correctness of resolving a game with multiplayer moves. function test_resolve_teamDeathmatch() public { gameProxy.attack(0, Claim.wrap(bytes32(uint256(5)))); gameProxy.attack(0, Claim.wrap(bytes32(uint256(4)))); @@ -325,35 +290,370 @@ contract FaultDisputeGame_Test is DisputeGameFactory_Init { } } -/** - * @title BigStepper - * @notice A mock fault proof processor contract for testing purposes. - *⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ - *⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⠶⢅⠒⢄⢔⣶⡦⣤⡤⠄⣀⠀⠀⠀⠀⠀⠀⠀ - *⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠨⡏⠀⠀⠈⠢⣙⢯⣄⠀⢨⠯⡺⡘⢄⠀⠀⠀⠀⠀ - *⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣶⡆⠀⠀⠀⠀⠈⠓⠬⡒⠡⣀⢙⡜⡀⠓⠄⠀⠀⠀ - *⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡷⠿⣧⣀⡀⠀⠀⠀⠀⠀⠀⠉⠣⣞⠩⠥⠀⠼⢄⠀⠀ - *⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⠀⠀⠉⢹⣶⠒⠒⠂⠈⠉⠁⠘⡆⠀⣿⣿⠫⡄⠀ - *⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⢶⣤⣀⡀⠀⠀⢸⡿⠀⠀⠀⠀⠀⢀⠞⠀⠀⢡⢨⢀⡄⠀ - *⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⡒⣿⢿⡤⠝⡣⠉⠁⠚⠛⠀⠤⠤⣄⡰⠁⠀⠀⠀⠉⠙⢸⠀⠀ - *⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡤⢯⡌⡿⡇⠘⡷⠀⠁⠀⠀⢀⣰⠢⠲⠛⣈⣸⠦⠤⠶⠴⢬⣐⣊⡂⠀ - *⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⡪⡗⢫⠞⠀⠆⣀⠻⠤⠴⠐⠚⣉⢀⠦⠂⠋⠁⠀⠁⠀⠀⠀⠀⢋⠉⠇⠀ - *⠀⠀⠀⠀⣀⡤⠐⠒⠘⡹⠉⢸⠇⠸⠀⠀⠀⠀⣀⣤⠴⠚⠉⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠼⠀⣾⠀ - *⠀⠀⠀⡰⠀⠉⠉⠀⠁⠀⠀⠈⢇⠈⠒⠒⠘⠈⢀⢡⡂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠀⢸⡄ - *⠀⠀⠸⣿⣆⠤⢀⡀⠀⠀⠀⠀⢘⡌⠀⠀⣀⣀⣀⡈⣤⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⢸⡇ - *⠀⠀⢸⣀⠀⠉⠒⠐⠛⠋⠭⠭⠍⠉⠛⠒⠒⠒⠀⠒⠚⠛⠛⠛⠩⠭⠭⠭⠭⠤⠤⠤⠤⠤⠭⠭⠉⠓⡆ - *⠀⠀⠘⠿⣷⣶⣤⣤⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇ - *⠀⠀⠀⠀⠀⠉⠙⠛⠛⠻⠿⢿⣿⣿⣷⣶⣶⣶⣤⣤⣀⣁⣛⣃⣒⠿⠿⠿⠤⠠⠄⠤⠤⢤⣛⣓⣂⣻⡇ - *⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠙⠛⠻⠿⠿⠿⢿⣿⣿⣿⣷⣶⣶⣾⣿⣿⣿⣿⠿⠟⠁ - *⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀ - */ -contract BigStepper { - /** - * @notice Steps from the `preState` to the `postState` by adding 1 to the `preState`. - * @param preState The pre state to start from - * @return postState The state stepped to - */ - function step(Claim preState) external pure returns (Claim postState) { - postState = Claim.wrap(bytes32(uint256(Claim.unwrap(preState)) + 1)); +/// @notice A generic game player actor with a configurable trace. +/// @dev This actor always responds rationally with respect to their trace. The +/// `play` function can be overridden to change this behavior. +contract GamePlayer { + bool public failedToStep; + FaultDisputeGame public gameProxy; + + GamePlayer internal counterParty; + Vm internal vm; + bytes internal trace; + uint256 internal maxDepth; + + /// @notice Initializes the player + function init( + FaultDisputeGame _gameProxy, + GamePlayer _counterParty, + Vm _vm + ) public virtual { + gameProxy = _gameProxy; + counterParty = _counterParty; + vm = _vm; + maxDepth = _gameProxy.MAX_GAME_DEPTH(); + } + + /// @notice Perform the next move in the game. + function play(uint256 _parentIndex) public virtual { + // Grab the claim data at the parent index. + (uint32 grandparentIndex, , Claim parentClaim, Position parentPos, ) = gameProxy.claimData( + _parentIndex + ); + + // The position to move to. + Position movePos; + // May or may not be used. + Position movePos2; + // Signifies whether the move is an attack or not. + bool isAttack; + + if (grandparentIndex == type(uint32).max) { + // If the parent claim is the root claim, begin by attacking. + movePos = parentPos.move(true); + // Flag the move as an attack. + isAttack = true; + } else { + // If the parent claim is not the root claim, check if we disagree with it and/or its grandparent + // to determine our next move(s). + + // Fetch our claim at the parent's position. + Claim ourParentClaim = claimAt(parentPos); + + // Fetch our claim at the grandparent's position. + (, , Claim grandparentClaim, Position grandparentPos, ) = gameProxy.claimData( + grandparentIndex + ); + Claim ourGrandparentClaim = claimAt(grandparentPos); + + if (Claim.unwrap(ourParentClaim) != Claim.unwrap(parentClaim)) { + // Attack parent. + movePos = parentPos.move(true); + // If we also disagree with the grandparent, attack it as well. + if (Claim.unwrap(ourGrandparentClaim) != Claim.unwrap(grandparentClaim)) { + movePos2 = grandparentPos.move(true); + } + + // Flag the move as an attack. + isAttack = true; + } else if ( + Claim.unwrap(ourParentClaim) == Claim.unwrap(parentClaim) && + Claim.unwrap(ourGrandparentClaim) == Claim.unwrap(grandparentClaim) + ) { + movePos = parentPos.move(false); + } + } + + // If we are past the maximum depth, break the recursion and step. + if (movePos.depth() > maxDepth) { + // Perform a step. + uint256 stateIndex; + // First, we need to find the pre/post state index depending on whether we + // are making an attack step or a defense step. If the index at depth of the + // move position is 0, the prestate is the absolute prestate and we need to + // do nothing. + if (movePos.indexAtDepth() > 0) { + Position leafPos = isAttack + ? Position.wrap(Position.unwrap(parentPos) - 1) + : Position.wrap(Position.unwrap(parentPos) + 1); + Position statePos = leafPos; + + // Walk up until the valid position that commits to the prestate's + // trace index is found. + while ( + Position.unwrap(statePos.parent().rightIndex(maxDepth)) == + Position.unwrap(leafPos) + ) { + statePos = statePos.parent(); + } + + // Now, search for the index of the claim that commits to the prestate's trace + // index. + uint256 len = claimDataLen(); + for (uint256 i = 0; i < len; i++) { + (, , , Position pos, ) = gameProxy.claimData(i); + if (Position.unwrap(pos) == Position.unwrap(statePos)) { + stateIndex = i; + break; + } + } + } + + // Perform the step and halt recursion. + try gameProxy.step(stateIndex, _parentIndex, isAttack, hex"", hex"") { + // Do nothing, step succeeded. + } catch { + failedToStep = true; + } + } else { + // Find the trace index that our next claim must commit to. + uint256 traceIndex = movePos.rightIndex(maxDepth).indexAtDepth(); + // Grab the claim that we need to make from the helper. + Claim ourClaim = claimAt(traceIndex); + + if (isAttack) { + // Attack the parent claim. + gameProxy.attack(_parentIndex, ourClaim); + // Call out to our counter party to respond. + counterParty.play(claimDataLen() - 1); + + // If we have a second move position, attack the grandparent. + if (Position.unwrap(movePos2) != 0) { + (, , , Position grandparentPos, ) = gameProxy.claimData(grandparentIndex); + Claim ourGrandparentClaim = claimAt(grandparentPos.move(true)); + + gameProxy.attack(grandparentIndex, ourGrandparentClaim); + counterParty.play(claimDataLen() - 1); + } + } else { + // Defend the parent claim. + gameProxy.defend(_parentIndex, ourClaim); + // Call out to our counter party to respond. + counterParty.play(claimDataLen() - 1); + } + } + } + + /// @notice Returns the length of the claim data array. + function claimDataLen() internal view returns (uint256 len_) { + return uint256(vm.load(address(gameProxy), bytes32(uint256(1)))); + } + + /// @notice Returns the player's claim that commits to a given gindex. + function claimAt(Position _position) internal view returns (Claim claim_) { + return claimAt(_position.rightIndex(maxDepth).indexAtDepth()); + } + + /// @notice Returns the player's claim that commits to a given trace index. + function claimAt(uint256 _traceIndex) public view returns (Claim claim_) { + return Claim.wrap(bytes32(uint256(bytes32(trace[_traceIndex]) >> 248))); + } +} + +contract OneVsOne_Arena is FaultDisputeGame_Init { + /// @dev The absolute prestate of the trace. + Claim internal constant ABSOLUTE_PRESTATE = Claim.wrap(bytes32(uint256(15))); + /// @dev The honest participant. + GamePlayer internal honest; + /// @dev The dishonest participant. + GamePlayer internal dishonest; + + function init( + GamePlayer _honest, + GamePlayer _dishonest, + Claim _rootClaim + ) public { + super.init(_rootClaim, ABSOLUTE_PRESTATE); + // Deploy a new honest player. + honest = _honest; + // Deploy a new dishonest player. + dishonest = _dishonest; + + // Set the counterparties. + honest.init(gameProxy, dishonest, vm); + dishonest.init(gameProxy, honest, vm); + + // Label actors for trace. + vm.label(address(honest), "HonestPlayer"); + vm.label(address(dishonest), "DishonestPlayer"); + } +} + +contract FaultDisputeGame_ResolvesCorrectly_IncorrectRoot is OneVsOne_Arena { + function setUp() public override { + GamePlayer honest = new HonestPlayer(); + GamePlayer dishonest = new FullyDivergentPlayer(); + super.init(honest, dishonest, Claim.wrap(bytes32(uint256(30)))); + } + + function test_resolvesCorrectly_succeeds() public { + // Play the game until a step is forced. + honest.play(0); + + // Resolve the game and assert that the honest player challenged the root + // claim successfully. + assertEq(uint8(gameProxy.resolve()), uint8(GameStatus.CHALLENGER_WINS)); + assertFalse(honest.failedToStep()); + } +} + +contract FaultDisputeGame_ResolvesCorrectly_CorrectRoot is OneVsOne_Arena { + function setUp() public override { + GamePlayer honest = new HonestPlayer(); + GamePlayer dishonest = new FullyDivergentPlayer(); + super.init(honest, dishonest, Claim.wrap(bytes32(uint256(31)))); + } + + function test_resolvesCorrectly_succeeds() public { + // Play the game until a step is forced. + dishonest.play(0); + + // Resolve the game and assert that the dishonest player challenged the root + // claim unsuccessfully. + assertEq(uint8(gameProxy.resolve()), uint8(GameStatus.DEFENDER_WINS)); + assertTrue(dishonest.failedToStep()); + } +} + +contract FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2 is OneVsOne_Arena { + function setUp() public override { + GamePlayer honest = new HonestPlayer(); + GamePlayer dishonest = new HalfDivergentPlayer(); + super.init(honest, dishonest, Claim.wrap(bytes32(uint256(15)))); + } + + function test_resolvesCorrectly_succeeds() public { + // Play the game until a step is forced. + honest.play(0); + + // Resolve the game and assert that the honest player challenged the root + // claim successfully. + assertEq(uint8(gameProxy.resolve()), uint8(GameStatus.CHALLENGER_WINS)); + assertFalse(honest.failedToStep()); + } +} + +contract FaultDisputeGame_ResolvesCorrectly_CorrectRoot2 is OneVsOne_Arena { + function setUp() public override { + GamePlayer honest = new HonestPlayer(); + GamePlayer dishonest = new HalfDivergentPlayer(); + super.init(honest, dishonest, Claim.wrap(bytes32(uint256(31)))); + } + + function test_resolvesCorrectly_succeeds() public { + // Play the game until a step is forced. + dishonest.play(0); + + // Resolve the game and assert that the dishonest player challenged the root + // claim unsuccessfully. + assertEq(uint8(gameProxy.resolve()), uint8(GameStatus.DEFENDER_WINS)); + assertTrue(dishonest.failedToStep()); + } +} + +contract FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3 is OneVsOne_Arena { + function setUp() public override { + GamePlayer honest = new HonestPlayer(); + GamePlayer dishonest = new EarlyDivergentPlayer(); + super.init(honest, dishonest, Claim.wrap(bytes32(uint256(15)))); + } + + function test_resolvesCorrectly_succeeds() public { + // Play the game until a step is forced. + honest.play(0); + + // Resolve the game and assert that the honest player challenged the root + // claim successfully. + assertEq(uint8(gameProxy.resolve()), uint8(GameStatus.CHALLENGER_WINS)); + assertFalse(honest.failedToStep()); + } +} + +contract FaultDisputeGame_ResolvesCorrectly_CorrectRoot4 is OneVsOne_Arena { + function setUp() public override { + GamePlayer honest = new HonestPlayer(); + GamePlayer dishonest = new EarlyDivergentPlayer(); + super.init(honest, dishonest, Claim.wrap(bytes32(uint256(31)))); + } + + function test_resolvesCorrectly_succeeds() public { + // Play the game until a step is forced. + dishonest.play(0); + + // Resolve the game and assert that the dishonest player challenged the root + // claim unsuccessfully. + assertEq(uint8(gameProxy.resolve()), uint8(GameStatus.DEFENDER_WINS)); + assertTrue(dishonest.failedToStep()); + } +} + +//////////////////////////////////////////////////////////////// +// ACTORS // +//////////////////////////////////////////////////////////////// + +contract HonestPlayer is GamePlayer { + function init( + FaultDisputeGame _gameProxy, + GamePlayer _counterParty, + Vm _vm + ) public virtual override { + super.init(_gameProxy, _counterParty, _vm); + uint8 absolutePrestate = uint8(uint256(Claim.unwrap(_gameProxy.ABSOLUTE_PRESTATE()))); + bytes memory honestTrace = new bytes(16); + for (uint8 i = 0; i < honestTrace.length; i++) { + honestTrace[i] = bytes1(absolutePrestate + i + 1); + } + trace = honestTrace; + } +} + +contract FullyDivergentPlayer is GamePlayer { + function init( + FaultDisputeGame _gameProxy, + GamePlayer _counterParty, + Vm _vm + ) public virtual override { + super.init(_gameProxy, _counterParty, _vm); + uint8 absolutePrestate = uint8(uint256(Claim.unwrap(_gameProxy.ABSOLUTE_PRESTATE()))); + bytes memory dishonestTrace = new bytes(16); + for (uint8 i = 0; i < dishonestTrace.length; i++) { + // Offset the honest trace by 1. + dishonestTrace[i] = bytes1(absolutePrestate + i); + } + trace = dishonestTrace; + } +} + +contract HalfDivergentPlayer is GamePlayer { + function init( + FaultDisputeGame _gameProxy, + GamePlayer _counterParty, + Vm _vm + ) public virtual override { + super.init(_gameProxy, _counterParty, _vm); + uint8 absolutePrestate = uint8(uint256(Claim.unwrap(_gameProxy.ABSOLUTE_PRESTATE()))); + bytes memory dishonestTrace = new bytes(16); + for (uint8 i = 0; i < dishonestTrace.length; i++) { + // Offset the trace after the first half. + dishonestTrace[i] = i > 7 ? bytes1(i) : bytes1(absolutePrestate + i + 1); + } + trace = dishonestTrace; + } +} + +contract EarlyDivergentPlayer is GamePlayer { + function init( + FaultDisputeGame _gameProxy, + GamePlayer _counterParty, + Vm _vm + ) public virtual override { + super.init(_gameProxy, _counterParty, _vm); + uint8 absolutePrestate = uint8(uint256(Claim.unwrap(_gameProxy.ABSOLUTE_PRESTATE()))); + bytes memory dishonestTrace = new bytes(16); + for (uint8 i = 0; i < dishonestTrace.length; i++) { + // Offset the trace after the first half. + dishonestTrace[i] = i > 2 ? bytes1(i) : bytes1(absolutePrestate + i + 1); + } + trace = dishonestTrace; } } diff --git a/packages/contracts-bedrock/contracts/test/L1CrossDomainMessenger.t.sol b/packages/contracts-bedrock/contracts/test/L1CrossDomainMessenger.t.sol index 78b3a7225b28..a97e56178019 100644 --- a/packages/contracts-bedrock/contracts/test/L1CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/contracts/test/L1CrossDomainMessenger.t.sol @@ -1,39 +1,39 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -/* Testing utilities */ +// Testing utilities import { Messenger_Initializer, Reverter, ConfigurableCaller } from "./CommonTest.t.sol"; import { L2OutputOracle_Initializer } from "./L2OutputOracle.t.sol"; -/* Libraries */ +// Libraries import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol"; import { Predeploys } from "../libraries/Predeploys.sol"; import { Hashing } from "../libraries/Hashing.sol"; import { Encoding } from "../libraries/Encoding.sol"; -/* Target contract dependencies */ +// Target contract dependencies import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; import { OptimismPortal } from "../L1/OptimismPortal.sol"; -/* Target contract */ +// Target contract import { L1CrossDomainMessenger } from "../L1/L1CrossDomainMessenger.sol"; contract L1CrossDomainMessenger_Test is Messenger_Initializer { - // Receiver address for testing + /// @dev The receiver address address recipient = address(0xabbaacdc); - // Storage slot of the l2Sender + /// @dev The storage slot of the l2Sender uint256 constant senderSlotIndex = 50; - // the version is encoded in the nonce + /// @dev Tests that the version can be decoded from the message nonce. function test_messageVersion_succeeds() external { (, uint16 version) = Encoding.decodeVersionedNonce(L1Messenger.messageNonce()); assertEq(version, L1Messenger.MESSAGE_VERSION()); } - // sendMessage: should be able to send a single message - // TODO: this same test needs to be done with the legacy message type - // by setting the message version to 0 + /// @dev Tests that the sendMessage function is able to send a single message. + /// TODO: this same test needs to be done with the legacy message type + /// by setting the message version to 0 function test_sendMessage_succeeds() external { // deposit transaction on the optimism portal should be called vm.expectCall( @@ -86,7 +86,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { L1Messenger.sendMessage(recipient, hex"ff", uint32(100)); } - // sendMessage: should be able to send the same message twice + /// @dev Tests that the sendMessage function is able to send + /// the same message twice. function test_sendMessage_twice_succeeds() external { uint256 nonce = L1Messenger.messageNonce(); L1Messenger.sendMessage(recipient, hex"aa", uint32(500_000)); @@ -95,11 +96,14 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { assertEq(nonce + 2, L1Messenger.messageNonce()); } + /// @dev Tests that the xDomainMessageSender reverts when not set. function test_xDomainSender_notSet_reverts() external { vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set"); L1Messenger.xDomainMessageSender(); } + /// @dev Tests that the relayMessage function reverts when + /// the message version is not 0 or 1. function test_relayMessage_v2_reverts() external { address target = address(0xabcd); address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; @@ -124,7 +128,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ); } - // relayMessage: should send a successful call to the target contract + /// @dev Tests that the relayMessage function is able to relay a message + /// successfully by calling the target contract. function test_relayMessage_succeeds() external { address target = address(0xabcd); address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; @@ -163,7 +168,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { assertEq(L1Messenger.failedMessages(hash), false); } - // relayMessage: should revert if attempting to relay a message sent to an L1 system contract + /// @dev Tests that relayMessage reverts if attempting to relay a message + /// sent to an L1 system contract. function test_relayMessage_toSystemContract_reverts() external { // set the target to be the OptimismPortal address target = address(op); @@ -193,7 +199,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ); } - // relayMessage: should revert if eth is sent from a contract other than the standard bridge + /// @dev Tests that the relayMessage function reverts if eth is + /// sent from a contract other than the standard bridge. function test_replayMessage_withValue_reverts() external { address target = address(0xabcd); address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; @@ -212,7 +219,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ); } - // relayMessage: the xDomainMessageSender is reset to the original value + /// @dev Tests that the xDomainMessageSender is reset to the original value + /// after a message is relayed. function test_xDomainMessageSender_reset_succeeds() external { vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set"); L1Messenger.xDomainMessageSender(); @@ -234,8 +242,9 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { L1Messenger.xDomainMessageSender(); } - // relayMessage: should send a successful call to the target contract after the first message - // fails and ETH gets stuck, but the second message succeeds + /// @dev Tests that relayMessage should successfully call the target contract after + /// the first message fails and ETH is stuck, but the second message succeeds + /// with a version 1 message. function test_relayMessage_retryAfterFailure_succeeds() external { address target = address(0xabcd); address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; @@ -291,6 +300,9 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { assertEq(L1Messenger.failedMessages(hash), true); } + /// @dev Tests that relayMessage should successfully call the target contract after + /// the first message fails and ETH is stuck, but the second message succeeds + /// with a legacy message. function test_relayMessage_legacy_succeeds() external { address target = address(0xabcd); address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; @@ -332,6 +344,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { assertEq(L1Messenger.failedMessages(hash), false); } + /// @dev Tests that relayMessage should revert if the message is already replayed. function test_relayMessage_legacyOldReplay_reverts() external { address target = address(0xabcd); address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; @@ -375,6 +388,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { assertEq(L1Messenger.failedMessages(hash), false); } + /// @dev Tests that relayMessage can be retried after a failure with a legacy message. function test_relayMessage_legacyRetryAfterFailure_succeeds() external { address target = address(0xabcd); address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; @@ -450,6 +464,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { assertEq(L1Messenger.failedMessages(hash), true); } + /// @dev Tests that relayMessage cannot be retried after success with a legacy message. function test_relayMessage_legacyRetryAfterSuccess_reverts() external { address target = address(0xabcd); address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; @@ -509,6 +524,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ); } + /// @dev Tests that relayMessage cannot be called after a failure and a successful replay. function test_relayMessage_legacyRetryAfterFailureThenSuccess_reverts() external { address target = address(0xabcd); address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; diff --git a/packages/contracts-bedrock/contracts/test/L1ERC721Bridge.t.sol b/packages/contracts-bedrock/contracts/test/L1ERC721Bridge.t.sol index 7651c59ff516..c59f8a4e647f 100644 --- a/packages/contracts-bedrock/contracts/test/L1ERC721Bridge.t.sol +++ b/packages/contracts-bedrock/contracts/test/L1ERC721Bridge.t.sol @@ -1,11 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +// Testing utilities import { Messenger_Initializer } from "./CommonTest.t.sol"; -import { L1ERC721Bridge } from "../L1/L1ERC721Bridge.sol"; +import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; + +// Target contract dependencies import { L2ERC721Bridge } from "../L2/L2ERC721Bridge.sol"; +// Target contract +import { L1ERC721Bridge } from "../L1/L1ERC721Bridge.sol"; + +/// @dev Test ERC721 contract. contract TestERC721 is ERC721 { constructor() ERC721("Test", "TST") {} @@ -39,6 +45,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { bytes extraData ); + /// @dev Sets up the testing environment. function setUp() public override { super.setUp(); @@ -58,6 +65,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { localToken.approve(address(bridge), tokenId); } + /// @dev Tests that the constructor sets the correct values. function test_constructor_succeeds() public { assertEq(address(bridge.MESSENGER()), address(L1Messenger)); assertEq(address(bridge.OTHER_BRIDGE()), otherBridge); @@ -65,6 +73,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { assertEq(address(bridge.otherBridge()), otherBridge); } + /// @dev Tests that the ERC721 can be bridged successfully. function test_bridgeERC721_succeeds() public { // Expect a call to the messenger. vm.expectCall( @@ -109,6 +118,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { assertEq(localToken.ownerOf(tokenId), address(bridge)); } + /// @dev Tests that the ERC721 bridge reverts for non externally owned accounts. function test_bridgeERC721_fromContract_reverts() external { // Bridge the token. vm.etch(alice, hex"01"); @@ -121,6 +131,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { assertEq(localToken.ownerOf(tokenId), alice); } + /// @dev Tests that the ERC721 bridge reverts for a zero address local token. function test_bridgeERC721_localTokenZeroAddress_reverts() external { // Bridge the token. vm.prank(alice); @@ -132,6 +143,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { assertEq(localToken.ownerOf(tokenId), alice); } + /// @dev Tests that the ERC721 bridge reverts for a zero address remote token. function test_bridgeERC721_remoteTokenZeroAddress_reverts() external { // Bridge the token. vm.prank(alice); @@ -143,6 +155,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { assertEq(localToken.ownerOf(tokenId), alice); } + /// @dev Tests that the ERC721 bridge reverts for an incorrect owner. function test_bridgeERC721_wrongOwner_reverts() external { // Bridge the token. vm.prank(bob); @@ -154,6 +167,8 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { assertEq(localToken.ownerOf(tokenId), alice); } + /// @dev Tests that the ERC721 bridge successfully sends a token + /// to a different address than the owner. function test_bridgeERC721To_succeeds() external { // Expect a call to the messenger. vm.expectCall( @@ -198,6 +213,8 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { assertEq(localToken.ownerOf(tokenId), address(bridge)); } + /// @dev Tests that the ERC721 bridge reverts for non externally owned accounts + /// when sending to a different address than the owner. function test_bridgeERC721To_localTokenZeroAddress_reverts() external { // Bridge the token. vm.prank(alice); @@ -209,6 +226,8 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { assertEq(localToken.ownerOf(tokenId), alice); } + /// @dev Tests that the ERC721 bridge reverts for a zero address remote token + /// when sending to a different address than the owner. function test_bridgeERC721To_remoteTokenZeroAddress_reverts() external { // Bridge the token. vm.prank(alice); @@ -220,6 +239,8 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { assertEq(localToken.ownerOf(tokenId), alice); } + /// @dev Tests that the ERC721 bridge reverts for an incorrect owner + //// when sending to a different address than the owner. function test_bridgeERC721To_wrongOwner_reverts() external { // Bridge the token. vm.prank(bob); @@ -238,6 +259,7 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { assertEq(localToken.ownerOf(tokenId), alice); } + /// @dev Tests that the ERC721 bridge successfully finalizes a withdrawal. function test_finalizeBridgeERC721_succeeds() external { // Bridge the token. vm.prank(alice); @@ -275,6 +297,8 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { assertEq(localToken.ownerOf(tokenId), alice); } + /// @dev Tests that the ERC721 bridge finalize reverts when not called + /// by the remote bridge. function test_finalizeBridgeERC721_notViaLocalMessenger_reverts() external { // Finalize a withdrawal. vm.prank(alice); @@ -289,6 +313,8 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ); } + /// @dev Tests that the ERC721 bridge finalize reverts when not called + /// from the remote messenger. function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external { // Finalize a withdrawal. vm.mockCall( @@ -308,6 +334,8 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ); } + /// @dev Tests that the ERC721 bridge finalize reverts when the local token + /// is set as the bridge itself. function test_finalizeBridgeERC721_selfToken_reverts() external { // Finalize a withdrawal. vm.mockCall( @@ -327,6 +355,8 @@ contract L1ERC721Bridge_Test is Messenger_Initializer { ); } + /// @dev Tests that the ERC721 bridge finalize reverts when the remote token + /// is not escrowed in the L1 bridge. function test_finalizeBridgeERC721_notEscrowed_reverts() external { // Finalize a withdrawal. vm.mockCall( diff --git a/packages/contracts-bedrock/contracts/test/L1StandardBridge.t.sol b/packages/contracts-bedrock/contracts/test/L1StandardBridge.t.sol index 6bb07baf1a92..6c53eaef8962 100644 --- a/packages/contracts-bedrock/contracts/test/L1StandardBridge.t.sol +++ b/packages/contracts-bedrock/contracts/test/L1StandardBridge.t.sol @@ -1,32 +1,39 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Testing utilities +import { stdStorage, StdStorage } from "forge-std/Test.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { Bridge_Initializer } from "./CommonTest.t.sol"; + +// Libraries +import { Predeploys } from "../libraries/Predeploys.sol"; + +// Target contract dependencies import { StandardBridge } from "../universal/StandardBridge.sol"; -import { OptimismPortal } from "../L1/OptimismPortal.sol"; import { L2StandardBridge } from "../L2/L2StandardBridge.sol"; import { CrossDomainMessenger } from "../universal/CrossDomainMessenger.sol"; -import { Predeploys } from "../libraries/Predeploys.sol"; import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol"; -import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import { stdStorage, StdStorage } from "forge-std/Test.sol"; + +// Target contract +import { OptimismPortal } from "../L1/OptimismPortal.sol"; contract L1StandardBridge_Getter_Test is Bridge_Initializer { + /// @dev Test that the accessors return the correct initialized values. function test_getters_succeeds() external { assert(L1Bridge.l2TokenBridge() == address(L2Bridge)); assert(L1Bridge.OTHER_BRIDGE() == L2Bridge); assert(L1Bridge.messenger() == L1Messenger); assert(L1Bridge.MESSENGER() == L1Messenger); - assertEq(L1Bridge.version(), "1.1.0"); + assertEq(L1Bridge.version(), "1.1.1"); } } contract L1StandardBridge_Initialize_Test is Bridge_Initializer { + /// @dev Test that the initialize function sets the correct values. function test_initialize_succeeds() external { assertEq(address(L1Bridge.messenger()), address(L1Messenger)); - assertEq(address(L1Bridge.OTHER_BRIDGE()), Predeploys.L2_STANDARD_BRIDGE); - assertEq(address(L2Bridge), Predeploys.L2_STANDARD_BRIDGE); } } @@ -34,8 +41,7 @@ contract L1StandardBridge_Initialize_Test is Bridge_Initializer { contract L1StandardBridge_Initialize_TestFail is Bridge_Initializer {} contract L1StandardBridge_Receive_Test is Bridge_Initializer { - // receive - // - can accept ETH + /// @dev Tests receive bridges ETH successfully. function test_receive_succeeds() external { assertEq(address(op).balance, 0); @@ -72,6 +78,8 @@ contract L1StandardBridge_Receive_Test is Bridge_Initializer { contract L1StandardBridge_Receive_TestFail {} contract PreBridgeETH is Bridge_Initializer { + /// @dev Asserts the expected calls and events for bridging ETH depending + /// on whether the bridge call is legacy or not. function _preBridgeETH(bool isLegacy) internal { assertEq(address(op).balance, 0); uint256 nonce = L1Messenger.messageNonce(); @@ -165,12 +173,11 @@ contract PreBridgeETH is Bridge_Initializer { } contract L1StandardBridge_DepositETH_Test is PreBridgeETH { - // depositETH - // - emits ETHDepositInitiated - // - emits ETHBridgeInitiated - // - calls optimismPortal.depositTransaction - // - only EOA - // - ETH ends up in the optimismPortal + /// @dev Tests that depositing ETH succeeds. + /// Emits ETHDepositInitiated and ETHBridgeInitiated events. + /// Calls depositTransaction on the OptimismPortal. + /// Only EOA can call depositETH. + /// ETH ends up in the optimismPortal. function test_depositETH_succeeds() external { _preBridgeETH({ isLegacy: true }); L1Bridge.depositETH{ value: 500 }(50000, hex"dead"); @@ -179,12 +186,11 @@ contract L1StandardBridge_DepositETH_Test is PreBridgeETH { } contract L1StandardBridge_BridgeETH_Test is PreBridgeETH { - // BridgeETH - // - emits ETHDepositInitiated - // - emits ETHBridgeInitiated - // - calls optimismPortal.depositTransaction - // - only EOA - // - ETH ends up in the optimismPortal + /// @dev Tests that bridging ETH succeeds. + /// Emits ETHDepositInitiated and ETHBridgeInitiated events. + /// Calls depositTransaction on the OptimismPortal. + /// Only EOA can call bridgeETH. + /// ETH ends up in the optimismPortal. function test_bridgeETH_succeeds() external { _preBridgeETH({ isLegacy: false }); L1Bridge.bridgeETH{ value: 500 }(50000, hex"dead"); @@ -193,10 +199,9 @@ contract L1StandardBridge_BridgeETH_Test is PreBridgeETH { } contract L1StandardBridge_DepositETH_TestFail is Bridge_Initializer { + /// @dev Tests that depositing ETH reverts if the call is not from an EOA. function test_depositETH_notEoa_reverts() external { - // turn alice into a contract vm.etch(alice, address(L1Token).code); - vm.expectRevert("StandardBridge: function can only be called from an EOA"); vm.prank(alice); L1Bridge.depositETH{ value: 1 }(300, hex""); @@ -204,6 +209,8 @@ contract L1StandardBridge_DepositETH_TestFail is Bridge_Initializer { } contract PreBridgeETHTo is Bridge_Initializer { + /// @dev Asserts the expected calls and events for bridging ETH to a different + /// address depending on whether the bridge call is legacy or not. function _preBridgeETHTo(bool isLegacy) internal { assertEq(address(op).balance, 0); uint256 nonce = L1Messenger.messageNonce(); @@ -299,11 +306,11 @@ contract PreBridgeETHTo is Bridge_Initializer { } contract L1StandardBridge_DepositETHTo_Test is PreBridgeETHTo { - // depositETHTo - // - emits ETHDepositInitiated - // - calls optimismPortal.depositTransaction - // - EOA or contract can call - // - ETH ends up in the optimismPortal + /// @dev Tests that depositing ETH to a different address succeeds. + /// Emits ETHDepositInitiated event. + /// Calls depositTransaction on the OptimismPortal. + /// EOA or contract can call depositETHTo. + /// ETH ends up in the optimismPortal. function test_depositETHTo_succeeds() external { _preBridgeETHTo({ isLegacy: true }); L1Bridge.depositETHTo{ value: 600 }(bob, 60000, hex"dead"); @@ -312,12 +319,11 @@ contract L1StandardBridge_DepositETHTo_Test is PreBridgeETHTo { } contract L1StandardBridge_BridgeETHTo_Test is PreBridgeETHTo { - // BridgeETHTo - // - emits ETHDepositInitiated - // - emits ETHBridgeInitiated - // - calls optimismPortal.depositTransaction - // - only EOA - // - ETH ends up in the optimismPortal + /// @dev Tests that bridging ETH to a different address succeeds. + /// Emits ETHDepositInitiated and ETHBridgeInitiated events. + /// Calls depositTransaction on the OptimismPortal. + /// Only EOA can call bridgeETHTo. + /// ETH ends up in the optimismPortal. function test_bridgeETHTo_succeeds() external { _preBridgeETHTo({ isLegacy: false }); L1Bridge.bridgeETHTo{ value: 600 }(bob, 60000, hex"dead"); @@ -335,6 +341,12 @@ contract L1StandardBridge_DepositERC20_Test is Bridge_Initializer { // - emits ERC20DepositInitiated // - calls optimismPortal.depositTransaction // - only callable by EOA + + /// @dev Tests that depositing ERC20 to the bridge succeeds. + /// Bridge deposits are updated. + /// Emits ERC20DepositInitiated event. + /// Calls depositTransaction on the OptimismPortal. + /// Only EOA can call depositERC20. function test_depositERC20_succeeds() external { uint256 nonce = L1Messenger.messageNonce(); uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION @@ -429,6 +441,8 @@ contract L1StandardBridge_DepositERC20_Test is Bridge_Initializer { } contract L1StandardBridge_DepositERC20_TestFail is Bridge_Initializer { + /// @dev Tests that depositing an ERC20 to the bridge reverts + /// if the caller is not an EOA. function test_depositERC20_notEoa_reverts() external { // turn alice into a contract vm.etch(alice, hex"ffff"); @@ -440,11 +454,12 @@ contract L1StandardBridge_DepositERC20_TestFail is Bridge_Initializer { } contract L1StandardBridge_DepositERC20To_Test is Bridge_Initializer { - // depositERC20To - // - updates bridge.deposits - // - emits ERC20DepositInitiated - // - calls optimismPortal.depositTransaction - // - callable by a contract + /// @dev Tests that depositing ERC20 to the bridge succeeds when + /// sent to a different address. + /// Bridge deposits are updated. + /// Emits ERC20DepositInitiated event. + /// Calls depositTransaction on the OptimismPortal. + /// Contracts can call depositERC20. function test_depositERC20To_succeeds() external { uint256 nonce = L1Messenger.messageNonce(); uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION @@ -541,9 +556,9 @@ contract L1StandardBridge_DepositERC20To_Test is Bridge_Initializer { contract L1StandardBridge_FinalizeETHWithdrawal_Test is Bridge_Initializer { using stdStorage for StdStorage; - // finalizeETHWithdrawal - // - emits ETHWithdrawalFinalized - // - only callable by L2 bridge + /// @dev Tests that finalizing an ETH withdrawal succeeds. + /// Emits ETHWithdrawalFinalized event. + /// Only callable by the L2 bridge. function test_finalizeETHWithdrawal_succeeds() external { uint256 aliceBalance = alice.balance; @@ -575,10 +590,10 @@ contract L1StandardBridge_FinalizeETHWithdrawal_TestFail is Bridge_Initializer { contract L1StandardBridge_FinalizeERC20Withdrawal_Test is Bridge_Initializer { using stdStorage for StdStorage; - // finalizeERC20Withdrawal - // - updates bridge.deposits - // - emits ERC20WithdrawalFinalized - // - only callable by L2 bridge + /// @dev Tests that finalizing an ERC20 withdrawal succeeds. + /// Bridge deposits are updated. + /// Emits ERC20WithdrawalFinalized event. + /// Only callable by the L2 bridge. function test_finalizeERC20Withdrawal_succeeds() external { deal(address(L1Token), address(L1Bridge), 100, true); @@ -625,6 +640,7 @@ contract L1StandardBridge_FinalizeERC20Withdrawal_Test is Bridge_Initializer { } contract L1StandardBridge_FinalizeERC20Withdrawal_TestFail is Bridge_Initializer { + /// @dev Tests that finalizing an ERC20 withdrawal reverts if the caller is not the L2 bridge. function test_finalizeERC20Withdrawal_notMessenger_reverts() external { vm.mockCall( address(L1Bridge.messenger()), @@ -643,6 +659,7 @@ contract L1StandardBridge_FinalizeERC20Withdrawal_TestFail is Bridge_Initializer ); } + /// @dev Tests that finalizing an ERC20 withdrawal reverts if the caller is not the L2 bridge. function test_finalizeERC20Withdrawal_notOtherBridge_reverts() external { vm.mockCall( address(L1Bridge.messenger()), @@ -663,6 +680,7 @@ contract L1StandardBridge_FinalizeERC20Withdrawal_TestFail is Bridge_Initializer } contract L1StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer { + /// @dev Tests that finalizing bridged ETH succeeds. function test_finalizeBridgeETH_succeeds() external { address messenger = address(L1Bridge.messenger()); vm.mockCall( @@ -681,6 +699,7 @@ contract L1StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer { } contract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer { + /// @dev Tests that finalizing bridged ETH reverts if the amount is incorrect. function test_finalizeBridgeETH_incorrectValue_reverts() external { address messenger = address(L1Bridge.messenger()); vm.mockCall( @@ -694,6 +713,7 @@ contract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer { L1Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex""); } + /// @dev Tests that finalizing bridged ETH reverts if the destination is the L1 bridge. function test_finalizeBridgeETH_sendToSelf_reverts() external { address messenger = address(L1Bridge.messenger()); vm.mockCall( @@ -707,6 +727,7 @@ contract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer { L1Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L1Bridge), 100, hex""); } + /// @dev Tests that finalizing bridged ETH reverts if the destination is the messenger. function test_finalizeBridgeETH_sendToMessenger_reverts() external { address messenger = address(L1Bridge.messenger()); vm.mockCall( diff --git a/packages/contracts-bedrock/contracts/test/L2OutputOracle.t.sol b/packages/contracts-bedrock/contracts/test/L2OutputOracle.t.sol index 33004078b0dc..c1878f7f7894 100644 --- a/packages/contracts-bedrock/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts-bedrock/contracts/test/L2OutputOracle.t.sol @@ -1,15 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Testing utilities import { stdError } from "forge-std/Test.sol"; import { L2OutputOracle_Initializer, NextImpl } from "./CommonTest.t.sol"; -import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; -import { Proxy } from "../universal/Proxy.sol"; + +// Libraries import { Types } from "../libraries/Types.sol"; -contract L2OutputOracleTest is L2OutputOracle_Initializer { - bytes32 proposedOutput1 = keccak256(abi.encode(1)); +// Target contract dependencies +import { Proxy } from "../universal/Proxy.sol"; + +// Target contract +import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; +contract L2OutputOracle_constructor_Test is L2OutputOracle_Initializer { + /// @dev Tests that constructor sets the initial values correctly. function test_constructor_succeeds() external { assertEq(oracle.PROPOSER(), proposer); assertEq(oracle.CHALLENGER(), owner); @@ -19,6 +25,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { assertEq(oracle.startingTimestamp(), startingTimestamp); } + /// @dev Tests that the constructor reverts if the starting timestamp is invalid. function test_constructor_badTimestamp_reverts() external { vm.expectRevert("L2OutputOracle: starting L2 timestamp must be less than current time"); @@ -34,6 +41,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { }); } + /// @dev Tests that the constructor reverts if the l2BlockTime is invalid. function test_constructor_l2BlockTimeZero_reverts() external { vm.expectRevert("L2OutputOracle: L2 block time must be greater than 0"); new L2OutputOracle({ @@ -47,6 +55,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { }); } + /// @dev Tests that the constructor reverts if the submissionInterval is zero. function test_constructor_submissionInterval_reverts() external { vm.expectRevert("L2OutputOracle: submission interval must be greater than 0"); new L2OutputOracle({ @@ -59,12 +68,12 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { _finalizationPeriodSeconds: 7 days }); } +} - /**************** - * Getter Tests * - ****************/ +contract L2OutputOracle_getter_Test is L2OutputOracle_Initializer { + bytes32 proposedOutput1 = keccak256(abi.encode(1)); - // Test: latestBlockNumber() should return the correct value + /// @dev Tests that `latestBlockNumber` returns the correct value. function test_latestBlockNumber_succeeds() external { uint256 proposedNumber = oracle.nextBlockNumber(); @@ -75,7 +84,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { assertEq(oracle.latestBlockNumber(), proposedNumber); } - // Test: getL2Output() should return the correct value + /// @dev Tests that `getL2Output` returns the correct value. function test_getL2Output_succeeds() external { uint256 nextBlockNumber = oracle.nextBlockNumber(); uint256 nextOutputIndex = oracle.nextOutputIndex(); @@ -92,7 +101,8 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { oracle.getL2Output(nextOutputIndex + 1); } - // Test: getL2OutputIndexAfter() returns correct value when input is exact block + /// @dev Tests that `getL2OutputIndexAfter` returns the correct value + /// when the input is the exact block number of the proposal. function test_getL2OutputIndexAfter_sameBlock_succeeds() external { bytes32 output1 = keccak256(abi.encode(1)); uint256 nextBlockNumber1 = oracle.nextBlockNumber(); @@ -105,7 +115,8 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { assertEq(index1, 0); } - // Test: getL2OutputIndexAfter() returns correct value when input is previous block + /// @dev Tests that `getL2OutputIndexAfter` returns the correct value + /// when the input is the previous block number of the proposal. function test_getL2OutputIndexAfter_previousBlock_succeeds() external { bytes32 output1 = keccak256(abi.encode(1)); uint256 nextBlockNumber1 = oracle.nextBlockNumber(); @@ -118,7 +129,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { assertEq(index1, 0); } - // Test: getL2OutputIndexAfter() returns correct value during binary search + /// @dev Tests that `getL2OutputIndexAfter` returns the correct value. function test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() external { bytes32 output1 = keccak256(abi.encode(1)); uint256 nextBlockNumber1 = oracle.nextBlockNumber(); @@ -157,13 +168,13 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { assertEq(index3, 3); } - // Test: getL2OutputIndexAfter() reverts when no output exists yet + /// @dev Tests that `getL2OutputIndexAfter` reverts when no output exists. function test_getL2OutputIndexAfter_noOutputsExis_reverts() external { vm.expectRevert("L2OutputOracle: cannot get output as no outputs have been proposed yet"); oracle.getL2OutputIndexAfter(0); } - // Test: nextBlockNumber() should return the correct value + /// @dev Tests that `nextBlockNumber` returns the correct value. function test_nextBlockNumber_succeeds() external { assertEq( oracle.nextBlockNumber(), @@ -172,55 +183,38 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { ); } + /// @dev Tests that `computeL2Timestamp` returns the correct value. function test_computeL2Timestamp_succeeds() external { // reverts if timestamp is too low vm.expectRevert(stdError.arithmeticError); oracle.computeL2Timestamp(startingBlockNumber - 1); - // returns the correct value... - // ... for the very first block + // check timestamp for the very first block assertEq(oracle.computeL2Timestamp(startingBlockNumber), startingTimestamp); - // ... for the first block after the starting block + // check timestamp for the first block after the starting block assertEq( oracle.computeL2Timestamp(startingBlockNumber + 1), startingTimestamp + l2BlockTime ); - // ... for some other block number + // check timestamp for some other block number assertEq( oracle.computeL2Timestamp(startingBlockNumber + 96024), startingTimestamp + l2BlockTime * 96024 ); } +} - /***************************** - * Propose Tests - Happy Path * - *****************************/ - - // Test: proposeL2Output succeeds when given valid input, and no block hash and number are - // specified. +contract L2OutputOracle_proposeL2Output_Test is L2OutputOracle_Initializer { + /// @dev Test that `proposeL2Output` succeeds for a valid input + /// and when a block hash and number are not specified. function test_proposeL2Output_proposeAnotherOutput_succeeds() public { - bytes32 proposedOutput2 = keccak256(abi.encode()); - uint256 nextBlockNumber = oracle.nextBlockNumber(); - uint256 nextOutputIndex = oracle.nextOutputIndex(); - warpToProposeTime(nextBlockNumber); - uint256 proposedNumber = oracle.latestBlockNumber(); - - // Ensure the submissionInterval is enforced - assertEq(nextBlockNumber, proposedNumber + submissionInterval); - - vm.roll(nextBlockNumber + 1); - - vm.expectEmit(true, true, true, true); - emit OutputProposed(proposedOutput2, nextOutputIndex, nextBlockNumber, block.timestamp); - - vm.prank(proposer); - oracle.proposeL2Output(proposedOutput2, nextBlockNumber, 0, 0); + proposeAnotherOutput(); } - // Test: proposeL2Output succeeds when given valid input, and when a block hash and number are - // specified for reorg protection. + /// @dev Tests that `proposeL2Output` succeeds when given valid input and + /// when a block hash and number are specified for reorg protection. function test_proposeWithBlockhashAndHeight_succeeds() external { // Get the number and hash of a previous block in the chain uint256 prevL1BlockNumber = block.number - 1; @@ -232,11 +226,8 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { oracle.proposeL2Output(nonZeroHash, nextBlockNumber, prevL1BlockHash, prevL1BlockNumber); } - /*************************** - * Propose Tests - Sad Path * - ***************************/ - - // Test: proposeL2Output fails if called by a party that is not the proposer. + /// @dev Tests that `proposeL2Output` reverts when called by a party + /// that is not the proposer. function test_proposeL2Output_notProposer_reverts() external { uint256 nextBlockNumber = oracle.nextBlockNumber(); warpToProposeTime(nextBlockNumber); @@ -246,7 +237,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0); } - // Test: proposeL2Output fails given a zero blockhash. + /// @dev Tests that `proposeL2Output` reverts when given a zero blockhash. function test_proposeL2Output_emptyOutput_reverts() external { bytes32 outputToPropose = bytes32(0); uint256 nextBlockNumber = oracle.nextBlockNumber(); @@ -256,7 +247,8 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { oracle.proposeL2Output(outputToPropose, nextBlockNumber, 0, 0); } - // Test: proposeL2Output fails if the block number doesn't match the next expected number. + /// @dev Tests that `proposeL2Output` reverts when given a block number + /// that does not match the next expected block number. function test_proposeL2Output_unexpectedBlockNumber_reverts() external { uint256 nextBlockNumber = oracle.nextBlockNumber(); warpToProposeTime(nextBlockNumber); @@ -265,7 +257,8 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { oracle.proposeL2Output(nonZeroHash, nextBlockNumber - 1, 0, 0); } - // Test: proposeL2Output fails if it would have a timestamp in the future. + /// @dev Tests that `proposeL2Output` reverts when given a block number + /// that has a timestamp in the future. function test_proposeL2Output_futureTimetamp_reverts() external { uint256 nextBlockNumber = oracle.nextBlockNumber(); uint256 nextTimestamp = oracle.computeL2Timestamp(nextBlockNumber); @@ -275,8 +268,8 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0); } - // Test: proposeL2Output fails if a non-existent L1 block hash and number are provided for reorg - // protection. + /// @dev Tests that `proposeL2Output` reverts when given a block number + /// whose hash does not match the given block hash. function test_proposeL2Output_wrongFork_reverts() external { uint256 nextBlockNumber = oracle.nextBlockNumber(); warpToProposeTime(nextBlockNumber); @@ -292,8 +285,8 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { ); } - // Test: proposeL2Output fails when given valid input, but the block hash and number do not - // match. + /// @dev Tests that `proposeL2Output` reverts when given a block number + /// whose block hash does not match the given block hash. function test_proposeL2Output_unmatchedBlockhash_reverts() external { // Move ahead to block 100 so that we can reference historical blocks vm.roll(100); @@ -312,14 +305,13 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { ); oracle.proposeL2Output(nonZeroHash, nextBlockNumber, l1BlockHash, l1BlockNumber - 1); } +} - /***************************** - * Delete Tests - Happy Path * - *****************************/ - +contract L2OutputOracle_deleteOutputs_Test is L2OutputOracle_Initializer { + /// @dev Tests that `deleteL2Outputs` succeeds for a single output. function test_deleteOutputs_singleOutput_succeeds() external { - test_proposeL2Output_proposeAnotherOutput_succeeds(); - test_proposeL2Output_proposeAnotherOutput_succeeds(); + proposeAnotherOutput(); + proposeAnotherOutput(); uint256 latestBlockNumber = oracle.latestBlockNumber(); uint256 latestOutputIndex = oracle.latestOutputIndex(); @@ -341,11 +333,12 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { assertEq(newLatestOutput.timestamp, proposal.timestamp); } + /// @dev Tests that `deleteL2Outputs` succeeds for multiple outputs. function test_deleteOutputs_multipleOutputs_succeeds() external { - test_proposeL2Output_proposeAnotherOutput_succeeds(); - test_proposeL2Output_proposeAnotherOutput_succeeds(); - test_proposeL2Output_proposeAnotherOutput_succeeds(); - test_proposeL2Output_proposeAnotherOutput_succeeds(); + proposeAnotherOutput(); + proposeAnotherOutput(); + proposeAnotherOutput(); + proposeAnotherOutput(); uint256 latestBlockNumber = oracle.latestBlockNumber(); uint256 latestOutputIndex = oracle.latestOutputIndex(); @@ -367,10 +360,7 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { assertEq(newLatestOutput.timestamp, proposal.timestamp); } - /*************************** - * Delete Tests - Sad Path * - ***************************/ - + /// @dev Tests that `deleteL2Outputs` reverts when not called by the challenger. function test_deleteL2Outputs_ifNotChallenger_reverts() external { uint256 latestBlockNumber = oracle.latestBlockNumber(); @@ -378,8 +368,9 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { oracle.deleteL2Outputs(latestBlockNumber); } + /// @dev Tests that `deleteL2Outputs` reverts for a non-existant output index. function test_deleteL2Outputs_nonExistent_reverts() external { - test_proposeL2Output_proposeAnotherOutput_succeeds(); + proposeAnotherOutput(); uint256 latestBlockNumber = oracle.latestBlockNumber(); @@ -388,11 +379,12 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { oracle.deleteL2Outputs(latestBlockNumber + 1); } + /// @dev Tests that `deleteL2Outputs` reverts when trying to delete outputs + /// after the latest output index. function test_deleteL2Outputs_afterLatest_reverts() external { - // Start by proposing three outputs - test_proposeL2Output_proposeAnotherOutput_succeeds(); - test_proposeL2Output_proposeAnotherOutput_succeeds(); - test_proposeL2Output_proposeAnotherOutput_succeeds(); + proposeAnotherOutput(); + proposeAnotherOutput(); + proposeAnotherOutput(); // Delete the latest two outputs uint256 latestOutputIndex = oracle.latestOutputIndex(); @@ -405,8 +397,9 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { oracle.deleteL2Outputs(latestOutputIndex - 2); } + /// @dev Tests that `deleteL2Outputs` reverts for finalized outputs. function test_deleteL2Outputs_finalized_reverts() external { - test_proposeL2Output_proposeAnotherOutput_succeeds(); + proposeAnotherOutput(); // Warp past the finalization period + 1 second vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1); @@ -428,6 +421,7 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer { proxy = Proxy(payable(address(oracle))); } + /// @dev Tests that the proxy is initialized with the correct values. function test_initValuesOnProxy_succeeds() external { assertEq(submissionInterval, oracleImpl.SUBMISSION_INTERVAL()); assertEq(l2BlockTime, oracleImpl.L2_BLOCK_TIME()); @@ -438,16 +432,19 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer { assertEq(owner, oracleImpl.CHALLENGER()); } + /// @dev Tests that the proxy cannot be initialized twice. function test_initializeProxy_alreadyInitialized_reverts() external { vm.expectRevert("Initializable: contract is already initialized"); L2OutputOracle(payable(proxy)).initialize(startingBlockNumber, startingTimestamp); } + /// @dev Tests that the implementation contract cannot be initialized twice. function test_initializeImpl_alreadyInitialized_reverts() external { vm.expectRevert("Initializable: contract is already initialized"); L2OutputOracle(oracleImpl).initialize(startingBlockNumber, startingTimestamp); } + /// @dev Tests that the proxy can be successfully upgraded. function test_upgrading_succeeds() external { // Check an unused slot before upgrading. bytes32 slot21Before = vm.load(address(oracle), bytes32(uint256(21))); diff --git a/packages/contracts-bedrock/contracts/test/LibClock.t.sol b/packages/contracts-bedrock/contracts/test/LibClock.t.sol index 6ad1bd51403f..ce6599d95251 100644 --- a/packages/contracts-bedrock/contracts/test/LibClock.t.sol +++ b/packages/contracts-bedrock/contracts/test/LibClock.t.sol @@ -5,21 +5,15 @@ import { Test } from "forge-std/Test.sol"; import { LibClock } from "../dispute/lib/LibClock.sol"; import "../libraries/DisputeTypes.sol"; -/** - * @notice Tests for `LibClock` - */ +/// @notice Tests for `LibClock` contract LibClock_Test is Test { - /** - * @notice Tests that the `duration` function correctly shifts out the `Duration` from a packed `Clock` type. - */ + /// @notice Tests that the `duration` function correctly shifts out the `Duration` from a packed `Clock` type. function testFuzz_duration_succeeds(Duration _duration, Timestamp _timestamp) public { Clock clock = LibClock.wrap(_duration, _timestamp); assertEq(Duration.unwrap(clock.duration()), Duration.unwrap(_duration)); } - /** - * @notice Tests that the `timestamp` function correctly shifts out the `Timestamp` from a packed `Clock` type. - */ + /// @notice Tests that the `timestamp` function correctly shifts out the `Timestamp` from a packed `Clock` type. function testFuzz_timestamp_succeeds(Duration _duration, Timestamp _timestamp) public { Clock clock = LibClock.wrap(_duration, _timestamp); assertEq(Timestamp.unwrap(clock.timestamp()), Timestamp.unwrap(_timestamp)); diff --git a/packages/contracts-bedrock/contracts/test/LibPosition.t.sol b/packages/contracts-bedrock/contracts/test/LibPosition.t.sol index 7e6f8b649018..aaaa3e6cb9db 100644 --- a/packages/contracts-bedrock/contracts/test/LibPosition.t.sol +++ b/packages/contracts-bedrock/contracts/test/LibPosition.t.sol @@ -5,15 +5,11 @@ import { Test } from "forge-std/Test.sol"; import { LibPosition } from "../dispute/lib/LibPosition.sol"; import "../libraries/DisputeTypes.sol"; -/** - * @notice Tests for `LibPosition` - */ +/// @notice Tests for `LibPosition` contract LibPosition_Test is Test { - /** - * @dev Assumes a MAX depth of 63 for the Position type. Any greater depth can cause overflows. - * @dev At the lowest level of the tree, this allows for 2 ** 63 leaves. In reality, the max game depth - * will likely be much lower. - */ + /// @dev Assumes a MAX depth of 63 for the Position type. Any greater depth can cause overflows. + /// @dev At the lowest level of the tree, this allows for 2 ** 63 leaves. In reality, the max game depth + /// will likely be much lower. uint8 internal constant MAX_DEPTH = 63; function boundIndexAtDepth(uint8 _depth, uint64 _indexAtDepth) internal view returns (uint64) { @@ -25,30 +21,24 @@ contract LibPosition_Test is Test { } } - /** - * @notice Tests that the `depth` function correctly shifts out the `depth` from a packed `Position` type. - */ - function testFuzz_depth_correctness(uint8 _depth, uint64 _indexAtDepth) public { + /// @notice Tests that the `depth` function correctly shifts out the `depth` from a packed `Position` type. + function testFuzz_depth_correctness_suceeds(uint8 _depth, uint64 _indexAtDepth) public { _depth = uint8(bound(_depth, 0, MAX_DEPTH)); _indexAtDepth = boundIndexAtDepth(_depth, _indexAtDepth); Position position = LibPosition.wrap(_depth, _indexAtDepth); assertEq(position.depth(), _depth); } - /** - * @notice Tests that the `indexAtDepth` function correctly shifts out the `indexAtDepth` from a packed `Position` type. - */ - function testFuzz_indexAtDepth_correctness(uint8 _depth, uint64 _indexAtDepth) public { + /// @notice Tests that the `indexAtDepth` function correctly shifts out the `indexAtDepth` from a packed `Position` type. + function testFuzz_indexAtDepth_correctness_suceeds(uint8 _depth, uint64 _indexAtDepth) public { _depth = uint8(bound(_depth, 0, MAX_DEPTH)); _indexAtDepth = boundIndexAtDepth(_depth, _indexAtDepth); Position position = LibPosition.wrap(_depth, _indexAtDepth); assertEq(position.indexAtDepth(), _indexAtDepth); } - /** - * @notice Tests that the `left` function correctly computes the position of the left child. - */ - function testFuzz_left_correctness(uint8 _depth, uint64 _indexAtDepth) public { + /// @notice Tests that the `left` function correctly computes the position of the left child. + function testFuzz_left_correctness_suceeds(uint8 _depth, uint64 _indexAtDepth) public { _depth = uint8(bound(_depth, 0, MAX_DEPTH)); _indexAtDepth = boundIndexAtDepth(_depth, _indexAtDepth); @@ -59,10 +49,8 @@ contract LibPosition_Test is Test { assertEq(left.indexAtDepth(), _indexAtDepth * 2); } - /** - * @notice Tests that the `right` function correctly computes the position of the right child. - */ - function testFuzz_right_correctness(uint8 _depth, uint64 _indexAtDepth) public { + /// @notice Tests that the `right` function correctly computes the position of the right child. + function testFuzz_right_correctness_suceeds(uint8 _depth, uint64 _indexAtDepth) public { // Depth bound: [0, 63] _depth = uint8(bound(_depth, 0, MAX_DEPTH)); _indexAtDepth = boundIndexAtDepth(_depth, _indexAtDepth); @@ -74,10 +62,8 @@ contract LibPosition_Test is Test { assertEq(right.indexAtDepth(), _indexAtDepth * 2 + 1); } - /** - * @notice Tests that the `parent` function correctly computes the position of the parent. - */ - function testFuzz_parent_correctness(uint8 _depth, uint64 _indexAtDepth) public { + /// @notice Tests that the `parent` function correctly computes the position of the parent. + function testFuzz_parent_correctness_suceeds(uint8 _depth, uint64 _indexAtDepth) public { _depth = uint8(bound(_depth, 1, MAX_DEPTH)); _indexAtDepth = boundIndexAtDepth(_depth, _indexAtDepth); @@ -88,11 +74,9 @@ contract LibPosition_Test is Test { assertEq(parent.indexAtDepth(), _indexAtDepth / 2); } - /** - * @notice Tests that the `rightIndex` function correctly computes the deepest, right most index relative - * to a given position. - */ - function testFuzz_rightIndex_correctness( + /// @notice Tests that the `rightIndex` function correctly computes the deepest, right most index relative + /// to a given position. + function testFuzz_rightIndex_correctness_suceeds( uint64 _maxDepth, uint8 _depth, uint64 _indexAtDepth @@ -105,49 +89,298 @@ contract LibPosition_Test is Test { _indexAtDepth = boundIndexAtDepth(_depth, _indexAtDepth); Position position = LibPosition.wrap(_depth, _indexAtDepth); - uint64 rightIndex = position.rightIndex(_maxDepth); + Position rightIndex = position.rightIndex(_maxDepth); // Find the deepest, rightmost index in Solidity rather than Yul for (uint256 i = _depth; i < _maxDepth; ++i) { position = position.right(); } - uint64 _rightIndex = position.indexAtDepth(); - assertEq(rightIndex, _rightIndex); + assertEq(Position.unwrap(rightIndex), Position.unwrap(position)); } - /** - * @notice Tests that the `attack` function correctly computes the position of the attack relative to - * a given position. - * @dev `attack` is an alias for `left`, but we test it separately for completeness. - */ - function testFuzz_attack_correctness(uint8 _depth, uint64 _indexAtDepth) public { + /// @notice Tests that the `attack` function correctly computes the position of the attack relative to + /// a given position. + /// @dev `attack` is an alias for `left`, but we test it separately for completeness. + function testFuzz_attack_correctness_suceeds(uint8 _depth, uint64 _indexAtDepth) public { // Depth bound: [0, 63] _depth = uint8(bound(_depth, 0, MAX_DEPTH)); _indexAtDepth = boundIndexAtDepth(_depth, _indexAtDepth); Position position = LibPosition.wrap(_depth, _indexAtDepth); - Position attack = position.attack(); + Position attack = position.move(true); assertEq(attack.depth(), _depth + 1); assertEq(attack.indexAtDepth(), _indexAtDepth * 2); } - /** - * @notice Tests that the `defend` function correctly computes the position of the defense relative to - * a given position. - * @dev A defense can only be given if the position does not belong to the root claim, hence the bound of [1, 127] - * on the depth. - */ - function testFuzz_defend_correctness(uint8 _depth, uint64 _indexAtDepth) public { + /// @notice Tests that the `defend` function correctly computes the position of the defense relative to + /// a given position. + /// @dev A defense can only be given if the position does not belong to the root claim, hence the bound of [1, 127] + /// on the depth. + function testFuzz_defend_correctness_suceeds(uint8 _depth, uint64 _indexAtDepth) public { // Depth bound: [1, 63] _depth = uint8(bound(_depth, 1, MAX_DEPTH)); _indexAtDepth = boundIndexAtDepth(_depth, _indexAtDepth); Position position = LibPosition.wrap(_depth, _indexAtDepth); - Position defend = position.defend(); + Position defend = position.move(false); assertEq(defend.depth(), _depth + 1); assertEq(defend.indexAtDepth(), ((_indexAtDepth / 2) * 2 + 1) * 2); } + + /// @notice A static unit test for the correctness of all gindicies, (depth, index) combos, + /// and the trace index in a tree of max depth = 4. + function test_pos_correctness_succeeds() public { + uint256 maxDepth = 4; + + Position p = LibPosition.wrap(0, 0); + assertEq(Position.unwrap(p), 1); // gindex = 1 + assertEq(p.depth(), 0); // depth = 0 + assertEq(p.indexAtDepth(), 0); // indexAtDepth = 0 + Position r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 31); // right gindex = 31 + assertEq(r.indexAtDepth(), 15); // trace index = 15 + + p = LibPosition.wrap(1, 0); + assertEq(Position.unwrap(p), 2); // gindex = 2 + assertEq(p.depth(), 1); // depth = 1 + assertEq(p.indexAtDepth(), 0); // indexAtDepth = 0 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 23); // right gindex = 23 + assertEq(r.indexAtDepth(), 7); // trace index = 7 + + p = LibPosition.wrap(1, 1); + assertEq(Position.unwrap(p), 3); // gindex = 3 + assertEq(p.depth(), 1); // depth = 1 + assertEq(p.indexAtDepth(), 1); // indexAtDepth = 1 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 31); // right gindex = 31 + assertEq(r.indexAtDepth(), 15); // trace index = 15 + + p = LibPosition.wrap(2, 0); + assertEq(Position.unwrap(p), 4); // gindex = 4 + assertEq(p.depth(), 2); // depth = 2 + assertEq(p.indexAtDepth(), 0); // indexAtDepth = 0 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 19); // right gindex = 19 + assertEq(r.indexAtDepth(), 3); // trace index = 3 + + p = LibPosition.wrap(2, 1); + assertEq(Position.unwrap(p), 5); // gindex = 5 + assertEq(p.depth(), 2); // depth = 2 + assertEq(p.indexAtDepth(), 1); // indexAtDepth = 1 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 23); // right gindex = 23 + assertEq(r.indexAtDepth(), 7); // trace index = 7 + + p = LibPosition.wrap(2, 2); + assertEq(Position.unwrap(p), 6); // gindex = 6 + assertEq(p.depth(), 2); // depth = 2 + assertEq(p.indexAtDepth(), 2); // indexAtDepth = 2 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 27); // right gindex = 27 + assertEq(r.indexAtDepth(), 11); // trace index = 11 + + p = LibPosition.wrap(2, 3); + assertEq(Position.unwrap(p), 7); // gindex = 7 + assertEq(p.depth(), 2); // depth = 2 + assertEq(p.indexAtDepth(), 3); // indexAtDepth = 3 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 31); // right gindex = 31 + assertEq(r.indexAtDepth(), 15); // trace index = 15 + + p = LibPosition.wrap(3, 0); + assertEq(Position.unwrap(p), 8); // gindex = 8 + assertEq(p.depth(), 3); // depth = 3 + assertEq(p.indexAtDepth(), 0); // indexAtDepth = 0 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 17); // right gindex = 17 + assertEq(r.indexAtDepth(), 1); // trace index = 1 + + p = LibPosition.wrap(3, 1); + assertEq(Position.unwrap(p), 9); // gindex = 9 + assertEq(p.depth(), 3); // depth = 3 + assertEq(p.indexAtDepth(), 1); // indexAtDepth = 1 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 19); // right gindex = 19 + assertEq(r.indexAtDepth(), 3); // trace index = 3 + + p = LibPosition.wrap(3, 2); + assertEq(Position.unwrap(p), 10); // gindex = 10 + assertEq(p.depth(), 3); // depth = 3 + assertEq(p.indexAtDepth(), 2); // indexAtDepth = 2 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 21); // right gindex = 21 + assertEq(r.indexAtDepth(), 5); // trace index = 5 + + p = LibPosition.wrap(3, 3); + assertEq(Position.unwrap(p), 11); // gindex = 11 + assertEq(p.depth(), 3); // depth = 3 + assertEq(p.indexAtDepth(), 3); // indexAtDepth = 3 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 23); // right gindex = 23 + assertEq(r.indexAtDepth(), 7); // trace index = 7 + + p = LibPosition.wrap(3, 4); + assertEq(Position.unwrap(p), 12); // gindex = 12 + assertEq(p.depth(), 3); // depth = 3 + assertEq(p.indexAtDepth(), 4); // indexAtDepth = 4 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 25); // right gindex = 25 + assertEq(r.indexAtDepth(), 9); // trace index = 9 + + p = LibPosition.wrap(3, 5); + assertEq(Position.unwrap(p), 13); // gindex = 13 + assertEq(p.depth(), 3); // depth = 3 + assertEq(p.indexAtDepth(), 5); // indexAtDepth = 5 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 27); // right gindex = 27 + assertEq(r.indexAtDepth(), 11); // trace index = 11 + + p = LibPosition.wrap(3, 6); + assertEq(Position.unwrap(p), 14); // gindex = 14 + assertEq(p.depth(), 3); // depth = 3 + assertEq(p.indexAtDepth(), 6); // indexAtDepth = 6 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 29); // right gindex = 29 + assertEq(r.indexAtDepth(), 13); // trace index = 13 + + p = LibPosition.wrap(3, 7); + assertEq(Position.unwrap(p), 15); // gindex = 15 + assertEq(p.depth(), 3); // depth = 3 + assertEq(p.indexAtDepth(), 7); // indexAtDepth = 7 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 31); // right gindex = 31 + assertEq(r.indexAtDepth(), 15); // trace index = 15 + + p = LibPosition.wrap(4, 0); + assertEq(Position.unwrap(p), 16); // gindex = 16 + assertEq(p.depth(), 4); // depth = 4 + assertEq(p.indexAtDepth(), 0); // indexAtDepth = 0 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 16); // right gindex = 16 + assertEq(r.indexAtDepth(), 0); // trace index = 0 + + p = LibPosition.wrap(4, 1); + assertEq(Position.unwrap(p), 17); // gindex = 17 + assertEq(p.depth(), 4); // depth = 4 + assertEq(p.indexAtDepth(), 1); // indexAtDepth = 1 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 17); // right gindex = 17 + assertEq(r.indexAtDepth(), 1); // trace index = 1 + + p = LibPosition.wrap(4, 2); + assertEq(Position.unwrap(p), 18); // gindex = 18 + assertEq(p.depth(), 4); // depth = 4 + assertEq(p.indexAtDepth(), 2); // indexAtDepth = 2 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 18); // right gindex = 18 + assertEq(r.indexAtDepth(), 2); // trace index = 2 + + p = LibPosition.wrap(4, 3); + assertEq(Position.unwrap(p), 19); // gindex = 19 + assertEq(p.depth(), 4); // depth = 4 + assertEq(p.indexAtDepth(), 3); // indexAtDepth = 3 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 19); // right gindex = 19 + assertEq(r.indexAtDepth(), 3); // trace index = 3 + + p = LibPosition.wrap(4, 4); + assertEq(Position.unwrap(p), 20); // gindex = 20 + assertEq(p.depth(), 4); // depth = 4 + assertEq(p.indexAtDepth(), 4); // indexAtDepth = 4 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 20); // right gindex = 20 + assertEq(r.indexAtDepth(), 4); // trace index = 4 + + p = LibPosition.wrap(4, 5); + assertEq(Position.unwrap(p), 21); // gindex = 21 + assertEq(p.depth(), 4); // depth = 4 + assertEq(p.indexAtDepth(), 5); // indexAtDepth = 5 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 21); // right gindex = 21 + assertEq(r.indexAtDepth(), 5); // trace index = 5 + + p = LibPosition.wrap(4, 6); + assertEq(Position.unwrap(p), 22); // gindex = 22 + assertEq(p.depth(), 4); // depth = 4 + assertEq(p.indexAtDepth(), 6); // indexAtDepth = 6 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 22); // right gindex = 22 + assertEq(r.indexAtDepth(), 6); // trace index = 6 + + p = LibPosition.wrap(4, 7); + assertEq(Position.unwrap(p), 23); // gindex = 23 + assertEq(p.depth(), 4); // depth = 4 + assertEq(p.indexAtDepth(), 7); // indexAtDepth = 7 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 23); // right gindex = 23 + assertEq(r.indexAtDepth(), 7); // trace index = 7 + + p = LibPosition.wrap(4, 8); + assertEq(Position.unwrap(p), 24); // gindex = 24 + assertEq(p.depth(), 4); // depth = 4 + assertEq(p.indexAtDepth(), 8); // indexAtDepth = 8 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 24); // right gindex = 24 + assertEq(r.indexAtDepth(), 8); // trace index = 8 + + p = LibPosition.wrap(4, 9); + assertEq(Position.unwrap(p), 25); // gindex = 25 + assertEq(p.depth(), 4); // depth = 4 + assertEq(p.indexAtDepth(), 9); // indexAtDepth = 9 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 25); // right gindex = 25 + assertEq(r.indexAtDepth(), 9); // trace index = 9 + + p = LibPosition.wrap(4, 10); + assertEq(Position.unwrap(p), 26); // gindex = 26 + assertEq(p.depth(), 4); // depth = 4 + assertEq(p.indexAtDepth(), 10); // indexAtDepth = 10 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 26); // right gindex = 26 + assertEq(r.indexAtDepth(), 10); // trace index = 10 + + p = LibPosition.wrap(4, 11); + assertEq(Position.unwrap(p), 27); // gindex = 27 + assertEq(p.depth(), 4); // depth = 4 + assertEq(p.indexAtDepth(), 11); // indexAtDepth = 11 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 27); // right gindex = 27 + assertEq(r.indexAtDepth(), 11); // trace index = 11 + + p = LibPosition.wrap(4, 12); + assertEq(Position.unwrap(p), 28); // gindex = 28 + assertEq(p.depth(), 4); // depth = 4 + assertEq(p.indexAtDepth(), 12); // indexAtDepth = 12 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 28); // right gindex = 28 + assertEq(r.indexAtDepth(), 12); // trace index = 12 + + p = LibPosition.wrap(4, 13); + assertEq(Position.unwrap(p), 29); // gindex = 29 + assertEq(p.depth(), 4); // depth = 4 + assertEq(p.indexAtDepth(), 13); // indexAtDepth = 13 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 29); // right gindex = 29 + assertEq(r.indexAtDepth(), 13); // trace index = 13 + + p = LibPosition.wrap(4, 14); + assertEq(Position.unwrap(p), 30); // gindex = 30 + assertEq(p.depth(), 4); // depth = 4 + assertEq(p.indexAtDepth(), 14); // indexAtDepth = 14 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 30); // right gindex = 30 + assertEq(r.indexAtDepth(), 14); // trace index = 14 + + p = LibPosition.wrap(4, 15); + assertEq(Position.unwrap(p), 31); // gindex = 31 + assertEq(p.depth(), 4); // depth = 4 + assertEq(p.indexAtDepth(), 15); // indexAtDepth = 15 + r = p.rightIndex(maxDepth); + assertEq(Position.unwrap(r), 31); // right gindex = 31 + assertEq(r.indexAtDepth(), 15); // trace index = 15 + } } diff --git a/packages/contracts-bedrock/contracts/test/OptimismPortal.t.sol b/packages/contracts-bedrock/contracts/test/OptimismPortal.t.sol index de9f97736eb9..42661a548c03 100644 --- a/packages/contracts-bedrock/contracts/test/OptimismPortal.t.sol +++ b/packages/contracts-bedrock/contracts/test/OptimismPortal.t.sol @@ -1,29 +1,36 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Testing utilities import { stdError } from "forge-std/Test.sol"; import { Portal_Initializer, CommonTest, NextImpl } from "./CommonTest.t.sol"; -import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol"; -import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; -import { OptimismPortal } from "../L1/OptimismPortal.sol"; + +// Libraries import { Types } from "../libraries/Types.sol"; import { Hashing } from "../libraries/Hashing.sol"; + +// Target contract dependencies import { Proxy } from "../universal/Proxy.sol"; import { ResourceMetering } from "../L1/ResourceMetering.sol"; +import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol"; +import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; + +// Target contract +import { OptimismPortal } from "../L1/OptimismPortal.sol"; contract OptimismPortal_Test is Portal_Initializer { event Paused(address); event Unpaused(address); + /// @dev Tests that the constructor sets the correct values. function test_constructor_succeeds() external { assertEq(address(op.L2_ORACLE()), address(oracle)); assertEq(op.l2Sender(), 0x000000000000000000000000000000000000dEaD); assertEq(op.paused(), false); } - /** - * @notice The OptimismPortal can be paused by the GUARDIAN - */ + /// @dev Tests that `pause` successfully pauses + /// when called by the GUARDIAN. function test_pause_succeeds() external { address guardian = op.GUARDIAN(); @@ -38,10 +45,7 @@ contract OptimismPortal_Test is Portal_Initializer { assertEq(op.paused(), true); } - /** - * @notice The OptimismPortal reverts when an account that is not the - * GUARDIAN calls `pause()` - */ + /// @dev Tests that `pause` reverts when called by a non-GUARDIAN. function test_pause_onlyGuardian_reverts() external { assertEq(op.paused(), false); @@ -53,9 +57,8 @@ contract OptimismPortal_Test is Portal_Initializer { assertEq(op.paused(), false); } - /** - * @notice The OptimismPortal can be unpaused by the GUARDIAN - */ + /// @dev Tests that `unpause` successfully unpauses + /// when called by the GUARDIAN. function test_unpause_succeeds() external { address guardian = op.GUARDIAN(); @@ -71,10 +74,7 @@ contract OptimismPortal_Test is Portal_Initializer { assertEq(op.paused(), false); } - /** - * @notice The OptimismPortal reverts when an account that is not - * the GUARDIAN calls `unpause()` - */ + /// @dev Tests that `unpause` reverts when called by a non-GUARDIAN. function test_unpause_onlyGuardian_reverts() external { address guardian = op.GUARDIAN(); @@ -90,6 +90,7 @@ contract OptimismPortal_Test is Portal_Initializer { assertEq(op.paused(), true); } + /// @dev Tests that `receive` successdully deposits ETH. function test_receive_succeeds() external { vm.expectEmit(true, true, false, true); emitTransactionDeposited(alice, alice, 100, 100, 100_000, false, hex""); @@ -103,17 +104,16 @@ contract OptimismPortal_Test is Portal_Initializer { assertEq(address(op).balance, 100); } - // Test: depositTransaction fails when contract creation has a non-zero destination address + /// @dev Tests that `depositTransaction` reverts when the destination address is non-zero + /// for a contract creation deposit. function test_depositTransaction_contractCreation_reverts() external { // contract creation must have a target of address(0) vm.expectRevert("OptimismPortal: must send to address(0) when creating a contract"); op.depositTransaction(address(1), 1, 0, true, hex""); } - /** - * @notice Prevent deposits from being too large to have a sane upper bound - * on unsafe blocks sent over the p2p network. - */ + /// @dev Tests that `depositTransaction` reverts when the data is too large. + /// This places an upper bound on unsafe blocks sent over p2p. function test_depositTransaction_largeData_reverts() external { uint256 size = 120_001; uint64 gasLimit = op.minimumGasLimit(uint64(size)); @@ -127,10 +127,7 @@ contract OptimismPortal_Test is Portal_Initializer { }); } - /** - * @notice Prevent gasless deposits from being force processed in L2 by - * ensuring that they have a large enough gas limit set. - */ + /// @dev Tests that `depositTransaction` reverts when the gas limit is too small. function test_depositTransaction_smallGasLimit_reverts() external { vm.expectRevert("OptimismPortal: gas limit too small"); op.depositTransaction({ @@ -142,9 +139,8 @@ contract OptimismPortal_Test is Portal_Initializer { }); } - /** - * @notice Fuzz for too small of gas limits - */ + /// @dev Tests that `depositTransaction` succeeds for small, + /// but sufficient, gas limits. function testFuzz_depositTransaction_smallGasLimit_succeeds( bytes memory _data, bool _shouldFail @@ -166,17 +162,16 @@ contract OptimismPortal_Test is Portal_Initializer { }); } - /** - * @notice Ensure that the 0 calldata case is covered and there is a linearly - * increasing gas limit for larger calldata sizes. - */ + /// @dev Tests that `minimumGasLimit` succeeds for small calldata sizes. + /// The gas limit should be 21k for 0 calldata and increase linearly + /// for larger calldata sizes. function test_minimumGasLimit_succeeds() external { assertEq(op.minimumGasLimit(0), 21_000); assertTrue(op.minimumGasLimit(2) > op.minimumGasLimit(1)); assertTrue(op.minimumGasLimit(3) > op.minimumGasLimit(2)); } - // Test: depositTransaction should emit the correct log when an EOA deposits a tx with 0 value + /// @dev Tests that `depositTransaction` succeeds for an EOA depositing a tx with 0 value. function test_depositTransaction_noValueEOA_succeeds() external { // EOA emulation vm.prank(address(this), address(this)); @@ -200,7 +195,7 @@ contract OptimismPortal_Test is Portal_Initializer { ); } - // Test: depositTransaction should emit the correct log when a contract deposits a tx with 0 value + /// @dev Tests that `depositTransaction` succeeds for a contract depositing a tx with 0 value. function test_depositTransaction_noValueContract_succeeds() external { vm.expectEmit(true, true, false, true); emitTransactionDeposited( @@ -222,7 +217,8 @@ contract OptimismPortal_Test is Portal_Initializer { ); } - // Test: depositTransaction should emit the correct log when an EOA deposits a contract creation with 0 value + /// @dev Tests that `depositTransaction` succeeds for an EOA + /// depositing a contract creation with 0 value. function test_depositTransaction_createWithZeroValueForEOA_succeeds() external { // EOA emulation vm.prank(address(this), address(this)); @@ -241,7 +237,8 @@ contract OptimismPortal_Test is Portal_Initializer { op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); } - // Test: depositTransaction should emit the correct log when a contract deposits a contract creation with 0 value + /// @dev Tests that `depositTransaction` succeeds for a contract + /// depositing a contract creation with 0 value. function test_depositTransaction_createWithZeroValueForContract_succeeds() external { vm.expectEmit(true, true, false, true); emitTransactionDeposited( @@ -257,7 +254,7 @@ contract OptimismPortal_Test is Portal_Initializer { op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); } - // Test: depositTransaction should increase its eth balance when an EOA deposits a transaction with ETH + /// @dev Tests that `depositTransaction` succeeds for an EOA depositing a tx with ETH. function test_depositTransaction_withEthValueFromEOA_succeeds() external { // EOA emulation vm.prank(address(this), address(this)); @@ -283,7 +280,7 @@ contract OptimismPortal_Test is Portal_Initializer { assertEq(address(op).balance, NON_ZERO_VALUE); } - // Test: depositTransaction should increase its eth balance when a contract deposits a transaction with ETH + /// @dev Tests that `depositTransaction` succeeds for a contract depositing a tx with ETH. function test_depositTransaction_withEthValueFromContract_succeeds() external { vm.expectEmit(true, true, false, true); emitTransactionDeposited( @@ -305,7 +302,7 @@ contract OptimismPortal_Test is Portal_Initializer { ); } - // Test: depositTransaction should increase its eth balance when an EOA deposits a contract creation with ETH + /// @dev Tests that `depositTransaction` succeeds for an EOA depositing a contract creation with ETH. function test_depositTransaction_withEthValueAndEOAContractCreation_succeeds() external { // EOA emulation vm.prank(address(this), address(this)); @@ -331,7 +328,7 @@ contract OptimismPortal_Test is Portal_Initializer { assertEq(address(op).balance, NON_ZERO_VALUE); } - // Test: depositTransaction should increase its eth balance when a contract deposits a contract creation with ETH + /// @dev Tests that `depositTransaction` succeeds for a contract depositing a contract creation with ETH. function test_depositTransaction_withEthValueAndContractContractCreation_succeeds() external { vm.expectEmit(true, true, false, true); emitTransactionDeposited( @@ -354,6 +351,7 @@ contract OptimismPortal_Test is Portal_Initializer { assertEq(address(op).balance, NON_ZERO_VALUE); } + /// @dev Tests that `isOutputFinalized` succeeds for an EOA depositing a tx with ETH and data. function test_simple_isOutputFinalized_succeeds() external { uint256 ts = block.timestamp; vm.mockCall( @@ -373,6 +371,7 @@ contract OptimismPortal_Test is Portal_Initializer { assertEq(op.isOutputFinalized(0), true); } + /// @dev Tests `isOutputFinalized` for a finalized output. function test_isOutputFinalized_succeeds() external { uint256 checkpoint = oracle.nextBlockNumber(); uint256 nextOutputIndex = oracle.nextOutputIndex(); @@ -439,7 +438,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { _proposedOutputIndex = oracle.nextOutputIndex(); } - // Get the system into a nice ready-to-use state. + /// @dev Setup the system for a ready-to-use state. function setUp() public override { // Configure the oracle to return the output root we've prepared. vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1); @@ -456,8 +455,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { vm.deal(address(op), 0xFFFFFFFF); } - // Utility function used in the subsequent test. This is necessary to assert that the - // reentrant call will revert. + /// @dev Asserts that the reentrant call will revert. function callPortalAndExpectRevert() external payable { vm.expectRevert("OptimismPortal: can only trigger one withdrawal per transaction"); // Arguments here don't matter, as the require check is the first thing that happens. @@ -467,9 +465,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { assertFalse(op.finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx))); } - /** - * @notice Proving withdrawal transactions should revert when paused - */ + /// @dev Tests that `proveWithdrawalTransaction` reverts when paused. function test_proveWithdrawalTransaction_paused_reverts() external { vm.prank(op.GUARDIAN()); op.pause(); @@ -483,7 +479,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { }); } - // Test: proveWithdrawalTransaction cannot prove a withdrawal with itself (the OptimismPortal) as the target. + /// @dev Tests that `proveWithdrawalTransaction` reverts when the target is the portal contract. function test_proveWithdrawalTransaction_onSelfCall_reverts() external { _defaultTx.target = address(op); vm.expectRevert("OptimismPortal: you cannot send messages to the portal contract"); @@ -495,7 +491,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ); } - // Test: proveWithdrawalTransaction reverts if the outputRootProof does not match the output root + /// @dev Tests that `proveWithdrawalTransaction` reverts when + /// the outputRootProof does not match the output root function test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() external { // Modify the version to invalidate the withdrawal proof. _outputRootProof.version = bytes32(uint256(1)); @@ -508,8 +505,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ); } - // Test: proveWithdrawalTransaction reverts if the proof is invalid due to non-existence of - // the withdrawal. + /// @dev Tests that `proveWithdrawalTransaction` reverts when the withdrawal is missing. function test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() external { // modify the default test values to invalidate the proof. _defaultTx.data = hex"abcd"; @@ -522,8 +518,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ); } - // Test: proveWithdrawalTransaction reverts if the passed transaction's withdrawalHash has - // already been proven. + /// @dev Tests that `proveWithdrawalTransaction` reverts when the withdrawal has already + /// been proven. function test_proveWithdrawalTransaction_replayProve_reverts() external { vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); @@ -543,8 +539,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ); } - // Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has - // already been proven AND the output root has changed AND the l2BlockNumber stays the same. + /// @dev Tests that `proveWithdrawalTransaction` succeeds when the withdrawal has already + /// been proven and the output root has changed and the l2BlockNumber stays the same. function test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() external { vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); @@ -587,8 +583,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { assertEq(timestamp, block.timestamp); } - // Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has - // already been proven AND the output root + output index + l2BlockNumber changes. + /// @dev Tests that `proveWithdrawalTransaction` succeeds when the withdrawal has already + /// been proven and the output root, output index, and l2BlockNumber have changed. function test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds() external { @@ -646,7 +642,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { assertEq(timestamp, block.timestamp); } - // Test: proveWithdrawalTransaction succeeds and emits the WithdrawalProven event. + /// @dev Tests that `proveWithdrawalTransaction` succeeds. function test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() external { vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); @@ -658,7 +654,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ); } - // Test: finalizeWithdrawalTransaction succeeds and emits the WithdrawalFinalized event. + /// @dev Tests that `finalizeWithdrawalTransaction` succeeds. function test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() external { uint256 bobBalanceBefore = address(bob).balance; @@ -679,9 +675,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { assert(address(bob).balance == bobBalanceBefore + 100); } - /** - * @notice Finalizing withdrawal transactions should revert when paused - */ + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the contract is paused. function test_finalizeWithdrawalTransaction_paused_reverts() external { vm.prank(op.GUARDIAN()); op.pause(); @@ -690,7 +684,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { op.finalizeWithdrawalTransaction(_defaultTx); } - // Test: finalizeWithdrawalTransaction reverts if the withdrawal has not been proven. + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal has not been function test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() external { uint256 bobBalanceBefore = address(bob).balance; @@ -700,7 +694,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { assert(address(bob).balance == bobBalanceBefore); } - // Test: finalizeWithdrawalTransaction reverts if withdrawal not proven long enough ago. + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal has not been + /// proven long enough ago. function test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() external { uint256 bobBalanceBefore = address(bob).balance; @@ -727,8 +722,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { assert(address(bob).balance == bobBalanceBefore); } - // Test: finalizeWithdrawalTransaction reverts if the provenWithdrawal's timestamp is less - // than the L2 output oracle's starting timestamp + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the provenWithdrawal's timestamp + /// is less than the L2 output oracle's starting timestamp. function test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() external { uint256 bobBalanceBefore = address(bob).balance; @@ -762,8 +757,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { assertEq(bobBalanceBefore, address(bob).balance); } - // Test: finalizeWithdrawalTransaction reverts if the output root proven is not the same as the - // output root at the time of finalization. + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the output root proven is not the + /// same as the output root at the time of finalization. function test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() external { uint256 bobBalanceBefore = address(bob).balance; @@ -804,8 +799,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { assertEq(bobBalanceBefore, address(bob).balance); } - // Test: finalizeWithdrawalTransaction reverts if the output proposal's timestamp has - // not passed the finalization period. + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the output proposal's timestamp + /// has not passed the finalization period. function test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() external { uint256 bobBalanceBefore = address(bob).balance; @@ -844,8 +839,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { assertEq(bobBalanceBefore, address(bob).balance); } - // Test: finalizeWithdrawalTransaction fails because the target reverts, - // and emits the WithdrawalFinalized event with success=false. + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the target reverts. function test_finalizeWithdrawalTransaction_targetFails_fails() external { uint256 bobBalanceBefore = address(bob).balance; vm.etch(bob, hex"fe"); // Contract with just the invalid opcode. @@ -867,7 +861,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { assert(address(bob).balance == bobBalanceBefore); } - // Test: finalizeWithdrawalTransaction reverts if the finalization period has not yet passed. + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the finalization period + /// has not yet passed. function test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() external { // Setup the Oracle to return an output with a recent timestamp uint256 recentTimestamp = block.timestamp - 1000; @@ -894,7 +889,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { op.finalizeWithdrawalTransaction(_defaultTx); } - // Test: finalizeWithdrawalTransaction reverts if the withdrawal has already been finalized. + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal has already been + /// finalized. function test_finalizeWithdrawalTransaction_onReplay_reverts() external { vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); @@ -914,7 +910,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { op.finalizeWithdrawalTransaction(_defaultTx); } - // Test: finalizeWithdrawalTransaction reverts if insufficient gas is supplied. + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal transaction + /// does not have enough gas to execute. function test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() external { // This number was identified through trial and error. uint256 gasLimit = 150_000; @@ -961,8 +958,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { op.finalizeWithdrawalTransaction{ gas: gasLimit }(insufficientGasTx); } - // Test: finalizeWithdrawalTransaction reverts if a sub-call attempts to finalize another - // withdrawal. + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if a sub-call attempts to finalize + /// another withdrawal. function test_finalizeWithdrawalTransaction_onReentrancy_reverts() external { uint256 bobBalanceBefore = address(bob).balance; @@ -1020,6 +1017,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { assert(address(bob).balance == bobBalanceBefore); } + /// @dev Tests that `finalizeWithdrawalTransaction` succeeds. function testDiff_finalizeWithdrawalTransaction_succeeds( address _sender, address _target, @@ -1101,12 +1099,14 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer { Proxy internal proxy; uint64 initialBlockNum; + /// @dev Sets up the test. function setUp() public override { super.setUp(); initialBlockNum = uint64(block.number); proxy = Proxy(payable(address(op))); } + /// @dev Tests that the proxy is initialized correctly. function test_params_initValuesOnProxy_succeeds() external { OptimismPortal p = OptimismPortal(payable(address(proxy))); @@ -1118,16 +1118,19 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer { assertEq(prevBlockNum, initialBlockNum); } + /// @dev Tests that the proxy cannot be initialized twice. function test_initialize_cannotInitProxy_reverts() external { vm.expectRevert("Initializable: contract is already initialized"); OptimismPortal(payable(proxy)).initialize(false); } + /// @dev Tests that the implementation cannot be initialized twice. function test_initialize_cannotInitImpl_reverts() external { vm.expectRevert("Initializable: contract is already initialized"); OptimismPortal(opImpl).initialize(false); } + /// @dev Tests that the proxy can be upgraded. function test_upgradeToAndCall_upgrading_succeeds() external { // Check an unused slot before upgrading. bytes32 slot21Before = vm.load(address(op), bytes32(uint256(21))); @@ -1148,21 +1151,15 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer { } } -/** - * @title OptimismPortalResourceFuzz_Test - * @dev Test various values of the resource metering config to ensure that deposits cannot be - * broken by changing the config. - */ +/// @title OptimismPortalResourceFuzz_Test +/// @dev Test various values of the resource metering config to ensure that deposits cannot be +/// broken by changing the config. contract OptimismPortalResourceFuzz_Test is Portal_Initializer { - /** - * @dev The max gas limit observed throughout this test. Setting this too high can cause - * the test to take too long to run. - */ + /// @dev The max gas limit observed throughout this test. Setting this too high can cause + /// the test to take too long to run. uint256 constant MAX_GAS_LIMIT = 30_000_000; - /** - * @dev Test that various values of the resource metering config will not break deposits. - */ + /// @dev Test that various values of the resource metering config will not break deposits. function testFuzz_systemConfigDeposit_succeeds( uint32 _maxResourceLimit, uint8 _elasticityMultiplier, diff --git a/packages/contracts-bedrock/contracts/test/ResourceMetering.t.sol b/packages/contracts-bedrock/contracts/test/ResourceMetering.t.sol index 47ce545ecad7..7620c8bf0579 100644 --- a/packages/contracts-bedrock/contracts/test/ResourceMetering.t.sol +++ b/packages/contracts-bedrock/contracts/test/ResourceMetering.t.sol @@ -1,11 +1,18 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Testing utilities import { Test } from "forge-std/Test.sol"; -import { ResourceMetering } from "../L1/ResourceMetering.sol"; -import { Proxy } from "../universal/Proxy.sol"; + +// Libraries import { Constants } from "../libraries/Constants.sol"; +// Target contract dependencies +import { Proxy } from "../universal/Proxy.sol"; + +// Target contract +import { ResourceMetering } from "../L1/ResourceMetering.sol"; + contract MeterUser is ResourceMetering { ResourceMetering.ResourceConfig public innerConfig; @@ -50,20 +57,20 @@ contract MeterUser is ResourceMetering { } } -/** - * @title ResourceConfig - * @notice The tests are based on the default config values. It is expected that - * the config values used in these tests are ran in production. - */ +/// @title ResourceMetering_Test +/// @dev Tests are based on the default config values. +/// It is expected that these config values are used in production. contract ResourceMetering_Test is Test { MeterUser internal meter; uint64 initialBlockNum; + /// @dev Sets up the test contract. function setUp() public { meter = new MeterUser(); initialBlockNum = uint64(block.number); } + /// @dev Tests that the initial resource params are set correctly. function test_meter_initialResourceParams_succeeds() external { (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params(); ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig(); @@ -73,6 +80,7 @@ contract ResourceMetering_Test is Test { assertEq(prevBlockNum, initialBlockNum); } + /// @dev Tests that updating the resource params to the same values works correctly. function test_meter_updateParamsNoChange_succeeds() external { meter.use(0); // equivalent to just updating the base fee and block number (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params(); @@ -84,6 +92,7 @@ contract ResourceMetering_Test is Test { assertEq(postBlockNum, prevBlockNum); } + /// @dev Tests that updating the initial block number sets the meter params correctly. function test_meter_updateOneEmptyBlock_succeeds() external { vm.roll(initialBlockNum + 1); meter.use(0); @@ -94,6 +103,7 @@ contract ResourceMetering_Test is Test { assertEq(prevBlockNum, initialBlockNum + 1); } + /// @dev Tests that updating the initial block number sets the meter params correctly. function test_meter_updateTwoEmptyBlocks_succeeds() external { vm.roll(initialBlockNum + 2); meter.use(0); @@ -104,6 +114,7 @@ contract ResourceMetering_Test is Test { assertEq(prevBlockNum, initialBlockNum + 2); } + /// @dev Tests that updating the initial block number sets the meter params correctly. function test_meter_updateTenEmptyBlocks_succeeds() external { vm.roll(initialBlockNum + 10); meter.use(0); @@ -114,6 +125,7 @@ contract ResourceMetering_Test is Test { assertEq(prevBlockNum, initialBlockNum + 10); } + /// @dev Tests that updating the gas delta sets the meter params correctly. function test_meter_updateNoGasDelta_succeeds() external { ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig(); uint256 target = uint256(rcfg.maxResourceLimit) / uint256(rcfg.elasticityMultiplier); @@ -125,6 +137,7 @@ contract ResourceMetering_Test is Test { assertEq(prevBlockNum, initialBlockNum); } + /// @dev Tests that the meter params are set correctly for the maximum gas delta. function test_meter_useMax_succeeds() external { ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig(); uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier); @@ -141,15 +154,9 @@ contract ResourceMetering_Test is Test { assertEq(postBaseFee, 2125000000); } - /** - * @notice This tests that the metered modifier reverts if - * the ResourceConfig baseFeeMaxChangeDenominator - * is set to 1. - * Since the metered modifier internally calls - * solmate's powWad function, it will revert - * with the error string "UNDEFINED" since the - * first parameter will be computed as 0. - */ + /// @dev Tests that the metered modifier reverts if the baseFeeMaxChangeDenominator is set to 1. + /// Since the metered modifier internally calls solmate's powWad function, it will revert + /// with the error string "UNDEFINED" since the first parameter will be computed as 0. function test_meter_denominatorEq1_reverts() external { ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig(); uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier); @@ -167,6 +174,7 @@ contract ResourceMetering_Test is Test { meter.use(0); } + /// @dev Tests that the metered modifier reverts if the value is greater than allowed. function test_meter_useMoreThanMax_reverts() external { ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig(); uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier); @@ -176,8 +184,7 @@ contract ResourceMetering_Test is Test { meter.use(target * elasticityMultiplier + 1); } - // Demonstrates that the resource metering arithmetic can tolerate very large gaps between - // deposits. + /// @dev Tests that resource metering can handle large gaps between deposits. function testFuzz_meter_largeBlockDiff_succeeds(uint64 _amount, uint256 _blockDiff) external { // This test fails if the following line is commented out. // At 12 seconds per block, this number is effectively unreachable. @@ -193,11 +200,9 @@ contract ResourceMetering_Test is Test { } } -/** - * @title CustomMeterUser - * @notice A simple wrapper around `ResourceMetering` that allows the initial - * params to be set in the constructor. - */ +/// @title CustomMeterUser +/// @notice A simple wrapper around `ResourceMetering` that allows the initial +/// params to be set in the constructor. contract CustomMeterUser is ResourceMetering { uint256 public startGas; uint256 public endGas; @@ -230,15 +235,13 @@ contract CustomMeterUser is ResourceMetering { } } -/** - * @title ArtifactResourceMetering_Test - * @notice A table test that sets the state of the ResourceParams and then requests - * various amounts of gas. This test ensures that a wide range of values - * can safely be used with the `ResourceMetering` contract. - * It also writes a CSV file to disk that includes useful information - * about how much gas is used and how expensive it is in USD terms to - * purchase the deposit gas. - */ +/// @title ArtifactResourceMetering_Test +/// @notice A table test that sets the state of the ResourceParams and then requests +/// various amounts of gas. This test ensures that a wide range of values +/// can safely be used with the `ResourceMetering` contract. +/// It also writes a CSV file to disk that includes useful information +/// about how much gas is used and how expensive it is in USD terms to +/// purchase the deposit gas. contract ArtifactResourceMetering_Test is Test { uint128 internal minimumBaseFee; uint128 internal maximumBaseFee; @@ -257,10 +260,7 @@ contract ArtifactResourceMetering_Test is Test { bytes32 internal emptyReturnData = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; - /** - * @notice Sets up the tests by getting constants from the ResourceMetering - * contract. - */ + /// @dev Sets up the tests with constants from the ResourceMetering contract. function setUp() public { vm.roll(1_000_000); @@ -275,11 +275,8 @@ contract ArtifactResourceMetering_Test is Test { try vm.removeFile(outfile) {} catch {} } - /** - * @notice Generate a CSV file. The call to `meter` should be called with at - * most the L1 block gas limit. Without specifying the amount of - * gas, it can take very long to execute. - */ + /// @dev Generates a CSV file. No more than the L1 block gas limit should + /// be supplied to the `meter` function to avoid long execution time. function test_meter_generateArtifact_succeeds() external { vm.writeLine( outfile, diff --git a/packages/contracts-bedrock/contracts/test/SystemConfig.t.sol b/packages/contracts-bedrock/contracts/test/SystemConfig.t.sol index 7af648e9d198..af657e942785 100644 --- a/packages/contracts-bedrock/contracts/test/SystemConfig.t.sol +++ b/packages/contracts-bedrock/contracts/test/SystemConfig.t.sol @@ -1,11 +1,18 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Testing utilities import { CommonTest } from "./CommonTest.t.sol"; -import { SystemConfig } from "../L1/SystemConfig.sol"; -import { ResourceMetering } from "../L1/ResourceMetering.sol"; + +// Libraries import { Constants } from "../libraries/Constants.sol"; +// Target contract dependencies +import { ResourceMetering } from "../L1/ResourceMetering.sol"; + +// Target contract +import { SystemConfig } from "../L1/SystemConfig.sol"; + contract SystemConfig_Init is CommonTest { SystemConfig sysConf; @@ -34,6 +41,7 @@ contract SystemConfig_Init is CommonTest { } contract SystemConfig_Initialize_TestFail is SystemConfig_Init { + /// @dev Tests that initialization reverts if the gas limit is too low. function test_initialize_lowGasLimit_reverts() external { uint64 minimumGasLimit = sysConf.minimumGasLimit(); @@ -60,32 +68,39 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Init { } contract SystemConfig_Setters_TestFail is SystemConfig_Init { + /// @dev Tests that `setBatcherHash` reverts if the caller is not the owner. function test_setBatcherHash_notOwner_reverts() external { vm.expectRevert("Ownable: caller is not the owner"); sysConf.setBatcherHash(bytes32(hex"")); } + /// @dev Tests that `setGasConfig` reverts if the caller is not the owner. function test_setGasConfig_notOwner_reverts() external { vm.expectRevert("Ownable: caller is not the owner"); sysConf.setGasConfig(0, 0); } + /// @dev Tests that `setGasLimit` reverts if the caller is not the owner. function test_setGasLimit_notOwner_reverts() external { vm.expectRevert("Ownable: caller is not the owner"); sysConf.setGasLimit(0); } + /// @dev Tests that `setUnsafeBlockSigner` reverts if the caller is not the owner. function test_setUnsafeBlockSigner_notOwner_reverts() external { vm.expectRevert("Ownable: caller is not the owner"); sysConf.setUnsafeBlockSigner(address(0x20)); } + /// @dev Tests that `setResourceConfig` reverts if the caller is not the owner. function test_setResourceConfig_notOwner_reverts() external { ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG(); vm.expectRevert("Ownable: caller is not the owner"); sysConf.setResourceConfig(config); } + /// @dev Tests that `setResourceConfig` reverts if the min base fee + /// is greater than the maximum allowed base fee. function test_setResourceConfig_badMinMax_reverts() external { ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ maxResourceLimit: 20_000_000, @@ -100,6 +115,8 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init { sysConf.setResourceConfig(config); } + /// @dev Tests that `setResourceConfig` reverts if the baseFeeMaxChangeDenominator + /// is zero. function test_setResourceConfig_zeroDenominator_reverts() external { ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ maxResourceLimit: 20_000_000, @@ -114,6 +131,7 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init { sysConf.setResourceConfig(config); } + /// @dev Tests that `setResourceConfig` reverts if the gas limit is too low. function test_setResourceConfig_lowGasLimit_reverts() external { uint64 gasLimit = sysConf.gasLimit(); @@ -130,6 +148,8 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init { sysConf.setResourceConfig(config); } + /// @dev Tests that `setResourceConfig` reverts if the elasticity multiplier + /// and max resource limit are configured such that there is a loss of precision. function test_setResourceConfig_badPrecision_reverts() external { ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ maxResourceLimit: 20_000_000, @@ -152,6 +172,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { bytes data ); + /// @dev Tests that `setBatcherHash` updates the batcher hash successfully. function testFuzz_setBatcherHash_succeeds(bytes32 newBatcherHash) external { vm.expectEmit(true, true, true, true); emit ConfigUpdate(0, SystemConfig.UpdateType.BATCHER, abi.encode(newBatcherHash)); @@ -161,6 +182,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { assertEq(sysConf.batcherHash(), newBatcherHash); } + /// @dev Tests that `setGasConfig` updates the overhead and scalar successfully. function testFuzz_setGasConfig_succeeds(uint256 newOverhead, uint256 newScalar) external { vm.expectEmit(true, true, true, true); emit ConfigUpdate( @@ -175,6 +197,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { assertEq(sysConf.scalar(), newScalar); } + /// @dev Tests that `setGasLimit` updates the gas limit successfully. function testFuzz_setGasLimit_succeeds(uint64 newGasLimit) external { uint64 minimumGasLimit = sysConf.minimumGasLimit(); newGasLimit = uint64( @@ -189,6 +212,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { assertEq(sysConf.gasLimit(), newGasLimit); } + /// @dev Tests that `setUnsafeBlockSigner` updates the block signer successfully. function testFuzz_setUnsafeBlockSigner_succeeds(address newUnsafeSigner) external { vm.expectEmit(true, true, true, true); emit ConfigUpdate( diff --git a/proxyd/server.go b/proxyd/server.go index 88b031cee902..847ad519fff8 100644 --- a/proxyd/server.go +++ b/proxyd/server.go @@ -16,11 +16,9 @@ import ( "sync" "time" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" "github.com/go-redis/redis/v8" "github.com/gorilla/mux" @@ -580,16 +578,7 @@ func (s *Server) populateContext(w http.ResponseWriter, r *http.Request) context } ctx := context.WithValue(r.Context(), ContextKeyXForwardedFor, xff) // nolint:staticcheck - if len(s.authenticatedPaths) == 0 { - // handle the edge case where auth is disabled - // but someone sends in an auth key anyway - if authorization != "" { - log.Info("blocked authenticated request against unauthenticated proxy") - httpResponseCodesTotal.WithLabelValues("404").Inc() - w.WriteHeader(404) - return nil - } - } else { + if len(s.authenticatedPaths) > 0 { if authorization == "" || s.authenticatedPaths[authorization] == "" { log.Info("blocked unauthorized request", "authorization", authorization) httpResponseCodesTotal.WithLabelValues("401").Inc()