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

Merge branch 'develop' into aj/application-scores

parents 26d5d6b4 a205f8e3
---
'@eth-optimism/core-utils': patch
---
Delete legacy core-utils
---
'@eth-optimism/fault-detector': major
'@eth-optimism/sdk': major
---
Make optimism/sdk default to bedrock mode
---
'@eth-optimism/fault-detector': patch
---
Fix false error to warning
---
'@eth-optimism/chain-mon': minor
'@eth-optimism/core-utils': patch
---
Added a new service wallet-mon to identify unexpected transfers from key accounts
---
'@eth-optimism/fault-detector': patch
---
Add better source maps and developer support
---
'@eth-optimism/chain-mon': patch
---
Fixed an issue with logging the wrong timestamp.
---
'@eth-optimism/contracts-bedrock': minor
---
Fix issue with deposits running out of gas
......@@ -59,6 +59,38 @@ commands:
pip3 install -r requirements.txt
python3 main.py "<<parameters.patterns>>"
jobs:
cannon-go-lint-and-test:
docker:
- image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
resource_class: medium
steps:
- checkout
- check-changed:
patterns: cannon,packages/contracts-bedrock/contracts/cannon
- run:
name: prep Cannon results dir
command: mkdir -p /tmp/test-results
- run:
name: build Cannon example binaries
command: make elf # only compile ELF binaries with Go, we do not have MIPS GCC for creating the debug-dumps.
working_directory: cannon/example
- run:
name: Cannon Go lint
command: |
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" ./...
working_directory: cannon
- run:
name: Cannon Go tests
command: |
gotestsum --format=standard-verbose --junitfile=/tmp/test-results/cannon.xml \
-- -parallel=2 -coverpkg=github.com/ethereum-optimism/optimism/cannon/... -coverprofile=coverage.out ./...
working_directory: cannon
- run:
name: upload Cannon coverage
command: codecov --verbose --clean --flags cannon-go-tests
- store_test_results:
path: /tmp/test-results
yarn-monorepo:
docker:
- image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
......@@ -1387,6 +1419,7 @@ workflows:
- op-challenger-docker-build
- check-generated-mocks-op-node
- check-generated-mocks-op-service
- cannon-go-lint-and-test
release:
jobs:
- hold:
......
node_modules
artifacts
cache
.*.swp
venv
.idea
*.log
example/bin
contracts/out
state.json
*.json
*.pprof
*.out
MIT License
Copyright (c) 2021 Optimism
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
<!--![cannon](https://upload.wikimedia.org/wikipedia/commons/8/80/Cannon%2C_Château_du_Haut-Koenigsbourg%2C_France.jpg)-->
<!--![cannon](https://cdn1.epicgames.com/ue/product/Featured/SCIFIWEAPONBUNDLE_featured-894x488-83fbc936b6d86edcbbe892b1a6780224.png)-->
<!--![cannon](https://static.wikia.nocookie.net/ageofempires/images/8/80/Bombard_cannon_aoe2DE.png/revision/latest/top-crop/width/360/height/360?cb=20200331021834)-->
<!--![cannon](https://paradacreativa.es/wp-content/uploads/2021/05/Canon-orbital-GTA-01.jpg)-->
---
Cannon *(cannon cannon cannon)* is an onchain MIPS instruction emulator.
Cannon supports EVM-equivalent fault proofs by enabling Geth to run onchain,
one instruction at a time, as part of an interactive dispute game.
* It's Go code
* ...that runs an EVM
* ...emulating a MIPS machine
* ...running compiled Go code
* ...that runs an EVM
For more information, see [Docs](./docs/README.md).
## Usage
```shell
# Build op-program server-mode and MIPS-client binaries.
cd ../op-program
make op-program # build
# Switch back to cannon, and build the CLI
cd ../cannon
go build -o cannon .
# Transform MIPS op-program client binary into first VM state.
# This outputs state.json (VM state) and meta.json (for debug symbols).
./cannon load-elf --path=../op-program/bin/op-program-client.elf
# Run cannon emulator (with example inputs)
# Note that the server-mode op-program command is passed into cannon (after the --),
# it runs as sub-process to provide the pre-image data.
#
# Note:
# - The L2 RPC is an archive L2 node on OP goerli.
# - The L1 RPC is a non-archive RPC, also change `--l1.rpckind` to reflect the correct L1 RPC type.
./cannon run
--pprof.cpu
--info-at '%10000000'
--proof-at never
--input ./state.json
--
../op-program/bin/op-program
--l2 http://127.0.0.1:8745
--l1 http://127.0.0.1:8645
--l1.trustrpc
--l1.rpckind debug_geth
--log.format terminal
--l2.head 0xedc79de4d616a9100fdd42192224580daee81ea3d6303de8089d48a6c1bf4816
--network goerli
--l1.head 0x204f815790ca3bb43526ad60ebcc64784ec809bdc3550e82b54a0172f981efab
--l2.claim 0x530658ab1b1b3ff4829731fc8d5955f0e6b8410db2cd65b572067ba58df1f2b9
--l2.blocknumber 8813570
--datadir /tmp/fpp-database
--server
# Add --proof-at '=12345' (or pick other pattern, see --help)
# to pick a step to build a proof for (e.g. exact step, every N steps, etc.)
# Also see `./cannon run --help` for more options
```
## Contracts
The Cannon contracts:
- `MIPS.sol`: A MIPS emulator implementation, to run a single instruction onchain, with merkleized VM memory.
- `PreimageOracle.sol`: implements the pre-image oracle ABI, to support the instruction execution pre-image requests.
The smart-contracts are integrated into the Optimism monorepo contracts:
[`../packages/contracts-bedrock/contracts/cannon`](../packages/contracts-bedrock/contracts/cannon)
## `mipsevm`
`mipsevm` is Go tooling to test the onchain MIPS implementation, and generate proof data.
## `example`
Example programs that can be run and proven with Cannon.
Optional dependency, but required for `mipsevm` Go tests.
See [`example/Makefile`](./example/Makefile) for building the example MIPS binaries.
## License
MIT, see [`LICENSE`](./LICENSE) file.
**Note: This code is unaudited.**
In NO WAY should it be used to secure any monetary value before testing and auditing.
This is experimental software, and should be treated as such.
The authors of this project make no guarantees of security of ANY KIND.
package cmd
import (
"encoding/json"
"errors"
"fmt"
"io"
"os"
)
func loadJSON[X any](inputPath string) (*X, error) {
if inputPath == "" {
return nil, errors.New("no path specified")
}
f, err := os.OpenFile(inputPath, os.O_RDONLY, 0)
if err != nil {
return nil, fmt.Errorf("failed to open file %q: %w", inputPath, err)
}
defer f.Close()
var state X
if err := json.NewDecoder(f).Decode(&state); err != nil {
return nil, fmt.Errorf("failed to decode file %q: %w", inputPath, err)
}
return &state, nil
}
func writeJSON[X any](outputPath string, value X, outIfEmpty bool) error {
var out io.Writer
if outputPath != "" {
f, err := os.OpenFile(outputPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil {
return fmt.Errorf("failed to open output file: %w", err)
}
defer f.Close()
out = f
} else if outIfEmpty {
out = os.Stdout
} else {
return nil
}
enc := json.NewEncoder(out)
if err := enc.Encode(value); err != nil {
return fmt.Errorf("failed to encode to JSON: %w", err)
}
_, err := out.Write([]byte{'\n'})
if err != nil {
return fmt.Errorf("failed to append new-line: %w", err)
}
return nil
}
package cmd
import (
"debug/elf"
"fmt"
"github.com/urfave/cli/v2"
"github.com/ethereum-optimism/optimism/cannon/mipsevm"
)
var (
LoadELFPathFlag = &cli.PathFlag{
Name: "path",
Usage: "Path to 32-bit big-endian MIPS ELF file",
TakesFile: true,
Required: true,
}
LoadELFPatchFlag = &cli.StringSliceFlag{
Name: "patch",
Usage: "Type of patching to do",
Value: cli.NewStringSlice("go", "stack"),
Required: false,
}
LoadELFOutFlag = &cli.PathFlag{
Name: "out",
Usage: "Output path to write JSON state to. State is dumped to stdout if set to empty string.",
Value: "state.json",
Required: false,
}
LoadELFMetaFlag = &cli.PathFlag{
Name: "meta",
Usage: "Write metadata file, for symbol lookup during program execution. None if empty.",
Value: "meta.json",
Required: false,
}
)
func LoadELF(ctx *cli.Context) error {
elfPath := ctx.Path(LoadELFPathFlag.Name)
elfProgram, err := elf.Open(elfPath)
if err != nil {
return fmt.Errorf("failed to open ELF file %q: %w", elfPath, err)
}
if elfProgram.Machine != elf.EM_MIPS {
return fmt.Errorf("ELF is not big-endian MIPS R3000, but got %q", elfProgram.Machine.String())
}
state, err := mipsevm.LoadELF(elfProgram)
if err != nil {
return fmt.Errorf("failed to load ELF data into VM state: %w", err)
}
for _, typ := range ctx.StringSlice(LoadELFPatchFlag.Name) {
switch typ {
case "stack":
err = mipsevm.PatchStack(state)
case "go":
err = mipsevm.PatchGo(elfProgram, state)
default:
return fmt.Errorf("unrecognized form of patching: %q", typ)
}
if err != nil {
return fmt.Errorf("failed to apply patch %s: %w", typ, err)
}
}
meta, err := mipsevm.MakeMetadata(elfProgram)
if err != nil {
return fmt.Errorf("failed to compute program metadata: %w", err)
}
if err := writeJSON[*mipsevm.Metadata](ctx.Path(LoadELFMetaFlag.Name), meta, false); err != nil {
return fmt.Errorf("failed to output metadata: %w", err)
}
return writeJSON[*mipsevm.State](ctx.Path(LoadELFOutFlag.Name), state, true)
}
var LoadELFCommand = &cli.Command{
Name: "load-elf",
Usage: "Load ELF file into Cannon JSON state",
Description: "Load ELF file into Cannon JSON state, optionally patch out functions",
Action: LoadELF,
Flags: []cli.Flag{
LoadELFPathFlag,
LoadELFPatchFlag,
LoadELFOutFlag,
LoadELFMetaFlag,
},
}
package cmd
import (
"io"
"github.com/ethereum/go-ethereum/log"
)
func Logger(w io.Writer, lvl log.Lvl) log.Logger {
h := log.StreamHandler(w, log.LogfmtFormat())
h = log.SyncHandler(h)
h = log.LvlFilterHandler(lvl, h)
l := log.New()
l.SetHandler(h)
return l
}
package cmd
import (
"fmt"
"strconv"
"strings"
"github.com/ethereum-optimism/optimism/cannon/mipsevm"
)
type StepMatcher func(st *mipsevm.State) bool
type StepMatcherFlag struct {
repr string
matcher StepMatcher
}
func MustStepMatcherFlag(pattern string) *StepMatcherFlag {
out := new(StepMatcherFlag)
if err := out.Set(pattern); err != nil {
panic(err)
}
return out
}
func (m *StepMatcherFlag) Set(value string) error {
m.repr = value
if value == "" || value == "never" {
m.matcher = func(st *mipsevm.State) bool {
return false
}
} else if value == "always" {
m.matcher = func(st *mipsevm.State) bool {
return true
}
} else if strings.HasPrefix(value, "=") {
when, err := strconv.ParseUint(value[1:], 0, 64)
if err != nil {
return fmt.Errorf("failed to parse step number: %w", err)
}
m.matcher = func(st *mipsevm.State) bool {
return st.Step == when
}
} else if strings.HasPrefix(value, "%") {
when, err := strconv.ParseUint(value[1:], 0, 64)
if err != nil {
return fmt.Errorf("failed to parse step interval number: %w", err)
}
m.matcher = func(st *mipsevm.State) bool {
return st.Step%when == 0
}
} else {
return fmt.Errorf("unrecognized step matcher: %q", value)
}
return nil
}
func (m *StepMatcherFlag) String() string {
return m.repr
}
func (m *StepMatcherFlag) Matcher() StepMatcher {
if m.matcher == nil { // Set(value) is not called for omitted inputs, default to never matching.
return func(st *mipsevm.State) bool {
return false
}
}
return m.matcher
}
package cmd
import (
"fmt"
"os"
"os/exec"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/urfave/cli/v2"
"github.com/pkg/profile"
"github.com/ethereum-optimism/optimism/cannon/mipsevm"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
)
var (
RunInputFlag = &cli.PathFlag{
Name: "input",
Usage: "path of input JSON state. Stdin if left empty.",
TakesFile: true,
Value: "state.json",
Required: true,
}
RunOutputFlag = &cli.PathFlag{
Name: "output",
Usage: "path of output JSON state. Stdout if left empty.",
TakesFile: true,
Value: "out.json",
Required: false,
}
patternHelp = "'never' (default), 'always', '=123' at exactly step 123, '%123' for every 123 steps"
RunProofAtFlag = &cli.GenericFlag{
Name: "proof-at",
Usage: "step pattern to output proof at: " + patternHelp,
Value: new(StepMatcherFlag),
Required: false,
}
RunProofFmtFlag = &cli.StringFlag{
Name: "proof-fmt",
Usage: "format for proof data output file names. Proof data is written to stdout if empty.",
Value: "proof-%d.json",
Required: false,
}
RunSnapshotAtFlag = &cli.GenericFlag{
Name: "snapshot-at",
Usage: "step pattern to output snapshots at: " + patternHelp,
Value: new(StepMatcherFlag),
Required: false,
}
RunSnapshotFmtFlag = &cli.StringFlag{
Name: "snapshot-fmt",
Usage: "format for snapshot output file names.",
Value: "state-%d.json",
Required: false,
}
RunStopAtFlag = &cli.GenericFlag{
Name: "stop-at",
Usage: "step pattern to stop at: " + patternHelp,
Value: new(StepMatcherFlag),
Required: false,
}
RunMetaFlag = &cli.PathFlag{
Name: "meta",
Usage: "path to metadata file for symbol lookup for enhanced debugging info durign execution.",
Value: "meta.json",
Required: false,
}
RunInfoAtFlag = &cli.GenericFlag{
Name: "info-at",
Usage: "step pattern to print info at: " + patternHelp,
Value: MustStepMatcherFlag("%100000"),
Required: false,
}
RunPProfCPU = &cli.BoolFlag{
Name: "pprof.cpu",
Usage: "enable pprof cpu profiling",
}
)
type Proof struct {
Step uint64 `json:"step"`
Pre common.Hash `json:"pre"`
Post common.Hash `json:"post"`
StepInput hexutil.Bytes `json:"step-input"`
OracleInput hexutil.Bytes `json:"oracle-input"`
}
type rawHint string
func (rh rawHint) Hint() string {
return string(rh)
}
type rawKey [32]byte
func (rk rawKey) PreimageKey() [32]byte {
return rk
}
type ProcessPreimageOracle struct {
pCl *preimage.OracleClient
hCl *preimage.HintWriter
cmd *exec.Cmd
}
func NewProcessPreimageOracle(name string, args []string) (*ProcessPreimageOracle, error) {
if name == "" {
return &ProcessPreimageOracle{}, nil
}
pClientRW, pOracleRW, err := preimage.CreateBidirectionalChannel()
if err != nil {
return nil, err
}
hClientRW, hOracleRW, err := preimage.CreateBidirectionalChannel()
if err != nil {
return nil, err
}
cmd := exec.Command(name, args...) // nosemgrep
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.ExtraFiles = []*os.File{
hOracleRW.Reader(),
hOracleRW.Writer(),
pOracleRW.Reader(),
pOracleRW.Writer(),
}
out := &ProcessPreimageOracle{
pCl: preimage.NewOracleClient(pClientRW),
hCl: preimage.NewHintWriter(hClientRW),
cmd: cmd,
}
return out, nil
}
func (p *ProcessPreimageOracle) Hint(v []byte) {
if p.hCl == nil { // no hint processor
return
}
p.hCl.Hint(rawHint(v))
}
func (p *ProcessPreimageOracle) GetPreimage(k [32]byte) []byte {
if p.pCl == nil {
panic("no pre-image retriever available")
}
return p.pCl.Get(rawKey(k))
}
func (p *ProcessPreimageOracle) Start() error {
if p.cmd == nil {
return nil
}
return p.cmd.Start()
}
func (p *ProcessPreimageOracle) Close() error {
if p.cmd == nil {
return nil
}
_ = p.cmd.Process.Signal(os.Interrupt)
// Go 1.20 feature, to introduce later
//p.cmd.WaitDelay = time.Second * 10
err := p.cmd.Wait()
if err, ok := err.(*exec.ExitError); ok {
if err.Success() {
return nil
}
}
return err
}
type StepFn func(proof bool) (*mipsevm.StepWitness, error)
func Guard(proc *os.ProcessState, fn StepFn) StepFn {
return func(proof bool) (*mipsevm.StepWitness, error) {
wit, err := fn(proof)
if err != nil {
if proc.Exited() {
return nil, fmt.Errorf("pre-image server exited with code %d, resulting in err %w", proc.ExitCode(), err)
} else {
return nil, err
}
}
return wit, nil
}
}
var _ mipsevm.PreimageOracle = (*ProcessPreimageOracle)(nil)
func Run(ctx *cli.Context) error {
if ctx.Bool(RunPProfCPU.Name) {
defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.CPUProfile).Stop()
}
state, err := loadJSON[mipsevm.State](ctx.Path(RunInputFlag.Name))
if err != nil {
return err
}
l := Logger(os.Stderr, log.LvlInfo)
outLog := &mipsevm.LoggingWriter{Name: "program std-out", Log: l}
errLog := &mipsevm.LoggingWriter{Name: "program std-err", Log: l}
// split CLI args after first '--'
args := ctx.Args().Slice()
for i, arg := range args {
if arg == "--" {
args = args[i+1:]
break
}
}
if len(args) == 0 {
args = []string{""}
}
po, err := NewProcessPreimageOracle(args[0], args[1:])
if err != nil {
return fmt.Errorf("failed to create pre-image oracle process: %w", err)
}
if err := po.Start(); err != nil {
return fmt.Errorf("failed to start pre-image oracle server: %w", err)
}
defer func() {
if err := po.Close(); err != nil {
l.Error("failed to close pre-image server", "err", err)
}
}()
stopAt := ctx.Generic(RunStopAtFlag.Name).(*StepMatcherFlag).Matcher()
proofAt := ctx.Generic(RunProofAtFlag.Name).(*StepMatcherFlag).Matcher()
snapshotAt := ctx.Generic(RunSnapshotAtFlag.Name).(*StepMatcherFlag).Matcher()
infoAt := ctx.Generic(RunInfoAtFlag.Name).(*StepMatcherFlag).Matcher()
var meta *mipsevm.Metadata
if metaPath := ctx.Path(RunMetaFlag.Name); metaPath == "" {
l.Info("no metadata file specified, defaulting to empty metadata")
meta = &mipsevm.Metadata{Symbols: nil} // provide empty metadata by default
} else {
if m, err := loadJSON[mipsevm.Metadata](metaPath); err != nil {
return fmt.Errorf("failed to load metadata: %w", err)
} else {
meta = m
}
}
us := mipsevm.NewInstrumentedState(state, po, outLog, errLog)
proofFmt := ctx.String(RunProofFmtFlag.Name)
snapshotFmt := ctx.String(RunSnapshotFmtFlag.Name)
stepFn := us.Step
if po.cmd != nil {
stepFn = Guard(po.cmd.ProcessState, stepFn)
}
start := time.Now()
startStep := state.Step
// avoid symbol lookups every instruction by preparing a matcher func
sleepCheck := meta.SymbolMatcher("runtime.notesleep")
for !state.Exited {
if state.Step%100 == 0 { // don't do the ctx err check (includes lock) too often
if err := ctx.Context.Err(); err != nil {
return err
}
}
step := state.Step
if infoAt(state) {
delta := time.Since(start)
l.Info("processing",
"step", step,
"pc", mipsevm.HexU32(state.PC),
"insn", mipsevm.HexU32(state.Memory.GetMemory(state.PC)),
"ips", float64(step-startStep)/(float64(delta)/float64(time.Second)),
"pages", state.Memory.PageCount(),
"mem", state.Memory.Usage(),
"name", meta.LookupSymbol(state.PC),
)
}
if sleepCheck(state.PC) { // don't loop forever when we get stuck because of an unexpected bad program
return fmt.Errorf("got stuck in Go sleep at step %d", step)
}
if stopAt(state) {
break
}
if snapshotAt(state) {
if err := writeJSON[*mipsevm.State](fmt.Sprintf(snapshotFmt, step), state, false); err != nil {
return fmt.Errorf("failed to write state snapshot: %w", err)
}
}
if proofAt(state) {
preStateHash := crypto.Keccak256Hash(state.EncodeWitness())
witness, err := stepFn(true)
if err != nil {
return fmt.Errorf("failed at proof-gen step %d (PC: %08x): %w", step, state.PC, err)
}
postStateHash := crypto.Keccak256Hash(state.EncodeWitness())
proof := &Proof{
Step: step,
Pre: preStateHash,
Post: postStateHash,
StepInput: witness.EncodeStepInput(),
}
if witness.HasPreimage() {
inp, err := witness.EncodePreimageOracleInput()
if err != nil {
return fmt.Errorf("failed to encode pre-image oracle input: %w", err)
}
proof.OracleInput = inp
}
if err := writeJSON[*Proof](fmt.Sprintf(proofFmt, step), proof, true); err != nil {
return fmt.Errorf("failed to write proof data: %w", err)
}
} else {
_, err = stepFn(false)
if err != nil {
return fmt.Errorf("failed at step %d (PC: %08x): %w", step, state.PC, err)
}
}
}
if err := writeJSON[*mipsevm.State](ctx.Path(RunOutputFlag.Name), state, true); err != nil {
return fmt.Errorf("failed to write state output: %w", err)
}
return nil
}
var RunCommand = &cli.Command{
Name: "run",
Usage: "Run VM step(s) and generate proof data to replicate onchain.",
Description: "Run VM step(s) and generate proof data to replicate onchain. See flags to match when to output a proof, a snapshot, or to stop early.",
Action: Run,
Flags: []cli.Flag{
RunInputFlag,
RunOutputFlag,
RunProofAtFlag,
RunProofFmtFlag,
RunSnapshotAtFlag,
RunSnapshotFmtFlag,
RunStopAtFlag,
RunMetaFlag,
RunInfoAtFlag,
RunPProfCPU,
},
}
# Cannon Overview
Cannon has two main components:
- Onchain `MIPS.sol`: EVM implementation to verify execution of a single MIPS instruction.
- Offchain `mipsevm`: Go implementation to produce a proof for any MIPS instruction to verify onchain.
Between these two modes of operation, the [witness data](#witness-data) is essential,
to reproduce the same instruction onchain as offchain.
## Onchain `MIPS.sol`
This is an onchain implementation of big-endian 32-bit MIPS instruction execution.
This covers MIPS III, R3000, as required by the `mips` Go compiler/runtime target.
The systemcall instruction is implemented to simulate a minimal subset of the Linux kernel,
just enough to serve the needs of a basic Go program:
allocate memory, read/write to certain file-descriptors, and exit.
Note that this does not include concurrency related system calls: when running Go programs,
the GC has to be disabled, since it runs concurrently.
This is done by patching out specific runtime functions that start the GC,
by simply inserting jumps to the return-address, before the functions spin up any additional threads.
## Offchain `mipsevm`
This is an instrumented emulator, also running big-endian 32-bit MIPS, that executes one step at a time,
and maintains the same state as used for onchain execution.
The difference is that it has access to the full memory, and pre-image oracle.
And as it executes each step, it can optionally produce the witness data for the step, to repeat it onchain.
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.
## Witness Data
There are 3 types of witness data involved in onchain execution:
- [Packed State](#packed-state)
- [Memory proofs](#memory-proofs)
- [Pre-image data](#pre-image-data)
### Packed State
The following state is packed together, and provided in every executed onchain instruction:
```solidity
struct State {
bytes32 memRoot;
bytes32 preimageKey;
uint32 preimageOffset;
uint32 pc;
uint32 nextPC;
uint32 lo;
uint32 hi;
uint32 heap;
uint8 exitCode;
bool exited;
uint64 step;
uint32[32] registers;
}
```
The packed state is small! The `State` data can be packed in such a small amount of EVM words,
that it is more efficient to fully provide it, than to create a proof for each individual part involved in execution.
The memory is represented as a merkle-tree root, committing to a binary merkle tree of all memory data,
see [memory proofs](#memory-proofs).
The `State` covers all general purpose registers, as well as the `lo`, `hi` and `pc` values.
`nextPC` helps pre-schedule the program counter change, to emulate delay-slot behavior of MIPS
after branch and jump instructions.
The program stops changing the state when `exited` is set to true. The exit-code is remembered,
to determine if the program is successful, or panicked/exited in some unexpected way.
This outcome can be used to determine truthiness of claims that are verified as part of the program execution.
The `heap` value is a special value, used to emulate a growing heap, to map new memory upon `mmap` calls by the program.
No memory reads/writes are actually illegal however, mmap-ing is purely to satisfy program runtimes that
need the memory-pointer result of the syscall to locate free memory.
The `preimageKey` and `preimageOffset` are backing the in-flight communication of [pre-image data](#pre-image-data).
The VM `stateHash` is computed as `keccak256(encoded_packed_state)`,
where `encoded_packed_state` is the concatenation of all state-values (all `uint` values are big-endian).
### Memory proofs
Simplicity is key here. Previous versions of Cannon used to overlap memory and register state,
and represent it with a Merkle Patricia Trie.
This added a lot of complexity, as there would be multiple dynamically-sized MPT proofs,
with read and write operations, during a single instruction.
Instead, memory in Cannon is now represented as a binary merkle tree:
The tree has a fixed-depth of 27 levels, with leaf values of 32 bytes each.
This spans the full 32-bit address space: `2**27 * 32 = 2**32`.
Each leaf contains the memory at that part of the tree.
The tree is efficiently allocated, since the root of fully zeroed sub-trees
can be computed without actually creating the full-subtree: `zero_hash[d] = hash(zero_hash[d-1], zero_hash[d-1])`,
until the base-case of `zero_hash[0] == bytes32(0)`.
Nodes in this memory tree are combined as: `out = keccak256(left ++ right)`, where `++` is concatenation,
and `left` and `right` are the 32-byte outputs of the respective sub-trees or the leaf values themselves.
Individual leaf nodes are not hashed.
The proof format is a concatenated byte array of 28 `bytes32`. The first `bytes32` is the leaf value,
and the remaining 27 `bytes32` are the sibling nodes up till the root of the tree,
along the branch of the leaf value, starting from the bottom.
To verify the proof, start with the leaf value as `node`, and combine it with respective sibling values:
`node = keccak256(node ++ sibling)` or `node = keccak256(sibling ++ node)`,
depending the position of `node` at that level of the tree.
During the onchain execution, each instruction only executes 1 or 2 memory reads, followed by 0 or 1 writes,
where the write is over the same memory as was last read.
The memory access is specifically:
- instruction (4 byte) read at `PC`
- load or syscall mem read, always aligned 4 bytes, read at any `addr`
- store or syscall mem write, always aligned 4 bytes, at ths same `addr`
Writing only once, at the last read leaf, also means that the leaf can be safely updated and the same proof-data
that was used to verify the read, can be used to reconstruct the new `memRoot` of the memory tree,
since all sibling data that is combined with the new leaf value was already authenticated during the read part.
### Pre-image data
Pre-image data is accessed through syscalls exclusively.
The OP-stack fault-proof [Pre-image Oracle specs](../../specs/fault-proof.md#pre-image-oracle)
define the ABI for communicating pre-images.
This ABI is implemented by the VM by intercepting the `read`/`write` syscalls to specific file descriptors:
- `hint client read = 3`: used by the client to send hint data to the host. Optional, implemented as blocking.
- `hint client write = 4`: used by the client to wait for the host. Always instant, since the above is implemented as blocking.
- `preimage client read = 5`: used by the client to read pre-image data, starting from the latest pre-image reading offset.
- `preimage client write = 6`: used by the client to change the pre-image key. The key may change a little bit at a time. The last 32 written bytes count as key for retrieval when reading the pre-image. Changing the key also resets the read offset to 0.
The data is loaded into `PreimageOracle.sol` using the respective loading function based on the pre-image type.
And then retrieved during execution of the `read` syscall.
Note that although the oracle provides up to 32 bytes of the pre-image,
Cannon only supports reading at most 4 bytes at a time, to unify the memory operations with regular load/stores.
## Usage in Dispute Game
The onchain MIPS execution functions as base-case of an interactive dispute game.
The dispute game narrows down a sequence of disputed instructions to a single disputed instruction.
This instruction can then be executed onchain to determine objective truth.
The Dispute Game itself is out of scope for Cannon: Cannon is just one example of a fault-proof VM that
can be used to resolve disputes.
all: elf dump
.PHONY: elf
elf: $(patsubst %/go.mod,bin/%.elf,$(wildcard */go.mod))
.PHONY: dump
dump: $(patsubst %/go.mod,bin/%.dump,$(wildcard */go.mod))
bin:
mkdir bin
# take any directory with a go mod, and build an ELF
# verify output with: readelf -h bin/<name>.elf
# result is mips32, big endian, R3000
bin/%.elf: bin
cd $(@:bin/%.elf=%) && GOOS=linux GOARCH=mips GOMIPS=softfloat go build -o ../$@ .
# take any ELF and dump it
# TODO: currently have the little-endian toolchain, but should use the big-endian one. The -EB compat flag works though.
bin/%.dump: bin/%.elf
mipsel-linux-gnu-objdump -D --disassembler-options=no-aliases --wide --source -m mips:3000 -EB $(@:%.dump=%.elf) > $@
module claim
go 1.20
require github.com/ethereum-optimism/optimism v0.0.0
require (
golang.org/x/crypto v0.8.0 // indirect
golang.org/x/sys v0.7.0 // indirect
)
replace github.com/ethereum-optimism/optimism v0.0.0 => ../../..
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
package main
import (
"encoding/binary"
"fmt"
"os"
"github.com/ethereum-optimism/optimism/op-preimage"
)
type rawHint string
func (rh rawHint) Hint() string {
return string(rh)
}
func main() {
_, _ = os.Stderr.Write([]byte("started!"))
po := preimage.NewOracleClient(preimage.ClientPreimageChannel())
hinter := preimage.NewHintWriter(preimage.ClientHinterChannel())
preHash := *(*[32]byte)(po.Get(preimage.LocalIndexKey(0)))
diffHash := *(*[32]byte)(po.Get(preimage.LocalIndexKey(1)))
claimData := *(*[8]byte)(po.Get(preimage.LocalIndexKey(2)))
// Hints are used to indicate which things the program will access,
// so the server can be prepared to serve the corresponding pre-images.
hinter.Hint(rawHint(fmt.Sprintf("fetch-state %x", preHash)))
pre := po.Get(preimage.Keccak256Key(preHash))
// Multiple pre-images may be fetched based on a hint.
// E.g. when we need all values of a merkle-tree.
hinter.Hint(rawHint(fmt.Sprintf("fetch-diff %x", diffHash)))
diff := po.Get(preimage.Keccak256Key(diffHash))
diffPartA := po.Get(preimage.Keccak256Key(*(*[32]byte)(diff[:32])))
diffPartB := po.Get(preimage.Keccak256Key(*(*[32]byte)(diff[32:])))
// Example state-transition function: s' = s*a + b
s := binary.BigEndian.Uint64(pre)
a := binary.BigEndian.Uint64(diffPartA)
b := binary.BigEndian.Uint64(diffPartB)
fmt.Printf("computing %d * %d + %d\n", s, a, b)
sOut := s*a + b
sClaim := binary.BigEndian.Uint64(claimData[:])
if sOut != sClaim {
fmt.Printf("claim %d is bad! Correct result is %d\n", sOut, sClaim)
os.Exit(1)
} else {
fmt.Printf("claim %d is good!\n", sOut)
os.Exit(0)
}
}
package main
import "os"
func main() {
_, _ = os.Stdout.Write([]byte("hello world!\n"))
}
package main
import (
"context"
"errors"
"fmt"
"os"
"os/signal"
"syscall"
"github.com/urfave/cli/v2"
"github.com/ethereum-optimism/optimism/cannon/cmd"
)
func main() {
app := cli.NewApp()
app.Name = "cannon"
app.Usage = "MIPS Fault Proof tool"
app.Description = "MIPS Fault Proof tool"
app.Commands = []*cli.Command{
cmd.LoadELFCommand,
cmd.RunCommand,
}
ctx, cancel := context.WithCancel(context.Background())
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
go func() {
for {
<-c
cancel()
fmt.Println("\r\nExiting...")
}
}()
err := app.RunContext(ctx, os.Args)
if err != nil {
if errors.Is(err, ctx.Err()) {
_, _ = fmt.Fprintf(os.Stderr, "command interrupted")
os.Exit(130)
} else {
_, _ = fmt.Fprintf(os.Stderr, "error: %v", err)
os.Exit(1)
}
}
}
mipsevm
mipsevm.test
*.prof
# `mipsevm`
Supported 55 instructions:
```
'addi', 'addiu', 'addu', 'and', 'andi',
'b', 'beq', 'beqz', 'bgez', 'bgtz', 'blez', 'bltz', 'bne', 'bnez',
'clz', 'divu',
'j', 'jal', 'jalr', 'jr',
'lb', 'lbu', 'lui', 'lw', 'lwr',
'mfhi', 'mflo', 'move', 'movn', 'movz', 'mtlo', 'mul', 'multu',
'negu', 'nop', 'not', 'or', 'ori',
'sb', 'sll', 'sllv', 'slt', 'slti', 'sltiu', 'sltu', 'sra', 'srl', 'srlv', 'subu', 'sw', 'swr', 'sync', 'syscall',
'xor', 'xori'
```
To run:
1. Load a program into a state, e.g. using `LoadELF`.
2. Patch the program if necessary: e.g. using `PatchGo` for Go programs, `PatchStack` for empty initial stack, etc.
4. Implement the `PreimageOracle` interface
5. Instrument the emulator with the state, and pre-image oracle, using `NewInstrumentedState`
6. Step through the instrumented state with `Step(proof)`,
where `proof==true` if witness data should be generated. Steps are faster with `proof==false`.
7. Optionally repeat the step on-chain by calling `MIPS.sol` and `PreimageOracle.sol`, using the above witness data.
package mipsevm
import (
"encoding/binary"
"encoding/json"
"fmt"
"math/big"
"os"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-chain-ops/srcmap"
)
var (
StepBytes4 = crypto.Keccak256([]byte("Step(bytes,bytes)"))[:4]
CheatBytes4 = crypto.Keccak256([]byte("cheat(uint256,bytes32,bytes32,uint256)"))[:4]
LoadKeccak256PreimagePartBytes4 = crypto.Keccak256([]byte("loadKeccak256PreimagePart(uint256,bytes)"))[:4]
)
// LoadContracts loads the Cannon contracts, from op-bindings package
func LoadContracts() (*Contracts, error) {
var mips, oracle Contract
mips.DeployedBytecode.Object = hexutil.MustDecode(bindings.MIPSDeployedBin)
mips.DeployedBytecode.SourceMap = bindings.MIPSDeployedSourceMap
oracle.DeployedBytecode.Object = hexutil.MustDecode(bindings.PreimageOracleDeployedBin)
oracle.DeployedBytecode.SourceMap = bindings.PreimageOracleDeployedSourceMap
return &Contracts{
MIPS: &mips,
Oracle: &oracle,
}, nil
}
// LoadContractsFromFiles loads the Cannon contracts, from local filesystem
func LoadContractsFromFiles() (*Contracts, error) {
mips, err := LoadContract("MIPS")
if err != nil {
return nil, err
}
oracle, err := LoadContract("Oracle")
if err != nil {
return nil, err
}
return &Contracts{
MIPS: mips,
Oracle: oracle,
}, nil
}
func LoadContract(name string) (*Contract, error) {
dat, err := os.ReadFile(fmt.Sprintf("../../packages/contracts-bedrock/forge-artifacts/%s.sol/%s.json", name, name))
if err != nil {
return nil, fmt.Errorf("failed to read contract JSON definition of %q: %w", name, err)
}
var out Contract
if err := json.Unmarshal(dat, &out); err != nil {
return nil, fmt.Errorf("failed to parse contract JSON definition of %q: %w", name, err)
}
return &out, nil
}
type Contract struct {
DeployedBytecode struct {
Object hexutil.Bytes `json:"object"`
SourceMap string `json:"sourceMap"`
} `json:"deployedBytecode"`
// ignore abi,bytecode,etc.
}
func (c *Contract) SourceMap(sourcePaths []string) (*srcmap.SourceMap, error) {
return srcmap.ParseSourceMap(sourcePaths, c.DeployedBytecode.Object, c.DeployedBytecode.SourceMap)
}
type Contracts struct {
MIPS *Contract
Oracle *Contract
}
type Addresses struct {
MIPS common.Address
Oracle common.Address
Sender common.Address
FeeRecipient common.Address
}
func NewEVMEnv(contracts *Contracts, addrs *Addresses) (*vm.EVM, *state.StateDB) {
chainCfg := params.MainnetChainConfig
offsetBlocks := uint64(1000) // blocks after shanghai fork
bc := &testChain{startTime: *chainCfg.ShanghaiTime + offsetBlocks*12}
header := bc.GetHeader(common.Hash{}, 17034870+offsetBlocks)
db := rawdb.NewMemoryDatabase()
statedb := state.NewDatabase(db)
state, err := state.New(types.EmptyRootHash, statedb, nil)
if err != nil {
panic(fmt.Errorf("failed to create memory state db: %w", err))
}
blockContext := core.NewEVMBlockContext(header, bc, nil, chainCfg, state)
vmCfg := vm.Config{}
env := vm.NewEVM(blockContext, vm.TxContext{}, state, chainCfg, vmCfg)
// pre-deploy the contracts
env.StateDB.SetCode(addrs.MIPS, contracts.MIPS.DeployedBytecode.Object)
env.StateDB.SetCode(addrs.Oracle, contracts.Oracle.DeployedBytecode.Object)
env.StateDB.SetState(addrs.MIPS, common.Hash{}, addrs.Oracle.Hash())
rules := env.ChainConfig().Rules(header.Number, true, header.Time)
env.StateDB.Prepare(rules, addrs.Sender, addrs.FeeRecipient, &addrs.MIPS, vm.ActivePrecompiles(rules), nil)
return env, state
}
type testChain struct {
startTime uint64
}
func (d *testChain) Engine() consensus.Engine {
return ethash.NewFullFaker()
}
func (d *testChain) GetHeader(h common.Hash, n uint64) *types.Header {
parentHash := common.Hash{0: 0xff}
binary.BigEndian.PutUint64(parentHash[1:], n-1)
return &types.Header{
ParentHash: parentHash,
UncleHash: types.EmptyUncleHash,
Coinbase: common.Address{},
Root: common.Hash{},
TxHash: types.EmptyTxsHash,
ReceiptHash: types.EmptyReceiptsHash,
Bloom: types.Bloom{},
Difficulty: big.NewInt(0),
Number: new(big.Int).SetUint64(n),
GasLimit: 30_000_000,
GasUsed: 0,
Time: d.startTime + n*12,
Extra: nil,
MixDigest: common.Hash{},
Nonce: types.BlockNonce{},
BaseFee: big.NewInt(7),
WithdrawalsHash: &types.EmptyWithdrawalsHash,
}
}
package mipsevm
import (
"bytes"
"debug/elf"
"io"
"math/big"
"os"
"path"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-chain-ops/srcmap"
)
func testContractsSetup(t *testing.T) (*Contracts, *Addresses) {
contracts, err := LoadContracts()
require.NoError(t, err)
addrs := &Addresses{
MIPS: common.Address{0: 0xff, 19: 1},
Oracle: common.Address{0: 0xff, 19: 2},
Sender: common.Address{0x13, 0x37},
FeeRecipient: common.Address{0xaa},
}
return contracts, addrs
}
func SourceMapTracer(t *testing.T, contracts *Contracts, addrs *Addresses) vm.EVMLogger {
mipsSrcMap, err := contracts.MIPS.SourceMap([]string{"../../packages/contracts-bedrock/contracts/cannon/MIPS.sol"})
require.NoError(t, err)
oracleSrcMap, err := contracts.Oracle.SourceMap([]string{"../../packages/contracts-bedrock/contracts/cannon/PreimageOracle.sol"})
require.NoError(t, err)
return srcmap.NewSourceMapTracer(map[common.Address]*srcmap.SourceMap{addrs.MIPS: mipsSrcMap, addrs.Oracle: oracleSrcMap}, os.Stdout)
}
func MarkdownTracer() vm.EVMLogger {
return logger.NewMarkdownLogger(&logger.Config{}, os.Stdout)
}
func TestEVM(t *testing.T) {
testFiles, err := os.ReadDir("open_mips_tests/test/bin")
require.NoError(t, err)
contracts, addrs := testContractsSetup(t)
var tracer vm.EVMLogger // no-tracer by default, but see SourceMapTracer and MarkdownTracer
//tracer = SourceMapTracer(t, contracts, addrs)
sender := common.Address{0x13, 0x37}
for _, f := range testFiles {
t.Run(f.Name(), func(t *testing.T) {
if f.Name() == "oracle.bin" {
t.Skip("oracle test needs to be updated to use syscall pre-image oracle")
}
env, evmState := NewEVMEnv(contracts, addrs)
env.Config.Tracer = tracer
fn := path.Join("open_mips_tests/test/bin", f.Name())
programMem, err := os.ReadFile(fn)
require.NoError(t, err)
state := &State{PC: 0, NextPC: 4, Memory: NewMemory()}
err = state.Memory.SetMemoryRange(0, bytes.NewReader(programMem))
require.NoError(t, err, "load program into state")
// set the return address ($ra) to jump into when test completes
state.Registers[31] = endAddr
us := NewInstrumentedState(state, nil, os.Stdout, os.Stderr)
for i := 0; i < 1000; i++ {
if us.state.PC == endAddr {
break
}
insn := state.Memory.GetMemory(state.PC)
t.Logf("step: %4d pc: 0x%08x insn: 0x%08x", state.Step, state.PC, insn)
stepWitness, err := us.Step(true)
require.NoError(t, err)
input := stepWitness.EncodeStepInput()
startingGas := uint64(30_000_000)
// we take a snapshot so we can clean up the state, and isolate the logs of this instruction run.
snap := env.StateDB.Snapshot()
ret, leftOverGas, err := env.Call(vm.AccountRef(sender), addrs.MIPS, input, startingGas, big.NewInt(0))
require.NoError(t, err, "evm should not fail")
require.Len(t, ret, 32, "expecting 32-byte state hash")
// remember state hash, to check it against state
postHash := common.Hash(*(*[32]byte)(ret))
logs := evmState.Logs()
require.Equal(t, 1, len(logs), "expecting a log with post-state")
evmPost := logs[0].Data
require.Equal(t, crypto.Keccak256Hash(evmPost), postHash, "logged state must be accurate")
env.StateDB.RevertToSnapshot(snap)
t.Logf("EVM step took %d gas, and returned stateHash %s", startingGas-leftOverGas, postHash)
// verify the post-state matches.
// 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")
}
require.Equal(t, uint32(endAddr), state.PC, "must reach end")
// inspect test result
done, result := state.Memory.GetMemory(baseAddrEnd+4), state.Memory.GetMemory(baseAddrEnd+8)
require.Equal(t, done, uint32(1), "must be done")
require.Equal(t, result, uint32(1), "must have success result")
})
}
}
func TestHelloEVM(t *testing.T) {
contracts, addrs := testContractsSetup(t)
var tracer vm.EVMLogger // no-tracer by default, but see SourceMapTracer and MarkdownTracer
//tracer = SourceMapTracer(t, contracts, addrs)
sender := common.Address{0x13, 0x37}
elfProgram, err := elf.Open("../example/bin/hello.elf")
require.NoError(t, err, "open ELF file")
state, err := LoadELF(elfProgram)
require.NoError(t, err, "load ELF into state")
err = PatchGo(elfProgram, state)
require.NoError(t, err, "apply Go runtime patches")
require.NoError(t, PatchStack(state), "add initial stack")
var stdOutBuf, stdErrBuf bytes.Buffer
us := NewInstrumentedState(state, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr))
env, evmState := NewEVMEnv(contracts, addrs)
env.Config.Tracer = tracer
start := time.Now()
for i := 0; i < 400_000; i++ {
if us.state.Exited {
break
}
insn := state.Memory.GetMemory(state.PC)
if i%1000 == 0 { // avoid spamming test logs, we are executing many steps
t.Logf("step: %4d pc: 0x%08x insn: 0x%08x", state.Step, state.PC, insn)
}
stepWitness, err := us.Step(true)
require.NoError(t, err)
input := stepWitness.EncodeStepInput()
startingGas := uint64(30_000_000)
// we take a snapshot so we can clean up the state, and isolate the logs of this instruction run.
snap := env.StateDB.Snapshot()
ret, leftOverGas, err := env.Call(vm.AccountRef(sender), addrs.MIPS, input, startingGas, big.NewInt(0))
require.NoErrorf(t, err, "evm should not fail, took %d gas", startingGas-leftOverGas)
require.Len(t, ret, 32, "expecting 32-byte state hash")
// remember state hash, to check it against state
postHash := common.Hash(*(*[32]byte)(ret))
logs := evmState.Logs()
require.Equal(t, 1, len(logs), "expecting a log with post-state")
evmPost := logs[0].Data
require.Equal(t, crypto.Keccak256Hash(evmPost), postHash, "logged state must be accurate")
env.StateDB.RevertToSnapshot(snap)
//t.Logf("EVM step took %d gas, and returned stateHash %s", startingGas-leftOverGas, postHash)
// verify the post-state matches.
// 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")
}
end := time.Now()
delta := end.Sub(start)
t.Logf("test took %s, %d instructions, %s per instruction", delta, state.Step, delta/time.Duration(state.Step))
require.True(t, state.Exited, "must complete program")
require.Equal(t, uint8(0), state.ExitCode, "exit with 0")
require.Equal(t, "hello world!\n", stdOutBuf.String(), "stdout says hello")
require.Equal(t, "", stdErrBuf.String(), "stderr silent")
}
func TestClaimEVM(t *testing.T) {
contracts, addrs := testContractsSetup(t)
var tracer vm.EVMLogger // no-tracer by default, but see SourceMapTracer and MarkdownTracer
//tracer = SourceMapTracer(t, contracts, addrs)
elfProgram, err := elf.Open("../example/bin/claim.elf")
require.NoError(t, err, "open ELF file")
state, err := LoadELF(elfProgram)
require.NoError(t, err, "load ELF into state")
err = PatchGo(elfProgram, state)
require.NoError(t, err, "apply Go runtime patches")
require.NoError(t, PatchStack(state), "add initial stack")
oracle, expectedStdOut, expectedStdErr := claimTestOracle(t)
var stdOutBuf, stdErrBuf bytes.Buffer
us := NewInstrumentedState(state, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr))
env, evmState := NewEVMEnv(contracts, addrs)
env.Config.Tracer = tracer
for i := 0; i < 2000_000; i++ {
if us.state.Exited {
break
}
insn := state.Memory.GetMemory(state.PC)
if i%1000 == 0 { // avoid spamming test logs, we are executing many steps
t.Logf("step: %4d pc: 0x%08x insn: 0x%08x", state.Step, state.PC, insn)
}
stepWitness, err := us.Step(true)
require.NoError(t, err)
input := stepWitness.EncodeStepInput()
startingGas := uint64(30_000_000)
// we take a snapshot so we can clean up the state, and isolate the logs of this instruction run.
snap := env.StateDB.Snapshot()
// prepare pre-image oracle data, if any
if stepWitness.HasPreimage() {
poInput, err := stepWitness.EncodePreimageOracleInput()
require.NoError(t, err, "encode preimage oracle input")
_, leftOverGas, err := env.Call(vm.AccountRef(addrs.Sender), addrs.Oracle, poInput, startingGas, big.NewInt(0))
require.NoErrorf(t, err, "evm should not fail, took %d gas", startingGas-leftOverGas)
}
ret, leftOverGas, err := env.Call(vm.AccountRef(addrs.Sender), addrs.MIPS, input, startingGas, big.NewInt(0))
require.NoErrorf(t, err, "evm should not fail, took %d gas", startingGas-leftOverGas)
require.Len(t, ret, 32, "expecting 32-byte state hash")
// remember state hash, to check it against state
postHash := common.Hash(*(*[32]byte)(ret))
logs := evmState.Logs()
require.Equal(t, 1, len(logs), "expecting a log with post-state")
evmPost := logs[0].Data
require.Equal(t, crypto.Keccak256Hash(evmPost), postHash, "logged state must be accurate")
env.StateDB.RevertToSnapshot(snap)
}
require.True(t, state.Exited, "must complete program")
require.Equal(t, uint8(0), state.ExitCode, "exit with 0")
require.Equal(t, expectedStdOut, stdOutBuf.String(), "stdout")
require.Equal(t, expectedStdErr, stdErrBuf.String(), "stderr")
}
package mipsevm
import (
"io"
)
type PreimageOracle interface {
Hint(v []byte)
GetPreimage(k [32]byte) []byte
}
type InstrumentedState struct {
state *State
stdOut io.Writer
stdErr io.Writer
lastMemAccess uint32
memProofEnabled bool
memProof [28 * 32]byte
preimageOracle PreimageOracle
// cached pre-image data, including 8 byte length prefix
lastPreimage []byte
// key for above preimage
lastPreimageKey [32]byte
// offset we last read from, or max uint32 if nothing is read this step
lastPreimageOffset uint32
}
const (
fdStdin = 0
fdStdout = 1
fdStderr = 2
fdHintRead = 3
fdHintWrite = 4
fdPreimageRead = 5
fdPreimageWrite = 6
)
const (
MipsEBADF = 0x9
MipsEINVAL = 0x16
)
func NewInstrumentedState(state *State, po PreimageOracle, stdOut, stdErr io.Writer) *InstrumentedState {
return &InstrumentedState{
state: state,
stdOut: stdOut,
stdErr: stdErr,
preimageOracle: po,
}
}
func (m *InstrumentedState) Step(proof bool) (wit *StepWitness, err error) {
m.memProofEnabled = proof
m.lastMemAccess = ^uint32(0)
m.lastPreimageOffset = ^uint32(0)
if proof {
insnProof := m.state.Memory.MerkleProof(m.state.PC)
wit = &StepWitness{
State: m.state.EncodeWitness(),
MemProof: insnProof[:],
}
}
err = m.mipsStep()
if err != nil {
return nil, err
}
if proof {
wit.MemProof = append(wit.MemProof, m.memProof[:]...)
if m.lastPreimageOffset != ^uint32(0) {
wit.PreimageOffset = m.lastPreimageOffset
wit.PreimageKey = m.lastPreimageKey
wit.PreimageValue = m.lastPreimage
}
}
return
}
package mipsevm
import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log"
)
// LoggingWriter is a simple util to wrap a logger,
// and expose an io Writer interface,
// for the program running within the VM to write to.
type LoggingWriter struct {
Name string
Log log.Logger
}
func logAsText(b string) bool {
for _, c := range b {
if (c < 0x20 || c >= 0x7F) && (c != '\n' && c != '\t') {
return false
}
}
return true
}
func (lw *LoggingWriter) Write(b []byte) (int, error) {
t := string(b)
if logAsText(t) {
lw.Log.Info("", "text", t)
} else {
lw.Log.Info("", "data", hexutil.Bytes(b))
}
return len(b), nil
}
package mipsevm
import (
"encoding/binary"
"encoding/json"
"fmt"
"io"
"math/bits"
"sort"
"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.
const (
PageAddrSize = 12
PageKeySize = 32 - PageAddrSize
PageSize = 1 << PageAddrSize
PageAddrMask = PageSize - 1
MaxPageCount = 1 << PageKeySize
PageKeyMask = MaxPageCount - 1
)
func HashPair(left, right [32]byte) [32]byte {
out := crypto.Keccak256Hash(left[:], right[:])
//fmt.Printf("0x%x 0x%x -> 0x%x\n", left, right, out)
return out
}
var zeroHashes = func() [256][32]byte {
// empty parts of the tree are all zero. Precompute the hash of each full-zero range sub-tree level.
var out [256][32]byte
for i := 1; i < 256; i++ {
out[i] = HashPair(out[i-1], out[i-1])
}
return out
}()
type Memory struct {
// generalized index -> merkle root or nil if invalidated
nodes map[uint64]*[32]byte
// pageIndex -> cached page
pages map[uint32]*CachedPage
// Note: since we don't de-alloc pages, we don't do ref-counting.
// Once a page exists, it doesn't leave memory
// two caches: we often read instructions from one page, and do memory things with another page.
// this prevents map lookups each instruction
lastPageKeys [2]uint32
lastPage [2]*CachedPage
}
func NewMemory() *Memory {
return &Memory{
nodes: make(map[uint64]*[32]byte),
pages: make(map[uint32]*CachedPage),
lastPageKeys: [2]uint32{^uint32(0), ^uint32(0)}, // default to invalid keys, to not match any pages
}
}
func (m *Memory) PageCount() int {
return len(m.pages)
}
func (m *Memory) ForEachPage(fn func(pageIndex uint32, page *Page) error) error {
for pageIndex, cachedPage := range m.pages {
if err := fn(pageIndex, cachedPage.Data); err != nil {
return err
}
}
return nil
}
func (m *Memory) Invalidate(addr uint32) {
// addr must be aligned to 4 bytes
if addr&0x3 != 0 {
panic(fmt.Errorf("unaligned memory access: %x", addr))
}
// find page, and invalidate addr within it
if p, ok := m.pageLookup(addr >> PageAddrSize); ok {
prevValid := p.Ok[1]
p.Invalidate(addr & PageAddrMask)
if !prevValid { // if the page was already invalid before, then nodes to mem-root will also still be.
return
}
} else { // no page? nothing to invalidate
return
}
// find the gindex of the first page covering the address
gindex := ((uint64(1) << 32) | uint64(addr)) >> PageAddrSize
for gindex > 0 {
m.nodes[gindex] = nil
gindex >>= 1
}
}
func (m *Memory) MerkleizeSubtree(gindex uint64) [32]byte {
l := uint64(bits.Len64(gindex))
if l > 28 {
panic("gindex too deep")
}
if l > PageKeySize {
depthIntoPage := l - 1 - PageKeySize
pageIndex := (gindex >> depthIntoPage) & PageKeyMask
if p, ok := m.pages[uint32(pageIndex)]; ok {
pageGindex := (1 << depthIntoPage) | (gindex & ((1 << depthIntoPage) - 1))
return p.MerkleizeSubtree(pageGindex)
} else {
return zeroHashes[28-l] // page does not exist
}
}
if l > PageKeySize+1 {
panic("cannot jump into intermediate node of page")
}
n, ok := m.nodes[gindex]
if !ok {
// if the node doesn't exist, the whole sub-tree is zeroed
return zeroHashes[28-l]
}
if n != nil {
return *n
}
left := m.MerkleizeSubtree(gindex << 1)
right := m.MerkleizeSubtree((gindex << 1) | 1)
r := HashPair(left, right)
m.nodes[gindex] = &r
return r
}
func (m *Memory) MerkleProof(addr uint32) (out [28 * 32]byte) {
proof := m.traverseBranch(1, addr, 0)
// encode the proof
for i := 0; i < 28; i++ {
copy(out[i*32:(i+1)*32], proof[i][:])
}
return out
}
func (m *Memory) traverseBranch(parent uint64, addr uint32, depth uint8) (proof [][32]byte) {
if depth == 32-5 {
proof = make([][32]byte, 0, 32-5+1)
proof = append(proof, m.MerkleizeSubtree(parent))
return
}
if depth > 32-5 {
panic("traversed too deep")
}
self := parent << 1
sibling := self | 1
if addr&(1<<(31-depth)) != 0 {
self, sibling = sibling, self
}
proof = m.traverseBranch(self, addr, depth+1)
siblingNode := m.MerkleizeSubtree(sibling)
proof = append(proof, siblingNode)
return
}
func (m *Memory) MerkleRoot() [32]byte {
return m.MerkleizeSubtree(1)
}
func (m *Memory) pageLookup(pageIndex uint32) (*CachedPage, bool) {
// hit caches
if pageIndex == m.lastPageKeys[0] {
return m.lastPage[0], true
}
if pageIndex == m.lastPageKeys[1] {
return m.lastPage[1], true
}
p, ok := m.pages[pageIndex]
// only cache existing pages.
if ok {
m.lastPageKeys[1] = m.lastPageKeys[0]
m.lastPage[1] = m.lastPage[0]
m.lastPageKeys[0] = pageIndex
m.lastPage[0] = p
}
return p, ok
}
func (m *Memory) SetMemory(addr uint32, v uint32) {
// addr must be aligned to 4 bytes
if addr&0x3 != 0 {
panic(fmt.Errorf("unaligned memory access: %x", addr))
}
pageIndex := addr >> PageAddrSize
pageAddr := addr & PageAddrMask
p, ok := m.pageLookup(pageIndex)
if !ok {
// allocate the page if we have not already.
// Go may mmap relatively large ranges, but we only allocate the pages just in time.
p = m.AllocPage(pageIndex)
} else {
m.Invalidate(addr) // invalidate this branch of memory, now that the value changed
}
binary.BigEndian.PutUint32(p.Data[pageAddr:pageAddr+4], v)
}
func (m *Memory) GetMemory(addr uint32) uint32 {
// addr must be aligned to 4 bytes
if addr&0x3 != 0 {
panic(fmt.Errorf("unaligned memory access: %x", addr))
}
p, ok := m.pageLookup(addr >> PageAddrSize)
if !ok {
return 0
}
pageAddr := addr & PageAddrMask
return binary.BigEndian.Uint32(p.Data[pageAddr : pageAddr+4])
}
func (m *Memory) AllocPage(pageIndex uint32) *CachedPage {
p := &CachedPage{Data: new(Page)}
m.pages[pageIndex] = p
// make nodes to root
k := (1 << PageKeySize) | uint64(pageIndex)
for k > 0 {
m.nodes[k] = nil
k >>= 1
}
return p
}
type pageEntry struct {
Index uint32 `json:"index"`
Data *Page `json:"data"`
}
func (m *Memory) MarshalJSON() ([]byte, error) { // nosemgrep
pages := make([]pageEntry, 0, len(m.pages))
for k, p := range m.pages {
pages = append(pages, pageEntry{
Index: k,
Data: p.Data,
})
}
sort.Slice(pages, func(i, j int) bool {
return pages[i].Index < pages[j].Index
})
return json.Marshal(pages)
}
func (m *Memory) UnmarshalJSON(data []byte) error {
var pages []pageEntry
if err := json.Unmarshal(data, &pages); err != nil {
return err
}
m.nodes = make(map[uint64]*[32]byte)
m.pages = make(map[uint32]*CachedPage)
m.lastPageKeys = [2]uint32{^uint32(0), ^uint32(0)}
m.lastPage = [2]*CachedPage{nil, nil}
for i, p := range pages {
if _, ok := m.pages[p.Index]; ok {
return fmt.Errorf("cannot load duplicate page, entry %d, page index %d", i, p.Index)
}
m.AllocPage(p.Index).Data = p.Data
}
return nil
}
func (m *Memory) SetMemoryRange(addr uint32, r io.Reader) error {
for {
pageIndex := addr >> PageAddrSize
pageAddr := addr & PageAddrMask
p, ok := m.pageLookup(pageIndex)
if !ok {
p = m.AllocPage(pageIndex)
}
p.InvalidateFull()
n, err := r.Read(p.Data[pageAddr:])
if err != nil {
if err == io.EOF {
return nil
}
return err
}
addr += uint32(n)
}
}
type memReader struct {
m *Memory
addr uint32
count uint32
}
func (r *memReader) Read(dest []byte) (n int, err error) {
if r.count == 0 {
return 0, io.EOF
}
// Keep iterating over memory until we have all our data.
// It may wrap around the address range, and may not be aligned
endAddr := r.addr + r.count
pageIndex := r.addr >> PageAddrSize
start := r.addr & PageAddrMask
end := uint32(PageSize)
if pageIndex == (endAddr >> PageAddrSize) {
end = endAddr & PageAddrMask
}
p, ok := r.m.pageLookup(pageIndex)
if ok {
n = copy(dest, p.Data[start:end])
} else {
n = copy(dest, make([]byte, end-start)) // default to zeroes
}
r.addr += uint32(n)
r.count -= uint32(n)
return n, nil
}
func (m *Memory) ReadMemoryRange(addr uint32, count uint32) io.Reader {
return &memReader{m: m, addr: addr, count: count}
}
func (m *Memory) Usage() string {
total := uint64(len(m.pages)) * PageSize
const unit = 1024
if total < unit {
return fmt.Sprintf("%d B", total)
}
div, exp := uint64(unit), 0
for n := total / unit; n >= unit; n /= unit {
div *= unit
exp++
}
// KiB, MiB, GiB, TiB, ...
return fmt.Sprintf("%.1f %ciB", float64(total)/float64(div), "KMGTPE"[exp])
}
package mipsevm
import (
"bytes"
"crypto/rand"
"encoding/binary"
"encoding/json"
"io"
"strings"
"testing"
"github.com/stretchr/testify/require"
)
func TestMemoryMerkleProof(t *testing.T) {
t.Run("nearly empty tree", func(t *testing.T) {
m := NewMemory()
m.SetMemory(0x10000, 0xaabbccdd)
proof := m.MerkleProof(0x10000)
require.Equal(t, uint32(0xaabbccdd), binary.BigEndian.Uint32(proof[:4]))
for i := 0; i < 32-5; i++ {
require.Equal(t, zeroHashes[i][:], proof[32+i*32:32+i*32+32], "empty siblings")
}
})
t.Run("fuller tree", func(t *testing.T) {
m := NewMemory()
m.SetMemory(0x10000, 0xaabbccdd)
m.SetMemory(0x80004, 42)
m.SetMemory(0x13370000, 123)
root := m.MerkleRoot()
proof := m.MerkleProof(0x80004)
require.Equal(t, uint32(42), binary.BigEndian.Uint32(proof[4:8]))
node := *(*[32]byte)(proof[:32])
path := uint32(0x80004) >> 5
for i := 32; i < len(proof); i += 32 {
sib := *(*[32]byte)(proof[i : i+32])
if path&1 != 0 {
node = HashPair(sib, node)
} else {
node = HashPair(node, sib)
}
path >>= 1
}
require.Equal(t, root, node, "proof must verify")
})
}
func TestMemoryMerkleRoot(t *testing.T) {
t.Run("empty", func(t *testing.T) {
m := NewMemory()
root := m.MerkleRoot()
require.Equal(t, zeroHashes[32-5], root, "fully zeroed memory should have expected zero hash")
})
t.Run("empty page", func(t *testing.T) {
m := NewMemory()
m.SetMemory(0xF000, 0)
root := m.MerkleRoot()
require.Equal(t, zeroHashes[32-5], root, "fully zeroed memory should have expected zero hash")
})
t.Run("single page", func(t *testing.T) {
m := NewMemory()
m.SetMemory(0xF000, 1)
root := m.MerkleRoot()
require.NotEqual(t, zeroHashes[32-5], root, "non-zero memory")
})
t.Run("repeat zero", func(t *testing.T) {
m := NewMemory()
m.SetMemory(0xF000, 0)
m.SetMemory(0xF004, 0)
root := m.MerkleRoot()
require.Equal(t, zeroHashes[32-5], root, "zero still")
})
t.Run("two empty pages", func(t *testing.T) {
m := NewMemory()
m.SetMemory(PageSize*3, 0)
m.SetMemory(PageSize*10, 0)
root := m.MerkleRoot()
require.Equal(t, zeroHashes[32-5], root, "zero still")
})
t.Run("random few pages", func(t *testing.T) {
m := NewMemory()
m.SetMemory(PageSize*3, 1)
m.SetMemory(PageSize*5, 42)
m.SetMemory(PageSize*6, 123)
p3 := m.MerkleizeSubtree((1 << PageKeySize) | 3)
p5 := m.MerkleizeSubtree((1 << PageKeySize) | 5)
p6 := m.MerkleizeSubtree((1 << PageKeySize) | 6)
z := zeroHashes[PageAddrSize-5]
r1 := HashPair(
HashPair(
HashPair(z, z), // 0,1
HashPair(z, p3), // 2,3
),
HashPair(
HashPair(z, p5), // 4,5
HashPair(p6, z), // 6,7
),
)
r2 := m.MerkleizeSubtree(1 << (PageKeySize - 3))
require.Equal(t, r1, r2, "expecting manual page combination to match subtree merkle func")
})
t.Run("invalidate page", func(t *testing.T) {
m := NewMemory()
m.SetMemory(0xF000, 0)
require.Equal(t, zeroHashes[32-5], m.MerkleRoot(), "zero at first")
m.SetMemory(0xF004, 1)
require.NotEqual(t, zeroHashes[32-5], m.MerkleRoot(), "non-zero")
m.SetMemory(0xF004, 0)
require.Equal(t, zeroHashes[32-5], m.MerkleRoot(), "zero again")
})
}
func TestMemoryReadWrite(t *testing.T) {
t.Run("large random", func(t *testing.T) {
m := NewMemory()
data := make([]byte, 20_000)
_, err := rand.Read(data[:])
require.NoError(t, err)
require.NoError(t, m.SetMemoryRange(0, bytes.NewReader(data)))
for _, i := range []uint32{0, 4, 1000, 20_000 - 4} {
v := m.GetMemory(i)
expected := binary.BigEndian.Uint32(data[i : i+4])
require.Equalf(t, expected, v, "read at %d", i)
}
})
t.Run("repeat range", func(t *testing.T) {
m := NewMemory()
data := []byte(strings.Repeat("under the big bright yellow sun ", 40))
require.NoError(t, m.SetMemoryRange(0x1337, bytes.NewReader(data)))
res, err := io.ReadAll(m.ReadMemoryRange(0x1337-10, uint32(len(data)+20)))
require.NoError(t, err)
require.Equal(t, make([]byte, 10), res[:10], "empty start")
require.Equal(t, data, res[10:len(res)-10], "result")
require.Equal(t, make([]byte, 10), res[len(res)-10:], "empty end")
})
t.Run("read-write", func(t *testing.T) {
m := NewMemory()
m.SetMemory(12, 0xAABBCCDD)
require.Equal(t, uint32(0xAABBCCDD), m.GetMemory(12))
m.SetMemory(12, 0xAABB1CDD)
require.Equal(t, uint32(0xAABB1CDD), m.GetMemory(12))
})
t.Run("unaligned read", func(t *testing.T) {
m := NewMemory()
m.SetMemory(12, 0xAABBCCDD)
m.SetMemory(16, 0x11223344)
require.Panics(t, func() {
m.GetMemory(13)
})
require.Panics(t, func() {
m.GetMemory(14)
})
require.Panics(t, func() {
m.GetMemory(15)
})
require.Equal(t, uint32(0x11223344), m.GetMemory(16))
require.Equal(t, uint32(0), m.GetMemory(20))
require.Equal(t, uint32(0xAABBCCDD), m.GetMemory(12))
})
t.Run("unaligned write", func(t *testing.T) {
m := NewMemory()
m.SetMemory(12, 0xAABBCCDD)
require.Panics(t, func() {
m.SetMemory(13, 0x11223344)
})
require.Panics(t, func() {
m.SetMemory(14, 0x11223344)
})
require.Panics(t, func() {
m.SetMemory(15, 0x11223344)
})
require.Equal(t, uint32(0xAABBCCDD), m.GetMemory(12))
})
}
func TestMemoryJSON(t *testing.T) {
m := NewMemory()
m.SetMemory(8, 123)
dat, err := json.Marshal(m)
require.NoError(t, err)
var res Memory
require.NoError(t, json.Unmarshal(dat, &res))
require.Equal(t, uint32(123), res.GetMemory(8))
}
package mipsevm
import (
"debug/elf"
"fmt"
"sort"
)
type Symbol struct {
Name string `json:"name"`
Start uint32 `json:"start"`
Size uint32 `json:"size"`
}
type Metadata struct {
Symbols []Symbol `json:"symbols"`
}
func MakeMetadata(elfProgram *elf.File) (*Metadata, error) {
syms, err := elfProgram.Symbols()
if err != nil {
return nil, fmt.Errorf("failed to load symbols table: %w", err)
}
// Make sure the table is sorted, Go outputs mostly sorted data, except some internal functions
sort.Slice(syms, func(i, j int) bool {
return syms[i].Value < syms[j].Value
})
out := &Metadata{Symbols: make([]Symbol, len(syms))}
for i, s := range syms {
out.Symbols[i] = Symbol{Name: s.Name, Start: uint32(s.Value), Size: uint32(s.Size)}
}
return out, nil
}
func (m *Metadata) LookupSymbol(addr uint32) string {
if len(m.Symbols) == 0 {
return "!unknown"
}
// find first symbol with higher start. Or n if no such symbol exists
i := sort.Search(len(m.Symbols), func(i int) bool {
return m.Symbols[i].Start > addr
})
if i == 0 {
return "!start"
}
out := &m.Symbols[i-1]
if out.Start+out.Size < addr { // addr may be pointing to a gap between symbols
return "!gap"
}
return out.Name
}
func (m *Metadata) SymbolMatcher(name string) func(addr uint32) bool {
for _, s := range m.Symbols {
if s.Name == name {
start := s.Start
end := s.Start + s.Size
return func(addr uint32) bool {
return addr >= start && addr < end
}
}
}
return func(addr uint32) bool {
return false
}
}
// HexU32 to lazy-format integer attributes for logging
type HexU32 uint32
func (v HexU32) String() string {
return fmt.Sprintf("%08x", uint32(v))
}
func (v HexU32) MarshalText() ([]byte, error) {
return []byte(v.String()), nil
}
package mipsevm
import (
"encoding/binary"
"fmt"
"io"
)
func (m *InstrumentedState) readPreimage(key [32]byte, offset uint32) (dat [32]byte, datLen uint32) {
preimage := m.lastPreimage
if key != m.lastPreimageKey {
m.lastPreimageKey = key
data := m.preimageOracle.GetPreimage(key)
// add the length prefix
preimage = make([]byte, 0, 8+len(data))
preimage = binary.BigEndian.AppendUint64(preimage, uint64(len(data)))
preimage = append(preimage, data...)
m.lastPreimage = preimage
}
m.lastPreimageOffset = offset
datLen = uint32(copy(dat[:], preimage[offset:]))
return
}
func (m *InstrumentedState) trackMemAccess(effAddr uint32) {
if m.memProofEnabled && m.lastMemAccess != effAddr {
if m.lastMemAccess != ^uint32(0) {
panic(fmt.Errorf("unexpected different mem access at %08x, already have access at %08x buffered", effAddr, m.lastMemAccess))
}
m.lastMemAccess = effAddr
m.memProof = m.state.Memory.MerkleProof(effAddr)
}
}
func (m *InstrumentedState) handleSyscall() error {
syscallNum := m.state.Registers[2] // v0
v0 := uint32(0)
v1 := uint32(0)
a0 := m.state.Registers[4]
a1 := m.state.Registers[5]
a2 := m.state.Registers[6]
//fmt.Printf("syscall: %d\n", syscallNum)
switch syscallNum {
case 4090: // mmap
sz := a1
if sz&PageAddrMask != 0 { // adjust size to align with page size
sz += PageSize - (sz & PageAddrMask)
}
if a0 == 0 {
v0 = m.state.Heap
//fmt.Printf("mmap heap 0x%x size 0x%x\n", v0, sz)
m.state.Heap += sz
} else {
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)
v0 = 1
case 4246: // exit_group
m.state.Exited = true
m.state.ExitCode = uint8(a0)
return nil
case 4003: // read
// args: a0 = fd, a1 = addr, a2 = count
// returns: v0 = read, v1 = err code
switch a0 {
case fdStdin:
// leave v0 and v1 zero: read nothing, no error
case fdPreimageRead: // pre-image oracle
effAddr := a1 & 0xFFffFFfc
m.trackMemAccess(effAddr)
mem := m.state.Memory.GetMemory(effAddr)
dat, datLen := m.readPreimage(m.state.PreimageKey, m.state.PreimageOffset)
//fmt.Printf("reading pre-image data: addr: %08x, offset: %d, datLen: %d, data: %x, key: %s count: %d\n", a1, m.state.PreimageOffset, datLen, dat[:datLen], m.state.PreimageKey, a2)
alignment := a1 & 3
space := 4 - alignment
if space < datLen {
datLen = space
}
if a2 < datLen {
datLen = a2
}
var outMem [4]byte
binary.BigEndian.PutUint32(outMem[:], mem)
copy(outMem[alignment:], dat[:datLen])
m.state.Memory.SetMemory(effAddr, binary.BigEndian.Uint32(outMem[:]))
m.state.PreimageOffset += datLen
v0 = datLen
//fmt.Printf("read %d pre-image bytes, new offset: %d, eff addr: %08x mem: %08x\n", datLen, m.state.PreimageOffset, effAddr, outMem)
case fdHintRead: // hint response
// don't actually read into memory, just say we read it all, we ignore the result anyway
v0 = a2
default:
v0 = 0xFFffFFff
v1 = MipsEBADF
}
case 4004: // write
// args: a0 = fd, a1 = addr, a2 = count
// returns: v0 = written, v1 = err code
switch a0 {
case fdStdout:
_, _ = io.Copy(m.stdOut, m.state.Memory.ReadMemoryRange(a1, a2))
v0 = a2
case fdStderr:
_, _ = io.Copy(m.stdErr, m.state.Memory.ReadMemoryRange(a1, a2))
v0 = a2
case fdHintWrite:
hintData, _ := io.ReadAll(m.state.Memory.ReadMemoryRange(a1, a2))
m.state.LastHint = append(m.state.LastHint, hintData...)
for len(m.state.LastHint) >= 4 { // process while there is enough data to check if there are any hints
hintLen := binary.BigEndian.Uint32(m.state.LastHint[:4])
if hintLen >= uint32(len(m.state.LastHint[4:])) {
hint := m.state.LastHint[4 : 4+hintLen] // without the length prefix
m.state.LastHint = m.state.LastHint[4+hintLen:]
m.preimageOracle.Hint(hint)
} else {
break // stop processing hints if there is incomplete data buffered
}
}
v0 = a2
case fdPreimageWrite:
effAddr := a1 & 0xFFffFFfc
m.trackMemAccess(effAddr)
mem := m.state.Memory.GetMemory(effAddr)
key := m.state.PreimageKey
alignment := a1 & 3
space := 4 - alignment
if space < a2 {
a2 = space
}
copy(key[:], key[a2:])
var tmp [4]byte
binary.BigEndian.PutUint32(tmp[:], mem)
copy(key[32-a2:], tmp[:])
m.state.PreimageKey = key
m.state.PreimageOffset = 0
//fmt.Printf("updating pre-image key: %s\n", m.state.PreimageKey)
v0 = a2
default:
v0 = 0xFFffFFff
v1 = MipsEBADF
}
case 4055: // fcntl
// args: a0 = fd, a1 = cmd
if a1 == 3 { // F_GETFL: get file descriptor flags
switch a0 {
case fdStdin, fdPreimageRead, fdHintRead:
v0 = 0 // O_RDONLY
case fdStdout, fdStderr, fdPreimageWrite, fdHintWrite:
v0 = 1 // O_WRONLY
default:
v0 = 0xFFffFFff
v1 = MipsEBADF
}
} else {
v0 = 0xFFffFFff
v1 = MipsEINVAL // cmd not recognized by this kernel
}
}
m.state.Registers[2] = v0
m.state.Registers[7] = v1
m.state.PC = m.state.NextPC
m.state.NextPC = m.state.NextPC + 4
return nil
}
func (m *InstrumentedState) handleBranch(opcode uint32, insn uint32, rtReg uint32, rs uint32) error {
shouldBranch := false
if opcode == 4 || opcode == 5 { // beq/bne
rt := m.state.Registers[rtReg]
shouldBranch = (rs == rt && opcode == 4) || (rs != rt && opcode == 5)
} else if opcode == 6 {
shouldBranch = int32(rs) <= 0 // blez
} else if opcode == 7 {
shouldBranch = int32(rs) > 0 // bgtz
} else if opcode == 1 {
// regimm
rtv := (insn >> 16) & 0x1F
if rtv == 0 { // bltz
shouldBranch = int32(rs) < 0
}
if rtv == 1 { // bgez
shouldBranch = int32(rs) >= 0
}
}
prevPC := m.state.PC
m.state.PC = m.state.NextPC // execute the delay slot first
if shouldBranch {
m.state.NextPC = prevPC + 4 + (SE(insn&0xFFFF, 16) << 2) // then continue with the instruction the branch jumps to.
} else {
m.state.NextPC = m.state.NextPC + 4 // branch not taken
}
return nil
}
func (m *InstrumentedState) handleHiLo(fun uint32, rs uint32, rt uint32, storeReg uint32) error {
val := uint32(0)
switch fun {
case 0x10: // mfhi
val = m.state.HI
case 0x11: // mthi
m.state.HI = rs
case 0x12: // mflo
val = m.state.LO
case 0x13: // mtlo
m.state.LO = rs
case 0x18: // mult
acc := uint64(int64(int32(rs)) * int64(int32(rt)))
m.state.HI = uint32(acc >> 32)
m.state.LO = uint32(acc)
case 0x19: // multu
acc := uint64(uint64(rs) * uint64(rt))
m.state.HI = uint32(acc >> 32)
m.state.LO = uint32(acc)
case 0x1a: // div
m.state.HI = uint32(int32(rs) % int32(rt))
m.state.LO = uint32(int32(rs) / int32(rt))
case 0x1b: // divu
m.state.HI = rs % rt
m.state.LO = rs / rt
}
if storeReg != 0 {
m.state.Registers[storeReg] = val
}
m.state.PC = m.state.NextPC
m.state.NextPC = m.state.NextPC + 4
return nil
}
func (m *InstrumentedState) handleJump(linkReg uint32, dest uint32) error {
prevPC := m.state.PC
m.state.PC = m.state.NextPC
m.state.NextPC = dest
if linkReg != 0 {
m.state.Registers[linkReg] = prevPC + 8 // set the link-register to the instr after the delay slot instruction.
}
return nil
}
func (m *InstrumentedState) handleRd(storeReg uint32, val uint32, conditional bool) error {
if storeReg >= 32 {
panic("invalid register")
}
if storeReg != 0 && conditional {
m.state.Registers[storeReg] = val
}
m.state.PC = m.state.NextPC
m.state.NextPC = m.state.NextPC + 4
return nil
}
func (m *InstrumentedState) mipsStep() error {
if m.state.Exited {
return nil
}
m.state.Step += 1
// instruction fetch
insn := m.state.Memory.GetMemory(m.state.PC)
opcode := insn >> 26 // 6-bits
// j-type j/jal
if opcode == 2 || opcode == 3 {
// TODO likely bug in original code: MIPS spec says this should be in the "current" region;
// a 256 MB aligned region (i.e. use top 4 bits of branch delay slot (pc+4))
linkReg := uint32(0)
if opcode == 3 {
linkReg = 31
}
return m.handleJump(linkReg, SE(insn&0x03FFFFFF, 26)<<2)
}
// register fetch
rs := uint32(0) // source register 1 value
rt := uint32(0) // source register 2 / temp value
rtReg := (insn >> 16) & 0x1F
// R-type or I-type (stores rt)
rs = m.state.Registers[(insn>>21)&0x1F]
rdReg := rtReg
if opcode == 0 || opcode == 0x1c {
// R-type (stores rd)
rt = m.state.Registers[rtReg]
rdReg = (insn >> 11) & 0x1F
} else if opcode < 0x20 {
// rt is SignExtImm
// don't sign extend for andi, ori, xori
if opcode == 0xC || opcode == 0xD || opcode == 0xe {
// ZeroExtImm
rt = insn & 0xFFFF
} else {
// SignExtImm
rt = SE(insn&0xFFFF, 16)
}
} else if opcode >= 0x28 || opcode == 0x22 || opcode == 0x26 {
// store rt value with store
rt = m.state.Registers[rtReg]
// store actual rt with lwl and lwr
rdReg = rtReg
}
if (opcode >= 4 && opcode < 8) || opcode == 1 {
return m.handleBranch(opcode, insn, rtReg, rs)
}
storeAddr := uint32(0xFF_FF_FF_FF)
// memory fetch (all I-type)
// we do the load for stores also
mem := uint32(0)
if opcode >= 0x20 {
// M[R[rs]+SignExtImm]
rs += SE(insn&0xFFFF, 16)
addr := rs & 0xFFFFFFFC
m.trackMemAccess(addr)
mem = m.state.Memory.GetMemory(addr)
if opcode >= 0x28 && opcode != 0x30 {
// store
storeAddr = addr
// store opcodes don't write back to a register
rdReg = 0
}
}
// ALU
val := execute(insn, rs, rt, mem)
fun := insn & 0x3f // 6-bits
if opcode == 0 && fun >= 8 && fun < 0x1c {
if fun == 8 || fun == 9 { // jr/jalr
linkReg := uint32(0)
if fun == 9 {
linkReg = rdReg
}
return m.handleJump(linkReg, rs)
}
if fun == 0xa { // movz
return m.handleRd(rdReg, rs, rt == 0)
}
if fun == 0xb { // movn
return m.handleRd(rdReg, rs, rt != 0)
}
// syscall (can read and write)
if fun == 0xC {
return m.handleSyscall()
}
// lo and hi registers
// can write back
if fun >= 0x10 && fun < 0x1c {
return m.handleHiLo(fun, rs, rt, rdReg)
}
}
// stupid sc, write a 1 to rt
if opcode == 0x38 && rtReg != 0 {
m.state.Registers[rtReg] = 1
}
// write memory
if storeAddr != 0xFF_FF_FF_FF {
m.trackMemAccess(storeAddr)
m.state.Memory.SetMemory(storeAddr, val)
}
// write back the value to destination register
return m.handleRd(rdReg, val, true)
}
func execute(insn uint32, rs uint32, rt uint32, mem uint32) uint32 {
opcode := insn >> 26 // 6-bits
fun := insn & 0x3f // 6-bits
// TODO(CLI-4136): deref the immed into a register
if opcode < 0x20 {
// transform ArithLogI
// TODO(CLI-4136): replace with table
if opcode >= 8 && opcode < 0xF {
switch opcode {
case 8:
fun = 0x20 // addi
case 9:
fun = 0x21 // addiu
case 0xA:
fun = 0x2A // slti
case 0xB:
fun = 0x2B // sltiu
case 0xC:
fun = 0x24 // andi
case 0xD:
fun = 0x25 // ori
case 0xE:
fun = 0x26 // xori
}
opcode = 0
}
// 0 is opcode SPECIAL
if opcode == 0 {
shamt := (insn >> 6) & 0x1F
if fun < 0x20 {
switch {
case fun >= 0x08:
return rs // jr/jalr/div + others
case fun == 0x00:
return rt << shamt // sll
case fun == 0x02:
return rt >> shamt // srl
case fun == 0x03:
return SE(rt>>shamt, 32-shamt) // sra
case fun == 0x04:
return rt << (rs & 0x1F) // sllv
case fun == 0x06:
return rt >> (rs & 0x1F) // srlv
case fun == 0x07:
return SE(rt>>rs, 32-rs) // srav
}
}
// 0x10-0x13 = mfhi, mthi, mflo, mtlo
// R-type (ArithLog)
switch fun {
case 0x20, 0x21:
return rs + rt // add or addu
case 0x22, 0x23:
return rs - rt // sub or subu
case 0x24:
return rs & rt // and
case 0x25:
return rs | rt // or
case 0x26:
return rs ^ rt // xor
case 0x27:
return ^(rs | rt) // nor
case 0x2A:
if int32(rs) < int32(rt) {
return 1 // slt
} else {
return 0
}
case 0x2B:
if rs < rt {
return 1 // sltu
} else {
return 0
}
}
} else if opcode == 0xF {
return rt << 16 // lui
} else if opcode == 0x1C { // SPECIAL2
if fun == 2 { // mul
return uint32(int32(rs) * int32(rt))
}
if fun == 0x20 || fun == 0x21 { // clo
if fun == 0x20 {
rs = ^rs
}
i := uint32(0)
for ; rs&0x80000000 != 0; i++ {
rs <<= 1
}
return i
}
}
} else if opcode < 0x28 {
switch opcode {
case 0x20: // lb
return SE((mem>>(24-(rs&3)*8))&0xFF, 8)
case 0x21: // lh
return SE((mem>>(16-(rs&2)*8))&0xFFFF, 16)
case 0x22: // lwl
val := mem << ((rs & 3) * 8)
mask := uint32(0xFFFFFFFF) << ((rs & 3) * 8)
return (rt & ^mask) | val
case 0x23: // lw
return mem
case 0x24: // lbu
return (mem >> (24 - (rs&3)*8)) & 0xFF
case 0x25: // lhu
return (mem >> (16 - (rs&2)*8)) & 0xFFFF
case 0x26: // lwr
val := mem >> (24 - (rs&3)*8)
mask := uint32(0xFFFFFFFF) >> (24 - (rs&3)*8)
return (rt & ^mask) | val
}
} else if opcode == 0x28 { // sb
val := (rt & 0xFF) << (24 - (rs&3)*8)
mask := 0xFFFFFFFF ^ uint32(0xFF<<(24-(rs&3)*8))
return (mem & mask) | val
} else if opcode == 0x29 { // sh
val := (rt & 0xFFFF) << (16 - (rs&2)*8)
mask := 0xFFFFFFFF ^ uint32(0xFFFF<<(16-(rs&2)*8))
return (mem & mask) | val
} else if opcode == 0x2a { // swl
val := rt >> ((rs & 3) * 8)
mask := uint32(0xFFFFFFFF) >> ((rs & 3) * 8)
return (mem & ^mask) | val
} else if opcode == 0x2b { // sw
return rt
} else if opcode == 0x2e { // swr
val := rt << (24 - (rs&3)*8)
mask := uint32(0xFFFFFFFF) << (24 - (rs&3)*8)
return (mem & ^mask) | val
} else if opcode == 0x30 {
return mem // ll
} else if opcode == 0x38 {
return rt // sc
}
panic("invalid instruction")
}
func SE(dat uint32, idx uint32) uint32 {
isSigned := (dat >> (idx - 1)) != 0
signed := ((uint32(1) << (32 - idx)) - 1) << idx
mask := (uint32(1) << idx) - 1
if isSigned {
return dat&mask | signed
} else {
return dat & mask
}
}
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
# OpenMIPS test vectors
Tests from https://github.com/grantae/OpenMIPS/tree/d606b35e9d5260aef20de2a58660c8303a681e9c/software/test/macro/tests
OpenMIPS is licensed LGPLv3 (as seen in the root of the repository), see [`LICENSE`](./LICENSE) file.
Note that some build-system files from 2014/2015 in that repository by the same author are marked as BSD licensed,
but the build-system is not used here.
Requires https://github.com/sergev/LiteBSD/releases/download/tools/gcc-4.8.1-mips-macosx.tgz to build
#!/usr/bin/env python3
import os
import sys
import tempfile
from capstone import *
from elftools.elf.elffile import ELFFile
md = Cs(CS_ARCH_MIPS, CS_MODE_32 + CS_MODE_BIG_ENDIAN)
def maketest(d, out):
with tempfile.NamedTemporaryFile() as nf:
path = "/Users/kafka/fun/mips/mips-gcc-4.8.1/bin/"
print("building", d, "->", out)
# which mips is go
ret = os.system("%s/mips-elf-as -defsym big_endian=1 -march=mips32r2 -o %s %s" % (path, nf.name, d))
assert(ret == 0)
nf.seek(0)
elffile = ELFFile(nf)
#print(elffile)
for sec in elffile.iter_sections():
#print(sec, sec.name, sec.data())
if sec.name == ".test":
with open(out, "wb") as f:
# jump to 0xdead0000 when done
#data = b"\x24\x1f\xde\xad\x00\x1f\xfc\x00" + sec.data()
data = sec.data()
for dd in md.disasm(data, 0):
print(dd)
f.write(data)
if __name__ == "__main__":
os.makedirs("/tmp/mips", exist_ok=True)
if len(sys.argv) > 2:
maketest(sys.argv[1], sys.argv[2])
else:
for d in os.listdir("test/"):
if not d.endswith(".asm"):
continue
maketest("test/"+d, "test/bin/"+(d.replace(".asm", ".bin")))
\ No newline at end of file
###############################################################################
# File : add.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'add' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xffff # A = 0xfffffffd (-3)
ori $t0, 0xfffd
ori $t1, $0, 0x3 # B = 0x3
add $t2, $t0, $t1 # C = A + B = 0
sltiu $v0, $t2, 1 # D = 1 if C == 0
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : addi.asm
# Project : MIPS32 MUX
# Author : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'addi' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xffff # A = 0xfffffffd (-3)
ori $t0, 0xfffd
addi $t1, $t0, 5 # B = A + 5 = 2
addi $t2, $t1, 0xfffe # C = B + -2 = 0
sltiu $v0, $t2, 1 # D = 1 if C == 0
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : addiu.asm
# Project : MIPS32 MUX
# Author : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'addiu' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xffff # A = 0xfffffffd (-3)
ori $t0, 0xfffd
addiu $t1, $t0, 5 # B = A + 5 = 2
addiu $t2, $t1, 0xfffe # C = B + -2 = 0
sltiu $v0, $t2, 1 # D = 1 if C == 0
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : addu.asm
# Project : MIPS32 MUX
# Author : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'addu' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xffff # A = 0xfffffffd (-3)
ori $t0, 0xfffd
ori $t1, $0, 0x3 # B = 0x3
addu $t2, $t0, $t1 # C = A + B = 0
sltiu $v0, $t2, 1 # D = 1 if C == 0
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : and.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'and' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xdeaf # A = 0xdeafbeef
lui $t1, 0xaaaa # B = 0xaaaaaaaa
lui $t2, 0x5555 # C = 0x55555555
ori $t0, 0xbeef
ori $t1, 0xaaaa
ori $t2, 0x5555
and $t3, $t0, $t1 # D = A & B = 0x8aaaaaaa
and $t4, $t2, $t3 # E = B & D = 0
sltiu $v0, $t4, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : andi.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'andi' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
ori $t0, $0, 0xcafe # A = 0xcafe
andi $t1, $t0, 0xaaaa # B = A & 0xaaaa = 0x8aaa
andi $t2, $t1, 0x5555 # C = B & 0x5555 = 0
sltiu $v0, $t2, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : beq.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'beq' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
ori $t0, $0, 0xcafe
ori $t1, $0, 0xcafe
ori $v0, $0, 0 # The test result starts as a failure
beq $t0, $v0, $finish # No branch
nop
beq $t0, $t1, $target
nop
$finish:
sw $v0, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
j $finish # Early-by-1 branch detection
$target:
nop
ori $v0, $0, 1 # Set the result to pass
beq $0, $0, $finish # Late-by-1 branch detection (result not stored)
nop
j $finish
nop
#### Test code end ####
.end test
###############################################################################
# File : bgez.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'bgez' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xffff
bgez $t0, $finish # No branch
nop
bgez $s1, $target
nop
$finish:
sw $v0, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
j $finish # Early-by-1 branch detection
$target:
nop
ori $v0, $0, 1 # Set the result to pass
bgez $0, $finish # Late-by-1 branch detection (result not stored)
nop
j $finish # Broken branch recovery
nop
#### Test code end ####
.end test
###############################################################################
# File : bgtz.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'bgtz' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
ori $v0, $0, 0 # The test result starts as a failure
lui $t0, 0xffff
bgtz $t0, $finish # No branch
nop
bgtz $s1, $target
nop
$finish:
sw $v0, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
j $finish # Early-by-1 branch detection
$target:
nop
ori $v0, $0, 1 # Set the result to pass
bgtz $s1, $finish # Late-by-1 branch detection (result not stored)
nop
j $finish # Broken branch recovery
nop
#### Test code end ####
.end test
###############################################################################
# File : blez.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'blez' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
ori $v0, $0, 0 # The test result starts as a failure
blez $s1, $finish # No branch
lui $t0, 0xffff
blez $t0, $target
nop
$finish:
sw $v0, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
j $finish # Early-by-1 branch detection
$target:
nop
ori $v0, $0, 1 # Set the result to pass
blez $0, $finish # Late-by-1 branch detection (result not stored)
nop
j $finish
nop
#### Test code end ####
.end test
###############################################################################
# File : bltz.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'bltz' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
ori $v0, $0, 0 # The test result starts as a failure
bltz $0, $finish # No branch
nop
bltz $s1, $finish # No branch
lui $t0, 0xffff
bltz $t0, $target
nop
$finish:
sw $v0, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
j $finish # Early-by-1 branch detection
$target:
nop
ori $v0, $0, 1 # Set the result to pass
bltz $t0, $finish # Late-by-1 branch detection (result not stored)
nop
j $finish # Broken branch recovery
nop
#### Test code end ####
.end test
###############################################################################
# File : bne.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'bne' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
ori $t0, $0, 0xcafe
ori $t1, $0, 0xcafe
ori $v0, $0, 0 # The test result starts as a failure
bne $t0, $t1, $finish # No branch
nop
bne $t0, $v0, $target
nop
$finish:
sw $v0, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
j $finish # Early-by-1 branch detection
$target:
nop
ori $v0, $0, 1 # Set the result to pass
bne $t0, $0, $finish # Late-by-1 branch detection (result not stored)
nop
j $finish
nop
#### Test code end ####
.end test
###############################################################################
# File : clo.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'clo' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t2, 0xffff # 32
ori $t2, 0xffff
lui $t3, 0xffff # 18
ori $t3, 0xc000
lui $t4, 0xf800 # 5
lui $t5, 0xf000 # 4
lui $t6, 0x7fff # 0
ori $t7, $0, 0 # 0
clo $s2, $t2
clo $s3, $t3
clo $s4, $t4
clo $s5, $t5
clo $s6, $t6
clo $s7, $t7
addiu $s2, -32
addiu $s3, -18
addiu $s4, -5
addiu $s5, -4
addiu $s6, 0
addiu $s7, 0
or $v1, $s2, $s3
or $v1, $v1, $s4
or $v1, $v1, $s5
or $v1, $v1, $s6
or $v1, $v1, $s7
sltiu $v0, $v1, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : clz.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'clz' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t2, 0xffff # 0
ori $t2, 0xffff
ori $t3, $0, 0x0100 # 23
lui $t4, 0x0700 # 5
lui $t5, 0x0f00 # 4
lui $t6, 0x7fff # 1
ori $t7, $0, 0 # 32
clz $s2, $t2
clz $s3, $t3
clz $s4, $t4
clz $s5, $t5
clz $s6, $t6
clz $s7, $t7
addiu $s2, 0
addiu $s3, -23
addiu $s4, -5
addiu $s5, -4
addiu $s6, -1
addiu $s7, -32
or $v1, $s2, $s3
or $v1, $v1, $s4
or $v1, $v1, $s5
or $v1, $v1, $s6
or $v1, $v1, $s7
sltiu $v0, $v1, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : div.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'div' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0x1234
ori $t0, 0x5678
lui $t1, 0xc001
ori $t1, 0xcafe
div $t1, $t0 # 0xfffffffd (q), 0xf69ece66 (r)
mfhi $t2
mflo $t3
lui $t4, 0xf69e
ori $t4, 0xce66
lui $t5, 0xffff
ori $t5, 0xfffd
subu $t6, $t2, $t4
subu $t7, $t3, $t5
sltiu $v0, $t6, 1
sltiu $v1, $t7, 1
and $v0, $v0, $v1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : divu.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'divu' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0x1234
ori $t0, 0x5678
lui $t1, 0xc001
ori $t1, 0xcafe
divu $t1, $t0 # 0xa (q), 0x09f66a4e (r)
mfhi $t2
mflo $t3
lui $t4, 0x09f6
ori $t4, 0x6a4e
lui $t5, 0x0000
ori $t5, 0x000a
subu $t6, $t2, $t4
subu $t7, $t3, $t5
sltiu $v0, $t6, 1
sltiu $v1, $t7, 1
and $v0, $v0, $v1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : j.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'j' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
j $target
ori $v0, $0, 0 # The test result starts as a failure
$finish:
sw $v0, 8($s0)
sw $s1, 4($s0)
jr $ra
nop
j $finish # Early-by-1 detection
$target:
nop
ori $v0, $0, 1 # Set the result to pass
j $finish # Late-by 1 detection (result not written)
nop
#### Test code end ####
.end test
###############################################################################
# File : jal.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'jal' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
ori $v1, $ra, 0 # Save $ra
jal $target
ori $v0, $0, 0 # The test result starts as a failure
$finish:
sw $v0, 8($s0)
ori $ra, $v1, 0 # Restore $ra
sw $s1, 4($s0)
jr $ra
nop
j $finish # Early-by-1 detection
$target:
nop
ori $v0, $0, 1 # Set the result to pass
jr $ra
nop
#### Test code end ####
.end test
###############################################################################
# File : jalr.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'jalr' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
ori $v1, $ra, 0 # Save $ra
la $t0, $target
jalr $t0
ori $v0, $0, 0 # The test result starts as a failure
$finish:
sw $v0, 8($s0)
ori $ra, $v1, 0 # Restore $ra
sw $s1, 4($s0)
jr $ra
nop
j $finish # Early-by-1 detection
$target:
nop
ori $v0, $0, 1 # Set the result to pass
jr $ra
nop
#### Test code end ####
.end test
###############################################################################
# File : jr.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'jr' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
la $t0, $target
jr $t0
ori $v0, $0, 0 # The test result starts as a failure
$finish:
sw $v0, 8($s0)
sw $s1, 4($s0)
jr $ra
nop
j $finish # Early-by-1 detection
$target:
nop
ori $v0, $0, 1 # Set the result to pass
j $finish
nop
#### Test code end ####
.end test
###############################################################################
# File : lb.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'lb' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xbfc0 # Load address 0xbfc007fc (last word in 2KB starting
ori $t0, 0x07fc # from 0xbfc00000)
lui $t1, 0xc001
ori $t1, 0x7afe
sw $t1, 0($t0)
lb $t2, 0($t0)
lb $t3, 1($t0)
lb $t4, 2($t0)
lb $t5, 3($t0)
.ifdef big_endian
lui $t6, 0xffff
ori $t6, 0xffc0
lui $t7, 0x0000
ori $t7, 0x0001
lui $t8, 0x0000
ori $t8, 0x007a
lui $t9, 0xffff
ori $t9, 0xfffe
.else
lui $t6, 0xffff
ori $t6, 0xfffe
lui $t7, 0x0000
ori $t7, 0x007a
lui $t8, 0x0000
ori $t8, 0x0001
lui $t9, 0xffff
ori $t9, 0xffc0
.endif
subu $v1, $t2, $t6
sltiu $v0, $v1, 1
subu $v1, $t3, $t7
sltiu $v1, $v1, 1
and $v0, $v0, $v1
subu $v1, $t4, $t8
sltiu $v1, $v1, 1
and $v0, $v0, $v1
subu $v1, $t5, $t9
sltiu $v1, $v1, 1
and $v0, $v0, $v1
# Repeat with halves swapped (sign extension corner cases)
lui $t1, 0x7afe
ori $t1, 0xc001
sw $t1, 0($t0)
lb $t2, 0($t0)
lb $t3, 1($t0)
lb $t4, 2($t0)
lb $t5, 3($t0)
.ifdef big_endian
lui $t6, 0x0000
ori $t6, 0x007a
lui $t7, 0xffff
ori $t7, 0xfffe
lui $t8, 0xffff
ori $t8, 0xffc0
lui $t9, 0x0000
ori $t9, 0x0001
.else
lui $t6, 0x0000
ori $t6, 0x0001
lui $t7, 0xffff
ori $t7, 0xffc0
lui $t8, 0xffff
ori $t8, 0xfffe
lui $t9, 0x0000
ori $t9, 0x007a
.endif
subu $v1, $t2, $t6
sltiu $v1, $v1, 1
and $v0, $v0, $v1
subu $v1, $t3, $t7
sltiu $v1, $v1, 1
and $v0, $v0, $v1
subu $v1, $t4, $t8
sltiu $v1, $v1, 1
and $v0, $v0, $v1
subu $v1, $t5, $t9
sltiu $v1, $v1, 1
and $v0, $v0, $v1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : lbu.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'lbu' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xbfc0 # Load address 0xbfc007fc (last word in 2KB starting
ori $t0, 0x07fc # from 0xbfc00000)
lui $t1, 0xc001
ori $t1, 0x7afe
sw $t1, 0($t0)
lbu $t2, 0($t0)
lbu $t3, 1($t0)
lbu $t4, 2($t0)
lbu $t5, 3($t0)
.ifdef big_endian
ori $t6, $0, 0x00c0
ori $t7, $0, 0x0001
ori $t8, $0, 0x007a
ori $t9, $0, 0x00fe
.else
ori $t6, $0, 0x00fe
ori $t7, $0, 0x007a
ori $t8, $0, 0x0001
ori $t9, $0, 0x00c0
.endif
subu $v1, $t2, $t6
sltiu $v0, $v1, 1
subu $v1, $t3, $t7
sltiu $v1, $v1, 1
and $v0, $v0, $v1
subu $v1, $t4, $t8
sltiu $v1, $v1, 1
and $v0, $v0, $v1
subu $v1, $t5, $t9
sltiu $v1, $v1, 1
and $v0, $v0, $v1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : lh.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'lh' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xbfc0 # Load address 0xbfc007fc (last word in 2KB starting
ori $t0, 0x07fc # from 0xbfc00000)
lui $t1, 0x7001
ori $t1, 0xcafe
sw $t1, 0($t0)
lh $t2, 0($t0)
lh $t3, 2($t0)
.ifdef big_endian
lui $t4, 0x0000
ori $t4, 0x7001
lui $t5, 0xffff
ori $t5, 0xcafe
.else
lui $t4, 0xffff
ori $t4, 0xcafe
lui $t5, 0x0000
ori $t5, 0x7001
.endif
subu $v1, $t2, $t4
sltiu $v0, $v1, 1
subu $v1, $t3, $t5
sltiu $v1, $v1, 1
and $v0, $v0, $v1
# Repeat with halves swapped (sign extension corner cases)
lui $t1, 0xcafe
ori $t1, 0x7001
sw $t1, 0($t0)
lh $t2, 0($t0)
lh $t3, 2($t0)
.ifdef big_endian
lui $t4, 0xffff
ori $t4, 0xcafe
lui $t5, 0x0000
ori $t5, 0x7001
.else
lui $t4, 0x0000
ori $t4, 0x7001
lui $t5, 0xffff
ori $t5, 0xcafe
.endif
subu $v1, $t2, $t4
sltiu $v1, $v1, 1
and $v0, $v0, $v1
subu $v1, $t3, $t5
sltiu $v1, $v1, 1
and $v0, $v0, $v1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : lhu.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'lhu' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xbfc0 # Load address 0xbfc007fc (last word in 2KB starting
ori $t0, 0x07fc # from 0xbfc00000)
lui $t1, 0x7001
ori $t1, 0xcafe
sw $t1, 0($t0)
lhu $t2, 0($t0)
lhu $t3, 2($t0)
.ifdef big_endian
ori $t4, $0, 0x7001
ori $t5, $0, 0xcafe
.else
ori $t4, $0, 0xcafe
ori $t5, $0, 0x7001
.endif
subu $v1, $t2, $t4
sltiu $v0, $v1, 1
subu $v1, $t3, $t5
sltiu $v1, $v1, 1
and $v0, $v0, $v1
# Repeat with halves swapped (sign extension corner cases)
lui $t1, 0xcafe
ori $t1, 0x7001
sw $t1, 0($t0)
lhu $t2, 0($t0)
lhu $t3, 2($t0)
.ifdef big_endian
ori $t4, $0, 0xcafe
ori $t5, $0, 0x7001
.else
ori $t4, $0, 0x7001
ori $t5, $0, 0xcafe
.endif
subu $v1, $t2, $t4
sltiu $v1, $v1, 1
and $v0, $v0, $v1
subu $v1, $t3, $t5
sltiu $v1, $v1, 1
and $v0, $v0, $v1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : lui.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'lui' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
ori $v0, $0, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : lw.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'lw' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xbfc0 # Load a valid address (last word in 2KB starting
ori $t0, 0x07fc # from 0xbfc00000)
sw $0, 0($t0)
ori $t1, $0, 1
sw $t1, 0($t0)
lw $v0, 0($t0)
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : lwl.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'lwl' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xbfc0 # Load address 0xbfc007fc (last word in 2KB starting
ori $t0, 0x07fc # from 0xbfc00000)
lui $t1, 0xc001 # Memory word is 0xc001cafe
ori $t1, 0xcafe
sw $t1, 0($t0)
lui $t2, 0xdeaf # Register word is 0xdeafbeef
ori $t2, 0xbeef
or $t3, $0, $t2
or $t4, $0, $t2
or $t5, $0, $t2
or $t6, $0, $t2
lwl $t3, 0($t0)
lwl $t4, 1($t0)
lwl $t5, 2($t0)
lwl $t6, 3($t0)
.ifdef big_endian
lui $s3, 0xc001 # 0xc001cafe
ori $s3, 0xcafe
lui $s4, 0x01ca # 0x01cafeef
ori $s4, 0xfeef
lui $s5, 0xcafe # 0xcafebeef
ori $s5, 0xbeef
lui $s6, 0xfeaf # 0xfeafbeef
ori $s6, 0xbeef
.else
lui $s3, 0xfeaf # 0xfeafbeef
ori $s3, 0xbeef
lui $s4, 0xcafe # 0xcafebeef
ori $s4, 0xbeef
lui $s5, 0x01ca # 0x01cafeef
ori $s5, 0xfeef
lui $s6, 0xc001 # 0xc001cafe
ori $s6, 0xcafe
.endif
subu $s2, $t3, $s3
sltiu $v0, $s2, 1
subu $s2, $t4, $s4
sltiu $v1, $s2, 1
and $v0, $v0, $v1
subu $s2, $t5, $s5
sltiu $v1, $s2, 1
and $v0, $v0, $v1
subu $s2, $t6, $s6
sltiu $v1, $s2, 1
and $v0, $v0, $v1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : lwr.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'lwr' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xbfc0 # Load address 0xbfc007fc (last word in 2KB starting
ori $t0, 0x07fc # from 0xbfc00000)
lui $t1, 0xc001 # Memory word is 0xc001cafe
ori $t1, 0xcafe
sw $t1, 0($t0)
lui $t2, 0xdeaf # Register word is 0xdeafbeef
ori $t2, 0xbeef
or $t3, $0, $t2
or $t4, $0, $t2
or $t5, $0, $t2
or $t6, $0, $t2
lwr $t3, 0($t0)
lwr $t4, 1($t0)
lwr $t5, 2($t0)
lwr $t6, 3($t0)
.ifdef big_endian
lui $s3, 0xdeaf # 0xdeafbec0
ori $s3, 0xbec0
lui $s4, 0xdeaf # 0xdeafc001
ori $s4, 0xc001
lui $s5, 0xdec0 # 0xdec001ca
ori $s5, 0x01ca
lui $s6, 0xc001 # 0xc001cafe
ori $s6, 0xcafe
.else
lui $s3, 0xc001 # 0xc001cafe
ori $s3, 0xcafe
lui $s4, 0xdec0 # 0xdec001ca
ori $s4, 0x01ca
lui $s5, 0xdeaf # 0xdeafc001
ori $s5, 0xc001
lui $s6, 0xdeaf # 0xdeafbec0
ori $s6, 0xbec0
.endif
subu $s2, $t3, $s3
sltiu $v0, $s2, 1
subu $s2, $t4, $s4
sltiu $v1, $s2, 1
and $v0, $v0, $v1
subu $s2, $t5, $s5
sltiu $v1, $s2, 1
and $v0, $v0, $v1
subu $s2, $t6, $s6
sltiu $v1, $s2, 1
and $v0, $v0, $v1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : mfthi.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'mthi' and 'mfhi' instructions.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xdeaf
ori $t0, 0xbeef
mthi $t0
mfhi $t1
subu $v1, $t0, $t1
sltiu $v0, $v1, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : mftlo.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'mtlo' and 'mflo' instructions.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xdeaf
ori $t0, 0xbeef
mtlo $t0
mflo $t1
subu $v1, $t0, $t1
sltiu $v0, $v1, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : movn.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'movn' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xdeaf
ori $t0, $t0, 0xbeef
ori $t1, $0, 0
movn $t2, $t0, $s1 # $t2 gets 0xdeafbeef
movn $t1, $t0, $0 # $t1 remains 0
subu $t3, $t2, $t0
sltiu $v0, $t3, 1
sltiu $v1, $t1, 1
and $v0, $v0, $v1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : movz.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'movz' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xdeaf
ori $t0, $t0, 0xbeef
ori $t2, $0, 0
movz $t2, $t0, $s0 # $t2 remains 0
movz $t1, $t0, $0 # $t1 gets 0xdeafbeef
subu $t3, $t1, $t0
sltiu $v0, $t3, 1
sltiu $v1, $t2, 1
and $v0, $v0, $v1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : mul.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'mul' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0x1234
ori $t0, 0x5678
lui $t1, 0xc001
ori $t1, 0xcafe
mul $t2, $t0, $t1 # 0xb2a07b10
lui $t3, 0xb2a0
ori $t3, 0x7b10
subu $t4, $t2, $t3
sltiu $v0, $t4, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : mult.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'mult' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0x1234
ori $t0, 0x5678
lui $t1, 0xc001
ori $t1, 0xcafe
mult $t0, $t1 # 0xfb730b05b2a07b10
mfhi $t2
mflo $t3
lui $t4, 0xfb73
ori $t4, 0x0b05
lui $t5, 0xb2a0
ori $t5, 0x7b10
subu $t6, $t2, $t4
subu $t7, $t3, $t5
sltiu $v0, $t6, 1
sltiu $v1, $t7, 1
and $v0, $v0, $v1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : multu.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'multu' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0x1234
ori $t0, 0x5678
lui $t1, 0xc001
ori $t1, 0xcafe
multu $t0, $t1 # 0x0da7617db2a07b10
mfhi $t2
mflo $t3
lui $t4, 0x0da7
ori $t4, 0x617d
lui $t5, 0xb2a0
ori $t5, 0x7b10
subu $t6, $t2, $t4
subu $t7, $t3, $t5
sltiu $v0, $t6, 1
sltiu $v1, $t7, 1
and $v0, $v0, $v1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : nor.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'nor' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xdeaf # A = 0xdeafbeef
ori $t0, $t0, 0xbeef
lui $t1, 0x3141 # B = 0x31415926
ori $t1, $t1, 0x5926
lui $t2, 0xffff # C = 0xfffffffe
ori $t2, $t2, 0xfffe
nor $t3, $t0, $t1 # D = nor(A,B) = 0x00100010
nor $v0, $t2, $t3 # E = nor(C,D) = 0x1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
# load hash at 0x30001000
# 0x47173285 a8d7341e 5e972fc6 77286384 f802f8ef 42a5ec5f 03bbfa25 4cb01fad = "hello world"
test:
lui $s0, 0x3000
ori $s0, 0x1000
lui $t0, 0x4717
ori $t0, 0x3285
sw $t0, 0($s0)
lui $t0, 0xa8d7
ori $t0, 0x341e
sw $t0, 4($s0)
lui $t0, 0x5e97
ori $t0, 0x2fc6
sw $t0, 8($s0)
lui $t0, 0x7728
ori $t0, 0x6384
sw $t0, 0xc($s0)
lui $t0, 0xf802
ori $t0, 0xf8ef
sw $t0, 0x10($s0)
lui $t0, 0x42a5
ori $t0, 0xec5f
sw $t0, 0x14($s0)
lui $t0, 0x03bb
ori $t0, 0xfa25
sw $t0, 0x18($s0)
lui $t0, 0x4cb0
ori $t0, 0x1fad
sw $t0, 0x1c($s0)
# syscall 4020 to trigger
li $v0, 4020
syscall
# length at 0x31000000
lui $s1, 0x3100
lw $t0, 0($s1)
# should be len("hello world") == 11
li $t4, 11
subu $t5, $t0, $t4
sltiu $v0, $t5, 1
# data at 0x31000004
lw $t0, 4($s1)
lui $t4, 0x6865
ori $t4, 0x6c6c
subu $t5, $t0, $t4
sltiu $v1, $t5, 1
and $v0, $v0, $v1
# save results
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : ori.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'ori' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
ori $v0, $s1, 0
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : sb.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'sb' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xbfc0 # Load address 0xbfc007fc (last word in 2KB starting
ori $t0, 0x07fc # from 0xbfc00000)
sw $0, 0($t0)
ori $t1, $0, 0xc0
ori $t2, $0, 0x01
ori $t3, $0, 0xca
ori $t4, $0, 0xfe
sb $t1, 0($t0)
sb $t2, 1($t0)
sb $t3, 2($t0)
sb $t4, 3($t0)
lw $t5, 0($t0)
.ifdef big_endian
lui $t6, 0xc001
ori $t6, 0xcafe
.else
lui $t6, 0xfeca
ori $t6, 0x01c0
.endif
subu $t7, $t5, $t6
sltiu $v0, $t7, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : sh.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'sh' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xbfc0 # Load address 0xbfc007fc (last word in 2KB starting
ori $t0, 0x07fc # from 0xbfc00000)
sw $0, 0($t0)
ori $t1, $0, 0xc001
ori $t2, $0, 0xcafe
sh $t1, 0($t0)
sh $t2, 2($t0)
lw $t3, 0($t0)
.ifdef big_endian
lui $t4, 0xc001
ori $t4, 0xcafe
.else
lui $t4, 0xcafe
ori $t4, 0xc001
.endif
subu $t5, $t3, $t4
sltiu $v0, $t5, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : sll.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'sll' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xdeaf # A = 0xdeafbeef
ori $t0, 0xbeef
sll $t1, $t0, 4 # B = 0xdeafbeef << 4 = 0xeafbeef0
lui $t2, 0xeafb # C = 0xeafbeef0
ori $t2, 0xeef0
subu $t3, $t1, $t2
sltiu $v0, $t3, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : sllv.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'sllv' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xdeaf # A = 0xdeafbeef
ori $t0, 0xbeef
ori $t1, $0, 12
sllv $t2, $t0, $t1 # B = 0xdeafbeef << 12 = 0xfbeef000
lui $t3, 0xfbee
ori $t3, 0xf000
subu $t4, $t2, $t3
sltiu $v0, $t4, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : slt.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'slt' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xffff
ori $t0, 0xffff
slt $v0, $t0, $s1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : slti.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'slti' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0x8000
slti $v0, $t0, 0xffff
slti $v1, $t0, 0
and $v0, $v0, $v1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : sltiu.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'sltiu' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0x8000
sltiu $v0, $t0, 0xffff
sltiu $v1, $0, 0xffff
and $v0, $v0, $v1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : sltu.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'sltu' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xffff
ori $t0, 0xffff
sltu $v0, $s1, $t0
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : sra.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'sra' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xdeaf # A = 0xdeafbeef
ori $t0, 0xbeef
sra $t1, $t0, 4 # B = 0xdeafbeef >> 4 = 0xfdeafbee
lui $t2, 0xfdea # C = 0xfdeafbee
ori $t2, 0xfbee
subu $t3, $t1, $t2 # D = B - C = 0
sltiu $v0, $t3, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : srav.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'srav' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xdeaf # A = 0xdeafbeef
ori $t0, 0xbeef
ori $t1, $0, 12
srav $t2, $t0, $t1 # B = 0xdeafbeef >> 12 = 0xfffdeafb
lui $t3, 0xfffd
ori $t3, 0xeafb
subu $t4, $t2, $t3
sltiu $v0, $t4, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : srl.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'srl' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xdeaf # A = 0xdeafbeef
ori $t0, 0xbeef
srl $t1, $t0, 4 # B = 0xdeafbeef >> 4 = 0x0deafbee
lui $t2, 0x0dea
ori $t2, 0xfbee
subu $t3, $t1, $t2 # D = B - C = 0
sltiu $v0, $t3, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : srlv.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'srlv' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xdeaf # A = 0xdeafbeef
ori $t0, 0xbeef
ori $t1, $0, 12
srlv $t2, $t0, $t1 # B = 0xdeafbeef >> 12 = 0x000deafb
lui $t3, 0x000d
ori $t3, 0xeafb
subu $t4, $t2, $t3
sltiu $v0, $t4, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : sub.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'sub' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xffff # A = 0xfffffffd (-3)
ori $t0, 0xfffd
sub $t1, $t0, $t0 # B = A - A = 0
sub $t2, $t1, $t0 # C = B - A = 0 - A = 3
ori $t3, $0, 3 # D = 2
sub $t4, $t2, $t3 # E = C - D = C - 2 = 0
sltiu $v0, $t4, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : subu.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'subu' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xffff # A = 0xfffffffd (-3)
ori $t0, 0xfffd
ori $t1, $0, 4 # B = 4
subu $t2, $t0, $t1 # C = A - B = 0xfffffff9 (-7)
lui $t3, 0xffff # D = 0xfffffff8 (like -8 mod 2^32)
ori $t3, 0xfff8
subu $t4, $t2, $t3 # F = C - D = 1
subu $t5, $t4, $s1 # G = F - 1 = 0
sltiu $v0, $t5, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : swl.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'swl' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xbfc0 # Load address 0xbfc007ec (last four words in 2KB starting
ori $t0, 0x07ec # from 0xbfc00000)
lui $t1, 0xc001 # Memory word is 0xc001cafe
ori $t1, 0xcafe
sw $t1, 0($t0)
sw $t1, 4($t0)
sw $t1, 8($t0)
sw $t1, 12($t0)
lui $t2, 0xdeaf # Register word is 0xdeafbeef
ori $t2, 0xbeef
swl $t2, 0($t0)
swl $t2, 5($t0)
swl $t2, 10($t0)
swl $t2, 15($t0)
lw $s2, 0($t0)
lw $s3, 4($t0)
lw $s4, 8($t0)
lw $s5, 12($t0)
.ifdef big_endian
lui $t3, 0xdeaf # 0xdeafbeef
ori $t3, 0xbeef
lui $t4, 0xc0de # 0xc0deafbe
ori $t4, 0xafbe
lui $t5, 0xc001 # 0xc001deaf
ori $t5, 0xdeaf
lui $t6, 0xc001 # 0xc001cade
ori $t6, 0xcade
.else
lui $t3, 0xc001 # 0xc001cade
ori $t3, 0xcade
lui $t4, 0xc001 # 0xc001deaf
ori $t4, 0xdeaf
lui $t5, 0xc0de # 0xc0deafbe
ori $t5, 0xafbe
lui $t6, 0xdeaf # 0xdeafbeef
ori $t6, 0xbeef
.endif
subu $t7, $s2, $t3
sltiu $v0, $t7, 1
subu $t7, $s3, $t4
sltiu $v1, $t7, 1
and $v0, $v0, $v1
subu $t7, $s4, $t5
sltiu $v1, $t7, 1
and $v0, $v0, $v1
subu $t7, $s5, $t6
sltiu $v1, $t7, 1
and $v0, $v0, $v1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : swr.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'swr' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xbfc0 # Load address 0xbfc007ec (last four words in 2KB starting
ori $t0, 0x07ec # from 0xbfc00000)
lui $t1, 0xc001 # Memory words are 0xc001cafe
ori $t1, 0xcafe
sw $t1, 0($t0)
sw $t1, 4($t0)
sw $t1, 8($t0)
sw $t1, 12($t0)
lui $t2, 0xdeaf # Register word is 0xdeafbeef
ori $t2, 0xbeef
swr $t2, 0($t0)
swr $t2, 5($t0)
swr $t2, 10($t0)
swr $t2, 15($t0)
lw $s2, 0($t0)
lw $s3, 4($t0)
lw $s4, 8($t0)
lw $s5, 12($t0)
.ifdef big_endian
lui $t3, 0xef01 # 0xef01cafe
ori $t3, 0xcafe
lui $t4, 0xbeef # 0xbeefcafe
ori $t4, 0xcafe
lui $t5, 0xafbe # 0xafbeeffe
ori $t5, 0xeffe
lui $t6, 0xdeaf # 0xdeafbeef
ori $t6, 0xbeef
.else
lui $t3, 0xdeaf # 0xdeafbeef
ori $t3, 0xbeef
lui $t4, 0xafbe # 0xafbeeffe
ori $t4, 0xeffe
lui $t5, 0xbeef # 0xbeefcafe
ori $t5, 0xcafe
lui $t6, 0xef01 # 0xef01cafe
ori $t6, 0xcafe
.endif
subu $t7, $s2, $t3
sltiu $v0, $t7, 1
subu $t7, $s3, $t4
sltiu $v1, $t7, 1
and $v0, $v0, $v1
subu $t7, $s4, $t5
sltiu $v1, $t7, 1
and $v0, $v0, $v1
subu $t7, $s5, $t6
sltiu $v1, $t7, 1
and $v0, $v0, $v1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : xor.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'xor' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
lui $t0, 0xdeaf # A = 0xdeafbeef
ori $t0, 0xbeef
lui $t1, 0x3141 # B = 0x31415926
ori $t1, 0x5926
lui $t2, 0xefee # C = 0xefeee7c8
ori $t2, 0xe7c8
xor $t3, $t0, $t1 # D = xor(A,B) = 0xefeee7c8
xor $t4, $t2, $t3 # E = xor(C,D) = 0x1
xor $t5, $t4, $s1 # F = xor(E,1) = 0
sltiu $v0, $t5, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
###############################################################################
# File : xori.asm
# Project : MIPS32 MUX
# Author: : Grant Ayers (ayers@cs.stanford.edu)
#
# Standards/Formatting:
# MIPS gas, soft tab, 80 column
#
# Description:
# Test the functionality of the 'xori' instruction.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
#### Test code start ####
ori $t0, $0, 0xdeaf # A = 0xdeaf
xori $t1, $t0, 0x3141 # B = xor(A, 0x3141) = 0xefee
xori $t2, $t1, 0xefef # C = xor(B, 0xefef) = 0x1
xori $t3, $t2, 1 # D = xor(C, 1) = 0
sltiu $v0, $t3, 1
#### Test code end ####
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
package mipsevm
import (
"encoding/hex"
"fmt"
"github.com/ethereum/go-ethereum/crypto"
)
type Page [PageSize]byte
func (p *Page) MarshalText() ([]byte, error) {
dst := make([]byte, hex.EncodedLen(len(p)))
hex.Encode(dst, p[:])
return dst, nil
}
func (p *Page) UnmarshalText(dat []byte) error {
if len(dat) != PageSize*2 {
return fmt.Errorf("expected %d hex chars, but got %d", PageSize*2, len(dat))
}
_, err := hex.Decode(p[:], dat)
return err
}
type CachedPage struct {
Data *Page
// intermediate nodes only
Cache [PageSize / 32][32]byte
// true if the intermediate node is valid
Ok [PageSize / 32]bool
}
func (p *CachedPage) Invalidate(pageAddr uint32) {
if pageAddr >= PageSize {
panic("invalid page addr")
}
k := (1 << PageAddrSize) | pageAddr
// first cache layer caches nodes that has two 32 byte leaf nodes.
k >>= 5 + 1
for k > 0 {
p.Ok[k] = false
k >>= 1
}
}
func (p *CachedPage) InvalidateFull() {
p.Ok = [PageSize / 32]bool{} // reset everything to false
}
func (p *CachedPage) MerkleRoot() [32]byte {
// hash the bottom layer
for i := uint64(0); i < PageSize; i += 64 {
j := PageSize/32/2 + i/64
if p.Ok[j] {
continue
}
p.Cache[j] = crypto.Keccak256Hash(p.Data[i : i+64])
//fmt.Printf("0x%x 0x%x -> 0x%x\n", p.Data[i:i+32], p.Data[i+32:i+64], p.Cache[j])
p.Ok[j] = true
}
// hash the cache layers
for i := PageSize/32 - 2; i > 0; i -= 2 {
j := i >> 1
if p.Ok[j] {
continue
}
p.Cache[j] = HashPair(p.Cache[i], p.Cache[i+1])
p.Ok[j] = true
}
return p.Cache[1]
}
func (p *CachedPage) MerkleizeSubtree(gindex uint64) [32]byte {
_ = p.MerkleRoot() // fill cache
if gindex >= PageSize/32 {
if gindex >= PageSize/32*2 {
panic("gindex too deep")
}
// it's pointing to a bottom node
nodeIndex := gindex & (PageAddrMask >> 5)
return *(*[32]byte)(p.Data[nodeIndex*32 : nodeIndex*32+32])
}
return p.Cache[gindex]
}
package mipsevm
import (
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
func TestCachedPage(t *testing.T) {
p := &CachedPage{Data: new(Page)}
p.Data[42] = 0xab
gindex := ((uint64(1) << PageAddrSize) | 42) >> 5
node := common.Hash(p.MerkleizeSubtree(gindex))
expectedLeaf := common.Hash{10: 0xab}
require.Equal(t, expectedLeaf, node, "leaf nodes should not be hashed")
node = p.MerkleizeSubtree(gindex >> 1)
expectedParent := common.Hash(HashPair(zeroHashes[0], expectedLeaf))
require.Equal(t, expectedParent, node, "can get the parent node")
node = p.MerkleizeSubtree(gindex >> 2)
expectedParentParent := common.Hash(HashPair(expectedParent, zeroHashes[1]))
require.Equal(t, expectedParentParent, node, "and the parent of the parent")
pre := p.MerkleRoot()
p.Data[42] = 0xcd
post := p.MerkleRoot()
require.Equal(t, pre, post, "no change expected until cache is invalidated")
p.Invalidate(42)
post2 := p.MerkleRoot()
require.NotEqual(t, post, post2, "change after cache invalidation")
p.Data[2000] = 0xef
p.Invalidate(42)
post3 := p.MerkleRoot()
require.Equal(t, post2, post3, "local invalidation is not global invalidation")
p.Invalidate(2000)
post4 := p.MerkleRoot()
require.NotEqual(t, post3, post4, "can see the change now")
p.Data[1000] = 0xff
p.InvalidateFull()
post5 := p.MerkleRoot()
require.NotEqual(t, post4, post5, "and global invalidation works regardless of changed data")
}
package mipsevm
import (
"bytes"
"debug/elf"
"encoding/binary"
"fmt"
"io"
)
func LoadELF(f *elf.File) (*State, error) {
s := &State{
PC: uint32(f.Entry),
NextPC: uint32(f.Entry + 4),
HI: 0,
LO: 0,
Heap: 0x20000000,
Registers: [32]uint32{},
Memory: NewMemory(),
ExitCode: 0,
Exited: false,
Step: 0,
}
for i, prog := range f.Progs {
if prog.Type == 0x70000003 { // MIPS_ABIFLAGS
continue
}
r := io.Reader(io.NewSectionReader(prog, 0, int64(prog.Filesz)))
if prog.Filesz != prog.Memsz {
if prog.Type == elf.PT_LOAD {
if prog.Filesz < prog.Memsz {
r = io.MultiReader(r, bytes.NewReader(make([]byte, prog.Memsz-prog.Filesz)))
} else {
return nil, fmt.Errorf("invalid PT_LOAD program segment %d, file size (%d) > mem size (%d)", i, prog.Filesz, prog.Memsz)
}
} else {
return nil, fmt.Errorf("program segment %d has different file size (%d) than mem size (%d): filling for non PT_LOAD segments is not supported", i, prog.Filesz, prog.Memsz)
}
}
if prog.Vaddr+prog.Memsz >= uint64(1<<32) {
return nil, fmt.Errorf("program %d out of 32-bit mem range: %x - %x (size: %x)", i, prog.Vaddr, prog.Vaddr+prog.Memsz, prog.Memsz)
}
if err := s.Memory.SetMemoryRange(uint32(prog.Vaddr), r); err != nil {
return nil, fmt.Errorf("failed to read program segment %d: %w", i, err)
}
}
return s, nil
}
func PatchGo(f *elf.File, st *State) error {
symbols, err := f.Symbols()
if err != nil {
return fmt.Errorf("failed to read symbols data, cannot patch program: %w", err)
}
for _, s := range symbols {
// Disable Golang GC by patching the functions that enable the GC to a no-op function.
switch s.Name {
case "runtime.gcenable",
"runtime.init.5", // patch out: init() { go forcegchelper() }
"runtime.main.func1", // patch out: main.func() { newm(sysmon, ....) }
"runtime.deductSweepCredit", // uses floating point nums and interacts with gc we disabled
"runtime.(*gcControllerState).commit",
// these prometheus packages rely on concurrent background things. We cannot run those.
"github.com/prometheus/client_golang/prometheus.init",
"github.com/prometheus/client_golang/prometheus.init.0",
"github.com/prometheus/procfs.init",
"github.com/prometheus/common/model.init",
"github.com/prometheus/client_model/go.init",
"github.com/prometheus/client_model/go.init.0",
"github.com/prometheus/client_model/go.init.1",
// skip flag pkg init, we need to debug arg-processing more to see why this fails
"flag.init",
// We need to patch this out, we don't pass float64nan because we don't support floats
"runtime.check":
// MIPS32 patch: ret (pseudo instruction)
// 03e00008 = jr $ra = ret (pseudo instruction)
// 00000000 = nop (executes with delay-slot, but does nothing)
if err := st.Memory.SetMemoryRange(uint32(s.Value), bytes.NewReader([]byte{
0x03, 0xe0, 0x00, 0x08,
0, 0, 0, 0,
})); err != nil {
return fmt.Errorf("failed to patch Go runtime.gcenable: %w", err)
}
case "runtime.MemProfileRate":
if err := st.Memory.SetMemoryRange(uint32(s.Value), bytes.NewReader(make([]byte, 4))); err != nil { // disable mem profiling, to avoid a lot of unnecessary floating point ops
return err
}
}
}
return nil
}
func PatchStack(st *State) error {
// setup stack pointer
sp := uint32(0x7f_ff_d0_00)
// allocate 1 page for the initial stack data, and 16KB = 4 pages for the stack to grow
if err := st.Memory.SetMemoryRange(sp-4*PageSize, bytes.NewReader(make([]byte, 5*PageSize))); err != nil {
return fmt.Errorf("failed to allocate page for stack content")
}
st.Registers[29] = sp
storeMem := func(addr uint32, v uint32) {
var dat [4]byte
binary.BigEndian.PutUint32(dat[:], v)
_ = st.Memory.SetMemoryRange(addr, bytes.NewReader(dat[:]))
}
// init argc, argv, aux on stack
storeMem(sp+4*1, 0x42) // argc = 0 (argument count)
storeMem(sp+4*2, 0x35) // argv[n] = 0 (terminating argv)
storeMem(sp+4*3, 0) // envp[term] = 0 (no env vars)
storeMem(sp+4*4, 6) // auxv[0] = _AT_PAGESZ = 6 (key)
storeMem(sp+4*5, 4096) // auxv[1] = page size of 4 KiB (value) - (== minPhysPageSize)
storeMem(sp+4*6, 25) // auxv[2] = AT_RANDOM
storeMem(sp+4*7, sp+4*9) // auxv[3] = address of 16 bytes containing random value
storeMem(sp+4*8, 0) // auxv[term] = 0
_ = st.Memory.SetMemoryRange(sp+4*9, bytes.NewReader([]byte("4;byfairdiceroll"))) // 16 bytes of "randomness"
return nil
}
package mipsevm
import (
"encoding/binary"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
type State struct {
Memory *Memory `json:"memory"`
PreimageKey common.Hash `json:"preimageKey"`
PreimageOffset uint32 `json:"preimageOffset"` // note that the offset includes the 8-byte length prefix
PC uint32 `json:"pc"`
NextPC uint32 `json:"nextPC"`
LO uint32 `json:"lo"`
HI uint32 `json:"hi"`
Heap uint32 `json:"heap"` // to handle mmap growth
ExitCode uint8 `json:"exit"`
Exited bool `json:"exited"`
Step uint64 `json:"step"`
Registers [32]uint32 `json:"registers"`
// LastHint is optional metadata, and not part of the VM state itself.
// It is used to remember the last pre-image hint,
// so a VM can start from any state without fetching prior pre-images,
// and instead just repeat the last hint on setup,
// to make sure pre-image requests can be served.
// The first 4 bytes are a uin32 length prefix.
// Warning: the hint MAY NOT BE COMPLETE. I.e. this is buffered,
// and should only be read when len(LastHint) > 4 && uint32(LastHint[:4]) >= len(LastHint[4:])
LastHint hexutil.Bytes `json:"lastHint,omitempty"`
}
func (s *State) EncodeWitness() []byte {
out := make([]byte, 0)
memRoot := s.Memory.MerkleRoot()
out = append(out, memRoot[:]...)
out = append(out, s.PreimageKey[:]...)
out = binary.BigEndian.AppendUint32(out, s.PreimageOffset)
out = binary.BigEndian.AppendUint32(out, s.PC)
out = binary.BigEndian.AppendUint32(out, s.NextPC)
out = binary.BigEndian.AppendUint32(out, s.LO)
out = binary.BigEndian.AppendUint32(out, s.HI)
out = binary.BigEndian.AppendUint32(out, s.Heap)
out = append(out, s.ExitCode)
if s.Exited {
out = append(out, 1)
} else {
out = append(out, 0)
}
out = binary.BigEndian.AppendUint64(out, s.Step)
for _, r := range s.Registers {
out = binary.BigEndian.AppendUint32(out, r)
}
return out
}
package mipsevm
import (
"bytes"
"debug/elf"
"encoding/binary"
"encoding/hex"
"fmt"
"io"
"os"
"path"
"strings"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
)
// 0xbf_c0_00_00 ... baseAddrEnd is used in tests to write the results to
const baseAddrEnd = 0xbf_ff_ff_f0
// endAddr is used as return-address for tests
const endAddr = 0xa7ef00d0
func TestState(t *testing.T) {
testFiles, err := os.ReadDir("open_mips_tests/test/bin")
require.NoError(t, err)
for _, f := range testFiles {
t.Run(f.Name(), func(t *testing.T) {
if f.Name() == "oracle.bin" {
t.Skip("oracle test needs to be updated to use syscall pre-image oracle")
}
// TODO: currently tests are compiled as flat binary objects
// We can use more standard tooling to compile them to ELF files and get remove maketests.py
fn := path.Join("open_mips_tests/test/bin", f.Name())
//elfProgram, err := elf.Open()
//require.NoError(t, err, "must load test ELF binary")
//state, err := LoadELF(elfProgram)
//require.NoError(t, err, "must load ELF into state")
programMem, err := os.ReadFile(fn)
require.NoError(t, err)
state := &State{PC: 0, NextPC: 4, Memory: NewMemory()}
err = state.Memory.SetMemoryRange(0, bytes.NewReader(programMem))
require.NoError(t, err, "load program into state")
// set the return address ($ra) to jump into when test completes
state.Registers[31] = endAddr
us := NewInstrumentedState(state, nil, os.Stdout, os.Stderr)
for i := 0; i < 1000; i++ {
if us.state.PC == endAddr {
break
}
_, err := us.Step(false)
require.NoError(t, err)
}
require.Equal(t, uint32(endAddr), us.state.PC, "must reach end")
// inspect test result
done, result := state.Memory.GetMemory(baseAddrEnd+4), state.Memory.GetMemory(baseAddrEnd+8)
require.Equal(t, done, uint32(1), "must be done")
require.Equal(t, result, uint32(1), "must have success result")
})
}
}
func TestHello(t *testing.T) {
elfProgram, err := elf.Open("../example/bin/hello.elf")
require.NoError(t, err, "open ELF file")
state, err := LoadELF(elfProgram)
require.NoError(t, err, "load ELF into state")
err = PatchGo(elfProgram, state)
require.NoError(t, err, "apply Go runtime patches")
require.NoError(t, PatchStack(state), "add initial stack")
var stdOutBuf, stdErrBuf bytes.Buffer
us := NewInstrumentedState(state, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr))
for i := 0; i < 400_000; i++ {
if us.state.Exited {
break
}
_, err := us.Step(false)
require.NoError(t, err)
}
require.True(t, state.Exited, "must complete program")
require.Equal(t, uint8(0), state.ExitCode, "exit with 0")
require.Equal(t, "hello world!\n", stdOutBuf.String(), "stdout says hello")
require.Equal(t, "", stdErrBuf.String(), "stderr silent")
}
type testOracle struct {
hint func(v []byte)
getPreimage func(k [32]byte) []byte
}
func (t *testOracle) Hint(v []byte) {
t.hint(v)
}
func (t *testOracle) GetPreimage(k [32]byte) []byte {
return t.getPreimage(k)
}
var _ PreimageOracle = (*testOracle)(nil)
func claimTestOracle(t *testing.T) (po PreimageOracle, stdOut string, stdErr string) {
s := uint64(1000)
a := uint64(3)
b := uint64(4)
encodeU64 := func(x uint64) []byte {
return binary.BigEndian.AppendUint64(nil, x)
}
var diff []byte
diff = append(diff, crypto.Keccak256(encodeU64(a))...)
diff = append(diff, crypto.Keccak256(encodeU64(b))...)
preHash := crypto.Keccak256Hash(encodeU64(s))
diffHash := crypto.Keccak256Hash(diff)
images := make(map[[32]byte][]byte)
images[preimage.LocalIndexKey(0).PreimageKey()] = preHash[:]
images[preimage.LocalIndexKey(1).PreimageKey()] = diffHash[:]
images[preimage.LocalIndexKey(2).PreimageKey()] = encodeU64(s*a + b)
oracle := &testOracle{
hint: func(v []byte) {
parts := strings.Split(string(v), " ")
require.Len(t, parts, 2)
p, err := hex.DecodeString(parts[1])
require.NoError(t, err)
require.Len(t, p, 32)
h := common.Hash(*(*[32]byte)(p))
switch parts[0] {
case "fetch-state":
require.Equal(t, h, preHash, "expecting request for pre-state pre-image")
images[preimage.Keccak256Key(preHash).PreimageKey()] = encodeU64(s)
case "fetch-diff":
require.Equal(t, h, diffHash, "expecting request for diff pre-images")
images[preimage.Keccak256Key(diffHash).PreimageKey()] = diff
images[preimage.Keccak256Key(crypto.Keccak256Hash(encodeU64(a))).PreimageKey()] = encodeU64(a)
images[preimage.Keccak256Key(crypto.Keccak256Hash(encodeU64(b))).PreimageKey()] = encodeU64(b)
default:
t.Fatalf("unexpected hint: %q", parts[0])
}
},
getPreimage: func(k [32]byte) []byte {
p, ok := images[k]
if !ok {
t.Fatalf("missing pre-image %s", k)
}
return p
},
}
return oracle, fmt.Sprintf("computing %d * %d + %d\nclaim %d is good!\n", s, a, b, s*a+b), "started!"
}
func TestClaim(t *testing.T) {
elfProgram, err := elf.Open("../example/bin/claim.elf")
require.NoError(t, err, "open ELF file")
state, err := LoadELF(elfProgram)
require.NoError(t, err, "load ELF into state")
err = PatchGo(elfProgram, state)
require.NoError(t, err, "apply Go runtime patches")
require.NoError(t, PatchStack(state), "add initial stack")
oracle, expectedStdOut, expectedStdErr := claimTestOracle(t)
var stdOutBuf, stdErrBuf bytes.Buffer
us := NewInstrumentedState(state, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr))
for i := 0; i < 2000_000; i++ {
if us.state.Exited {
break
}
_, err := us.Step(false)
require.NoError(t, err)
}
require.True(t, state.Exited, "must complete program")
require.Equal(t, uint8(0), state.ExitCode, "exit with 0")
require.Equal(t, expectedStdOut, stdOutBuf.String(), "stdout")
require.Equal(t, expectedStdErr, stdErrBuf.String(), "stderr")
}
package mipsevm
import (
"encoding/binary"
"errors"
"fmt"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
)
type StepWitness struct {
// encoded state witness
State []byte
MemProof []byte
PreimageKey [32]byte // zeroed when no pre-image is accessed
PreimageValue []byte // including the 8-byte length prefix
PreimageOffset uint32
}
func uint32ToBytes32(v uint32) []byte {
var out [32]byte
binary.BigEndian.PutUint32(out[32-4:], v)
return out[:]
}
func (wit *StepWitness) EncodeStepInput() []byte {
var input []byte
input = append(input, StepBytes4...)
input = append(input, uint32ToBytes32(32*2)...) // state data offset in bytes
input = append(input, uint32ToBytes32(32*2+32+uint32(len(wit.State)))...) // proof data offset in bytes
input = append(input, uint32ToBytes32(uint32(len(wit.State)))...) // state data length in bytes
input = append(input, wit.State[:]...)
input = append(input, uint32ToBytes32(uint32(len(wit.MemProof)))...) // proof data length in bytes
input = append(input, wit.MemProof[:]...)
return input
}
func (wit *StepWitness) HasPreimage() bool {
return wit.PreimageKey != ([32]byte{})
}
func (wit *StepWitness) EncodePreimageOracleInput() ([]byte, error) {
if wit.PreimageKey == ([32]byte{}) {
return nil, errors.New("cannot encode pre-image oracle input, witness has no pre-image to proof")
}
switch preimage.KeyType(wit.PreimageKey[0]) {
case preimage.LocalKeyType:
// We have no on-chain form of preparing the bootstrap pre-images onchain yet.
// So instead we cheat them in.
// In production usage there should be an on-chain contract that exposes this,
// rather than going through the global keccak256 oracle.
var input []byte
input = append(input, CheatBytes4...)
input = append(input, uint32ToBytes32(wit.PreimageOffset)...)
input = append(input, wit.PreimageKey[:]...)
var tmp [32]byte
copy(tmp[:], wit.PreimageValue[wit.PreimageOffset:])
input = append(input, tmp[:]...)
input = append(input, uint32ToBytes32(uint32(len(wit.PreimageValue))-8)...)
// Note: we can pad calldata to 32 byte multiple, but don't strictly have to
return input, nil
case preimage.Keccak256KeyType:
var input []byte
input = append(input, LoadKeccak256PreimagePartBytes4...)
input = append(input, uint32ToBytes32(wit.PreimageOffset)...)
input = append(input, uint32ToBytes32(32+32)...) // partOffset, calldata offset
input = append(input, uint32ToBytes32(uint32(len(wit.PreimageValue))-8)...)
input = append(input, wit.PreimageValue[8:]...)
// Note: we can pad calldata to 32 byte multiple, but don't strictly have to
return input, nil
default:
return nil, fmt.Errorf("unsupported pre-image type %d, cannot prepare preimage with key %x offset %d for oracle",
wit.PreimageKey[0], wit.PreimageKey, wit.PreimageOffset)
}
}
......@@ -8,6 +8,7 @@ ignore:
- "op-bindings/bindings/*.go"
- "packages/contracts-bedrock/contracts/vendor/WETH9.sol"
- "packages/contracts-bedrock/contracts/echidna"
- "packages/contracts-bedrock/contracts/cannon" # tested through Go tests
coverage:
status:
patch:
......
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"]
......@@ -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
......
......@@ -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"
)
......
......@@ -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),
}
......
......@@ -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 (
......
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
)
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -26,10 +26,12 @@ 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
golang.org/x/term v0.6.0
......@@ -62,6 +64,7 @@ require (
github.com/docker/go-units v0.5.0 // indirect
github.com/edsrzf/mmap-go v1.1.0 // indirect
github.com/elastic/gosigar v0.14.2 // indirect
github.com/felixge/fgprof v0.9.3 // indirect
github.com/fjl/memsize v0.0.1 // indirect
github.com/flynn/noise v1.0.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
......@@ -131,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
......@@ -162,7 +164,6 @@ require (
go.uber.org/fx v1.19.1 // indirect
go.uber.org/multierr v1.9.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.6.0 // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.6.0 // indirect
......
......@@ -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=
......@@ -146,6 +146,8 @@ github.com/ethereum-optimism/op-geth v1.101106.0-rc.2 h1:F3SGS0XIvRQ0MjL3Rzbx3A6
github.com/ethereum-optimism/op-geth v1.101106.0-rc.2/go.mod h1:X9t7oeerFMU9/zMIjZKT/jbIca+O05QqtBTLjL+XVeA=
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ=
github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
......@@ -268,6 +270,7 @@ github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U=
github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
......@@ -310,6 +313,7 @@ github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFck
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k=
......@@ -557,6 +561,8 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK
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.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA=
github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo=
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.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
......@@ -675,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=
......
......@@ -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"
......
......@@ -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),
......
......@@ -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)",
......
......@@ -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,
......
......@@ -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),
}
}
......@@ -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
......
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),
}
}
......@@ -33,7 +33,9 @@ bindings: l1block-bindings \
legacy-erc20-eth-bindings \
dispute-game-factory-bindings \
standard-bridge-bindings \
cross-domain-messenger-bindings
cross-domain-messenger-bindings \
cannon-mips \
cannon-preimage-oracle
version:
forge --version
......@@ -134,11 +136,20 @@ standard-bridge-bindings: compile
cross-domain-messenger-bindings: compile
./gen_bindings.sh contracts/universal/CrossDomainMessenger.sol:CrossDomainMessenger $(pkg)
cannon-mips: compile
./gen_bindings.sh contracts/cannon/MIPS.sol:MIPS $(pkg)
cannon-preimage-oracle: compile
./gen_bindings.sh contracts/cannon/PreimageOracle.sol:PreimageOracle $(pkg)
more:
go run ./gen/main.go \
-artifacts ../packages/contracts-bedrock/artifacts \
-forge-artifacts ../packages/contracts-bedrock/forge-artifacts \
-out ./bindings \
-contracts SystemConfig,OptimismMintableERC20Factory,L2StandardBridge,L1BlockNumber,LegacyMessagePasser,DeployerWhitelist,Proxy,OptimismPortal,L2ToL1MessagePasser,L2CrossDomainMessenger,SequencerFeeVault,L1Block,LegacyERC20ETH,WETH9,GovernanceToken,L1CrossDomainMessenger,L2ERC721Bridge,OptimismMintableERC721Factory,ProxyAdmin \
-contracts SystemConfig,OptimismMintableERC20Factory,L2StandardBridge,L1BlockNumber,LegacyMessagePasser,DeployerWhitelist,Proxy,OptimismPortal,L2ToL1MessagePasser,L2CrossDomainMessenger,SequencerFeeVault,L1Block,LegacyERC20ETH,WETH9,GovernanceToken,L1CrossDomainMessenger,L2ERC721Bridge,OptimismMintableERC721Factory,ProxyAdmin,MIPS,PreimageOracle \
-source-maps MIPS,PreimageOracle \
-package bindings
mkdir:
......
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindings
import (
"errors"
"math/big"
"strings"
ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = errors.New
_ = big.NewInt
_ = strings.NewReader
_ = ethereum.NotFound
_ = bind.Bind
_ = common.Big1
_ = types.BloomLookup
_ = event.NewSubscription
)
// MIPSMetaData contains all meta data concerning the MIPS contract.
var MIPSMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[],\"name\":\"BRK_START\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"stateData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"}],\"name\":\"Step\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contractIPreimageOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
Bin: "0x608060405234801561001057600080fd5b50611b1c806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063155633fe146100465780637dc0d1d01461006757806398bb138314610098575b600080fd5b61004e61016c565b6040805163ffffffff9092168252519081900360200190f35b61006f610174565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61015a600480360360408110156100ae57600080fd5b8101906020810181356401000000008111156100c957600080fd5b8201836020820111156100db57600080fd5b803590602001918460018302840111640100000000831117156100fd57600080fd5b91939092909160208101903564010000000081111561011b57600080fd5b82018360208201111561012d57600080fd5b8035906020019184600183028401116401000000008311171561014f57600080fd5b509092509050610190565b60408051918252519081900360200190f35b634000000081565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b600061019a611a62565b608081146101a757600080fd5b604051610600146101b757600080fd5b606486146101c457600080fd5b61016684146101d257600080fd5b6101ef565b8035602084810360031b9190911c8352920192910190565b8560806101fe602082846101d7565b9150915061020e602082846101d7565b9150915061021e600482846101d7565b9150915061022e600482846101d7565b9150915061023e600482846101d7565b9150915061024e600482846101d7565b9150915061025e600482846101d7565b9150915061026e600482846101d7565b9150915061027e600182846101d7565b9150915061028e600182846101d7565b9150915061029e600882846101d7565b6020810190819052909250905060005b60208110156102d0576102c3600483856101d7565b90935091506001016102ae565b505050806101200151156102ee576102e6610710565b915050610708565b6101408101805160010167ffffffffffffffff1690526060810151600090610316908261081e565b9050603f601a82901c16600281148061033557508063ffffffff166003145b15610382576103788163ffffffff1660021461035257601f610355565b60005b60ff16600261036b856303ffffff16601a6108e6565b63ffffffff16901b610959565b9350505050610708565b6101608301516000908190601f601086901c81169190601587901c16602081106103a857fe5b602002015192508063ffffffff851615806103c957508463ffffffff16601c145b156103fa578661016001518263ffffffff16602081106103e557fe5b6020020151925050601f600b86901c166104b1565b60208563ffffffff16101561045d578463ffffffff16600c148061042457508463ffffffff16600d145b8061043557508463ffffffff16600e145b15610446578561ffff169250610458565b6104558661ffff1660106108e6565b92505b6104b1565b60288563ffffffff1610158061047957508463ffffffff166022145b8061048a57508463ffffffff166026145b156104b1578661016001518263ffffffff16602081106104a657fe5b602002015192508190505b60048563ffffffff16101580156104ce575060088563ffffffff16105b806104df57508463ffffffff166001145b156104fe576104f0858784876109c4565b975050505050505050610708565b63ffffffff60006020878316106105635761051e8861ffff1660106108e6565b9095019463fffffffc861661053481600161081e565b915060288863ffffffff161015801561055457508763ffffffff16603014155b1561056157809250600093505b505b600061057189888885610b4d565b63ffffffff9081169150603f8a16908916158015610596575060088163ffffffff1610155b80156105a85750601c8163ffffffff16105b15610687578063ffffffff16600814806105c857508063ffffffff166009145b156105ff576105ed8163ffffffff166008146105e457856105e7565b60005b89610959565b9b505050505050505050505050610708565b8063ffffffff16600a1415610620576105ed858963ffffffff8a1615611213565b8063ffffffff16600b1415610642576105ed858963ffffffff8a161515611213565b8063ffffffff16600c1415610659576105ed6112f8565b60108163ffffffff16101580156106765750601c8163ffffffff16105b15610687576105ed81898988611770565b8863ffffffff1660381480156106a2575063ffffffff861615155b156106d15760018b61016001518763ffffffff16602081106106c057fe5b63ffffffff90921660209290920201525b8363ffffffff1663ffffffff146106ee576106ee84600184611954565b6106fa85836001611213565b9b5050505050505050505050505b949350505050565b6000610728565b602083810382015183520192910190565b60806040518061073a60208285610717565b9150925061074a60208285610717565b9150925061075a60048285610717565b9150925061076a60048285610717565b9150925061077a60048285610717565b9150925061078a60048285610717565b9150925061079a60048285610717565b915092506107aa60048285610717565b915092506107ba60018285610717565b915092506107ca60018285610717565b915092506107da60088285610717565b60209091019350905060005b6020811015610808576107fb60048386610717565b90945091506001016107e6565b506000815281810382a081900390209150505b90565b60008061082a836119f0565b9050600384161561083a57600080fd5b602081019035610857565b60009081526020919091526040902090565b8460051c8160005b601b8110156108af5760208501943583821c60011680156108875760018114610898576108a5565b6108918285610845565b93506108a5565b6108a28483610845565b93505b505060010161085f565b5060805191508181146108ca57630badf00d60005260206000fd5b5050601f8516601c0360031b1c63ffffffff1691505092915050565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b0182610943576000610945565b815b90861663ffffffff16179250505092915050565b6000610963611a62565b5060e08051610100805163ffffffff90811690935284831690526080918516156109b357806008018261016001518663ffffffff16602081106109a257fe5b63ffffffff90921660209290920201525b6109bb610710565b95945050505050565b60006109ce611a62565b5060806000600463ffffffff881614806109ee57508663ffffffff166005145b15610a645760008261016001518663ffffffff1660208110610a0c57fe5b602002015190508063ffffffff168563ffffffff16148015610a3457508763ffffffff166004145b80610a5c57508063ffffffff168563ffffffff1614158015610a5c57508763ffffffff166005145b915050610ae1565b8663ffffffff1660061415610a825760008460030b13159050610ae1565b8663ffffffff1660071415610a9f5760008460030b139050610ae1565b8663ffffffff1660011415610ae157601f601087901c1680610ac55760008560030b1291505b8063ffffffff1660011415610adf5760008560030b121591505b505b606082018051608084015163ffffffff169091528115610b27576002610b0c8861ffff1660106108e6565b63ffffffff90811690911b8201600401166080840152610b39565b60808301805160040163ffffffff1690525b610b41610710565b98975050505050505050565b6000603f601a86901c81169086166020821015610f215760088263ffffffff1610158015610b815750600f8263ffffffff16105b15610c28578163ffffffff1660081415610b9d57506020610c23565b8163ffffffff1660091415610bb457506021610c23565b8163ffffffff16600a1415610bcb5750602a610c23565b8163ffffffff16600b1415610be25750602b610c23565b8163ffffffff16600c1415610bf957506024610c23565b8163ffffffff16600d1415610c1057506025610c23565b8163ffffffff16600e1415610c23575060265b600091505b63ffffffff8216610e7157601f600688901c16602063ffffffff83161015610d455760088263ffffffff1610610c6357869350505050610708565b63ffffffff8216610c835763ffffffff86811691161b9250610708915050565b8163ffffffff1660021415610ca75763ffffffff86811691161c9250610708915050565b8163ffffffff1660031415610cd2576103788163ffffffff168763ffffffff16901c826020036108e6565b8163ffffffff1660041415610cf6575050505063ffffffff8216601f84161b610708565b8163ffffffff1660061415610d1a575050505063ffffffff8216601f84161c610708565b8163ffffffff1660071415610d45576103788763ffffffff168763ffffffff16901c886020036108e6565b8163ffffffff1660201480610d6057508163ffffffff166021145b15610d72578587019350505050610708565b8163ffffffff1660221480610d8d57508163ffffffff166023145b15610d9f578587039350505050610708565b8163ffffffff1660241415610dbb578587169350505050610708565b8163ffffffff1660251415610dd7578587179350505050610708565b8163ffffffff1660261415610df3578587189350505050610708565b8163ffffffff1660271415610e0f575050505082821719610708565b8163ffffffff16602a1415610e42578560030b8760030b12610e32576000610e35565b60015b60ff169350505050610708565b8163ffffffff16602b1415610e6b578563ffffffff168763ffffffff1610610e32576000610e35565b50610f1c565b8163ffffffff16600f1415610e945760108563ffffffff16901b92505050610708565b8163ffffffff16601c1415610f1c578063ffffffff1660021415610ebd57505050828202610708565b8063ffffffff1660201480610ed857508063ffffffff166021145b15610f1c578063ffffffff1660201415610ef0579419945b60005b6380000000871615610f12576401fffffffe600197881b169601610ef3565b9250610708915050565b6111ac565b60288263ffffffff16101561108b578163ffffffff1660201415610f6e57610f658660031660080260180363ffffffff168563ffffffff16901c60ff1660086108e6565b92505050610708565b8163ffffffff1660211415610fa457610f658660021660080260100363ffffffff168563ffffffff16901c61ffff1660106108e6565b8163ffffffff1660221415610fd55750505063ffffffff60086003851602811681811b198416918316901b17610708565b8163ffffffff1660231415610fee578392505050610708565b8163ffffffff1660241415611022578560031660080260180363ffffffff168463ffffffff16901c60ff1692505050610708565b8163ffffffff1660251415611057578560021660080260100363ffffffff168463ffffffff16901c61ffff1692505050610708565b8163ffffffff1660261415610f1c5750505063ffffffff60086003851602601803811681811c198416918316901c17610708565b8163ffffffff16602814156110c35750505060ff63ffffffff60086003861602601803811682811b9091188316918416901b17610708565b8163ffffffff16602914156110fc5750505061ffff63ffffffff60086002861602601003811682811b9091188316918416901b17610708565b8163ffffffff16602a141561112d5750505063ffffffff60086003851602811681811c198316918416901c17610708565b8163ffffffff16602b1415611146578492505050610708565b8163ffffffff16602e141561117a5750505063ffffffff60086003851602601803811681811b198316918416901b17610708565b8163ffffffff1660301415611193578392505050610708565b8163ffffffff16603814156111ac578492505050610708565b604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e00000000000000000000000000604482015290519081900360640190fd5b600061121d611a62565b506080602063ffffffff86161061129557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c6964207265676973746572000000000000000000000000000000000000604482015290519081900360640190fd5b63ffffffff8516158015906112a75750825b156112d557838161016001518663ffffffff16602081106112c457fe5b63ffffffff90921660209290920201525b60808101805163ffffffff808216606085015260049091011690526109bb610710565b6000611302611a62565b506101e051604081015160808083015160a084015160c09094015191936000928392919063ffffffff8616610ffa141561137a5781610fff81161561134c57610fff811661100003015b63ffffffff84166113705760e08801805163ffffffff838201169091529550611374565b8395505b50611723565b8563ffffffff16610fcd14156113965763400000009450611723565b8563ffffffff1661101814156113af5760019450611723565b8563ffffffff1661109614156113e757600161012088015260ff83166101008801526113d9610710565b97505050505050505061081b565b8563ffffffff16610fa314156115a15763ffffffff83166114075761159c565b63ffffffff8316600514156115795760006114298363fffffffc16600161081e565b6000805460208b01516040808d015181517fe03110e1000000000000000000000000000000000000000000000000000000008152600481019390935263ffffffff16602483015280519495509293849373ffffffffffffffffffffffffffffffffffffffff9093169263e03110e19260448082019391829003018186803b1580156114b357600080fd5b505afa1580156114c7573d6000803e3d6000fd5b505050506040513d60408110156114dd57600080fd5b508051602090910151909250905060038516600481900382811015611500578092505b508185101561150d578491505b8260088302610100031c925082600882021b9250600180600883600403021b036001806008858560040301021b0391508119811690508381198616179450505061155f8563fffffffc16600185611954565b60408a018051820163ffffffff169052965061159c915050565b63ffffffff8316600314156115905780945061159c565b63ffffffff9450600993505b611723565b8563ffffffff16610fa414156116755763ffffffff8316600114806115cc575063ffffffff83166002145b806115dd575063ffffffff83166004145b156115ea5780945061159c565b63ffffffff83166006141561159057600061160c8363fffffffc16600161081e565b60208901519091506003841660040383811015611627578093505b83900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193850293841b0116911b1760208801526000604088015293508361159c565b8563ffffffff16610fd71415611723578163ffffffff16600314156117175763ffffffff831615806116ad575063ffffffff83166005145b806116be575063ffffffff83166003145b156116cc576000945061159c565b63ffffffff8316600114806116e7575063ffffffff83166002145b806116f8575063ffffffff83166006145b80611709575063ffffffff83166004145b15611590576001945061159c565b63ffffffff9450601693505b6101608701805163ffffffff808816604090920191909152905185821660e09091015260808801805180831660608b01526004019091169052611764610710565b97505050505050505090565b600061177a611a62565b5060806000601063ffffffff88161415611799575060c08101516118f1565b8663ffffffff16601114156117b95763ffffffff861660c08301526118f1565b8663ffffffff16601214156117d3575060a08101516118f1565b8663ffffffff16601314156117f35763ffffffff861660a08301526118f1565b8663ffffffff16601814156118285763ffffffff600387810b9087900b02602081901c821660c08501521660a08301526118f1565b8663ffffffff166019141561185a5763ffffffff86811681871602602081901c821660c08501521660a08301526118f1565b8663ffffffff16601a14156118a5578460030b8660030b8161187857fe5b0763ffffffff1660c0830152600385810b9087900b8161189457fe5b0563ffffffff1660a08301526118f1565b8663ffffffff16601b14156118f1578463ffffffff168663ffffffff16816118c957fe5b0663ffffffff90811660c0840152858116908716816118e457fe5b0463ffffffff1660a08301525b63ffffffff84161561192657808261016001518563ffffffff166020811061191557fe5b63ffffffff90921660209290920201525b60808201805163ffffffff80821660608601526004909101169052611949610710565b979650505050505050565b600061195f836119f0565b9050600384161561196f57600080fd5b6020810190601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b8110156119e55760208401933582821c60011680156119bd57600181146119ce576119db565b6119c78286610845565b94506119db565b6119d88583610845565b94505b5050600101611995565b505060805250505050565b60ff81166103800261016681019036906104e601811015611a5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611aed6023913960400191505060405180910390fd5b50919050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101611ac8611acd565b905290565b604051806104000160405280602090602082028036833750919291505056fe636865636b207468617420746865726520697320656e6f7567682063616c6c64617461a164736f6c6343000706000a",
}
// MIPSABI is the input ABI used to generate the binding from.
// Deprecated: Use MIPSMetaData.ABI instead.
var MIPSABI = MIPSMetaData.ABI
// MIPSBin is the compiled bytecode used for deploying new contracts.
// Deprecated: Use MIPSMetaData.Bin instead.
var MIPSBin = MIPSMetaData.Bin
// DeployMIPS deploys a new Ethereum contract, binding an instance of MIPS to it.
func DeployMIPS(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *MIPS, error) {
parsed, err := MIPSMetaData.GetAbi()
if err != nil {
return common.Address{}, nil, nil, err
}
if parsed == nil {
return common.Address{}, nil, nil, errors.New("GetABI returned nil")
}
address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(MIPSBin), backend)
if err != nil {
return common.Address{}, nil, nil, err
}
return address, tx, &MIPS{MIPSCaller: MIPSCaller{contract: contract}, MIPSTransactor: MIPSTransactor{contract: contract}, MIPSFilterer: MIPSFilterer{contract: contract}}, nil
}
// MIPS is an auto generated Go binding around an Ethereum contract.
type MIPS struct {
MIPSCaller // Read-only binding to the contract
MIPSTransactor // Write-only binding to the contract
MIPSFilterer // Log filterer for contract events
}
// MIPSCaller is an auto generated read-only Go binding around an Ethereum contract.
type MIPSCaller struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// MIPSTransactor is an auto generated write-only Go binding around an Ethereum contract.
type MIPSTransactor struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// MIPSFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
type MIPSFilterer struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// MIPSSession is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type MIPSSession struct {
Contract *MIPS // Generic contract binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// MIPSCallerSession is an auto generated read-only Go binding around an Ethereum contract,
// with pre-set call options.
type MIPSCallerSession struct {
Contract *MIPSCaller // Generic contract caller binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
}
// MIPSTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
// with pre-set transact options.
type MIPSTransactorSession struct {
Contract *MIPSTransactor // Generic contract transactor binding to set the session for
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// MIPSRaw is an auto generated low-level Go binding around an Ethereum contract.
type MIPSRaw struct {
Contract *MIPS // Generic contract binding to access the raw methods on
}
// MIPSCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
type MIPSCallerRaw struct {
Contract *MIPSCaller // Generic read-only contract binding to access the raw methods on
}
// MIPSTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
type MIPSTransactorRaw struct {
Contract *MIPSTransactor // Generic write-only contract binding to access the raw methods on
}
// NewMIPS creates a new instance of MIPS, bound to a specific deployed contract.
func NewMIPS(address common.Address, backend bind.ContractBackend) (*MIPS, error) {
contract, err := bindMIPS(address, backend, backend, backend)
if err != nil {
return nil, err
}
return &MIPS{MIPSCaller: MIPSCaller{contract: contract}, MIPSTransactor: MIPSTransactor{contract: contract}, MIPSFilterer: MIPSFilterer{contract: contract}}, nil
}
// NewMIPSCaller creates a new read-only instance of MIPS, bound to a specific deployed contract.
func NewMIPSCaller(address common.Address, caller bind.ContractCaller) (*MIPSCaller, error) {
contract, err := bindMIPS(address, caller, nil, nil)
if err != nil {
return nil, err
}
return &MIPSCaller{contract: contract}, nil
}
// NewMIPSTransactor creates a new write-only instance of MIPS, bound to a specific deployed contract.
func NewMIPSTransactor(address common.Address, transactor bind.ContractTransactor) (*MIPSTransactor, error) {
contract, err := bindMIPS(address, nil, transactor, nil)
if err != nil {
return nil, err
}
return &MIPSTransactor{contract: contract}, nil
}
// NewMIPSFilterer creates a new log filterer instance of MIPS, bound to a specific deployed contract.
func NewMIPSFilterer(address common.Address, filterer bind.ContractFilterer) (*MIPSFilterer, error) {
contract, err := bindMIPS(address, nil, nil, filterer)
if err != nil {
return nil, err
}
return &MIPSFilterer{contract: contract}, nil
}
// bindMIPS binds a generic wrapper to an already deployed contract.
func bindMIPS(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader(MIPSABI))
if err != nil {
return nil, err
}
return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_MIPS *MIPSRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _MIPS.Contract.MIPSCaller.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_MIPS *MIPSRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _MIPS.Contract.MIPSTransactor.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_MIPS *MIPSRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _MIPS.Contract.MIPSTransactor.contract.Transact(opts, method, params...)
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_MIPS *MIPSCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _MIPS.Contract.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_MIPS *MIPSTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _MIPS.Contract.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_MIPS *MIPSTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _MIPS.Contract.contract.Transact(opts, method, params...)
}
// BRKSTART is a free data retrieval call binding the contract method 0x155633fe.
//
// Solidity: function BRK_START() view returns(uint32)
func (_MIPS *MIPSCaller) BRKSTART(opts *bind.CallOpts) (uint32, error) {
var out []interface{}
err := _MIPS.contract.Call(opts, &out, "BRK_START")
if err != nil {
return *new(uint32), err
}
out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32)
return out0, err
}
// BRKSTART is a free data retrieval call binding the contract method 0x155633fe.
//
// Solidity: function BRK_START() view returns(uint32)
func (_MIPS *MIPSSession) BRKSTART() (uint32, error) {
return _MIPS.Contract.BRKSTART(&_MIPS.CallOpts)
}
// BRKSTART is a free data retrieval call binding the contract method 0x155633fe.
//
// Solidity: function BRK_START() view returns(uint32)
func (_MIPS *MIPSCallerSession) BRKSTART() (uint32, error) {
return _MIPS.Contract.BRKSTART(&_MIPS.CallOpts)
}
// Oracle is a free data retrieval call binding the contract method 0x7dc0d1d0.
//
// Solidity: function oracle() view returns(address)
func (_MIPS *MIPSCaller) Oracle(opts *bind.CallOpts) (common.Address, error) {
var out []interface{}
err := _MIPS.contract.Call(opts, &out, "oracle")
if err != nil {
return *new(common.Address), err
}
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
return out0, err
}
// Oracle is a free data retrieval call binding the contract method 0x7dc0d1d0.
//
// Solidity: function oracle() view returns(address)
func (_MIPS *MIPSSession) Oracle() (common.Address, error) {
return _MIPS.Contract.Oracle(&_MIPS.CallOpts)
}
// Oracle is a free data retrieval call binding the contract method 0x7dc0d1d0.
//
// Solidity: function oracle() view returns(address)
func (_MIPS *MIPSCallerSession) Oracle() (common.Address, error) {
return _MIPS.Contract.Oracle(&_MIPS.CallOpts)
}
// Step is a paid mutator transaction binding the contract method 0x98bb1383.
//
// Solidity: function Step(bytes stateData, bytes proof) returns(bytes32)
func (_MIPS *MIPSTransactor) Step(opts *bind.TransactOpts, stateData []byte, proof []byte) (*types.Transaction, error) {
return _MIPS.contract.Transact(opts, "Step", stateData, proof)
}
// Step is a paid mutator transaction binding the contract method 0x98bb1383.
//
// Solidity: function Step(bytes stateData, bytes proof) returns(bytes32)
func (_MIPS *MIPSSession) Step(stateData []byte, proof []byte) (*types.Transaction, error) {
return _MIPS.Contract.Step(&_MIPS.TransactOpts, stateData, proof)
}
// Step is a paid mutator transaction binding the contract method 0x98bb1383.
//
// Solidity: function Step(bytes stateData, bytes proof) returns(bytes32)
func (_MIPS *MIPSTransactorSession) Step(stateData []byte, proof []byte) (*types.Transaction, error) {
return _MIPS.Contract.Step(&_MIPS.TransactOpts, stateData, proof)
}
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindings
import (
"encoding/json"
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const MIPSStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"contracts/cannon/MIPS.sol:MIPS\",\"label\":\"oracle\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_contract(IPreimageOracle)1001\"}],\"types\":{\"t_contract(IPreimageOracle)1001\":{\"encoding\":\"inplace\",\"label\":\"contract IPreimageOracle\",\"numberOfBytes\":\"20\"}}}"
var MIPSStorageLayout = new(solc.StorageLayout)
var MIPSDeployedBin = "0x608060405234801561001057600080fd5b50600436106100415760003560e01c8063155633fe146100465780637dc0d1d01461006757806398bb138314610098575b600080fd5b61004e61016c565b6040805163ffffffff9092168252519081900360200190f35b61006f610174565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61015a600480360360408110156100ae57600080fd5b8101906020810181356401000000008111156100c957600080fd5b8201836020820111156100db57600080fd5b803590602001918460018302840111640100000000831117156100fd57600080fd5b91939092909160208101903564010000000081111561011b57600080fd5b82018360208201111561012d57600080fd5b8035906020019184600183028401116401000000008311171561014f57600080fd5b509092509050610190565b60408051918252519081900360200190f35b634000000081565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b600061019a611a62565b608081146101a757600080fd5b604051610600146101b757600080fd5b606486146101c457600080fd5b61016684146101d257600080fd5b6101ef565b8035602084810360031b9190911c8352920192910190565b8560806101fe602082846101d7565b9150915061020e602082846101d7565b9150915061021e600482846101d7565b9150915061022e600482846101d7565b9150915061023e600482846101d7565b9150915061024e600482846101d7565b9150915061025e600482846101d7565b9150915061026e600482846101d7565b9150915061027e600182846101d7565b9150915061028e600182846101d7565b9150915061029e600882846101d7565b6020810190819052909250905060005b60208110156102d0576102c3600483856101d7565b90935091506001016102ae565b505050806101200151156102ee576102e6610710565b915050610708565b6101408101805160010167ffffffffffffffff1690526060810151600090610316908261081e565b9050603f601a82901c16600281148061033557508063ffffffff166003145b15610382576103788163ffffffff1660021461035257601f610355565b60005b60ff16600261036b856303ffffff16601a6108e6565b63ffffffff16901b610959565b9350505050610708565b6101608301516000908190601f601086901c81169190601587901c16602081106103a857fe5b602002015192508063ffffffff851615806103c957508463ffffffff16601c145b156103fa578661016001518263ffffffff16602081106103e557fe5b6020020151925050601f600b86901c166104b1565b60208563ffffffff16101561045d578463ffffffff16600c148061042457508463ffffffff16600d145b8061043557508463ffffffff16600e145b15610446578561ffff169250610458565b6104558661ffff1660106108e6565b92505b6104b1565b60288563ffffffff1610158061047957508463ffffffff166022145b8061048a57508463ffffffff166026145b156104b1578661016001518263ffffffff16602081106104a657fe5b602002015192508190505b60048563ffffffff16101580156104ce575060088563ffffffff16105b806104df57508463ffffffff166001145b156104fe576104f0858784876109c4565b975050505050505050610708565b63ffffffff60006020878316106105635761051e8861ffff1660106108e6565b9095019463fffffffc861661053481600161081e565b915060288863ffffffff161015801561055457508763ffffffff16603014155b1561056157809250600093505b505b600061057189888885610b4d565b63ffffffff9081169150603f8a16908916158015610596575060088163ffffffff1610155b80156105a85750601c8163ffffffff16105b15610687578063ffffffff16600814806105c857508063ffffffff166009145b156105ff576105ed8163ffffffff166008146105e457856105e7565b60005b89610959565b9b505050505050505050505050610708565b8063ffffffff16600a1415610620576105ed858963ffffffff8a1615611213565b8063ffffffff16600b1415610642576105ed858963ffffffff8a161515611213565b8063ffffffff16600c1415610659576105ed6112f8565b60108163ffffffff16101580156106765750601c8163ffffffff16105b15610687576105ed81898988611770565b8863ffffffff1660381480156106a2575063ffffffff861615155b156106d15760018b61016001518763ffffffff16602081106106c057fe5b63ffffffff90921660209290920201525b8363ffffffff1663ffffffff146106ee576106ee84600184611954565b6106fa85836001611213565b9b5050505050505050505050505b949350505050565b6000610728565b602083810382015183520192910190565b60806040518061073a60208285610717565b9150925061074a60208285610717565b9150925061075a60048285610717565b9150925061076a60048285610717565b9150925061077a60048285610717565b9150925061078a60048285610717565b9150925061079a60048285610717565b915092506107aa60048285610717565b915092506107ba60018285610717565b915092506107ca60018285610717565b915092506107da60088285610717565b60209091019350905060005b6020811015610808576107fb60048386610717565b90945091506001016107e6565b506000815281810382a081900390209150505b90565b60008061082a836119f0565b9050600384161561083a57600080fd5b602081019035610857565b60009081526020919091526040902090565b8460051c8160005b601b8110156108af5760208501943583821c60011680156108875760018114610898576108a5565b6108918285610845565b93506108a5565b6108a28483610845565b93505b505060010161085f565b5060805191508181146108ca57630badf00d60005260206000fd5b5050601f8516601c0360031b1c63ffffffff1691505092915050565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b0182610943576000610945565b815b90861663ffffffff16179250505092915050565b6000610963611a62565b5060e08051610100805163ffffffff90811690935284831690526080918516156109b357806008018261016001518663ffffffff16602081106109a257fe5b63ffffffff90921660209290920201525b6109bb610710565b95945050505050565b60006109ce611a62565b5060806000600463ffffffff881614806109ee57508663ffffffff166005145b15610a645760008261016001518663ffffffff1660208110610a0c57fe5b602002015190508063ffffffff168563ffffffff16148015610a3457508763ffffffff166004145b80610a5c57508063ffffffff168563ffffffff1614158015610a5c57508763ffffffff166005145b915050610ae1565b8663ffffffff1660061415610a825760008460030b13159050610ae1565b8663ffffffff1660071415610a9f5760008460030b139050610ae1565b8663ffffffff1660011415610ae157601f601087901c1680610ac55760008560030b1291505b8063ffffffff1660011415610adf5760008560030b121591505b505b606082018051608084015163ffffffff169091528115610b27576002610b0c8861ffff1660106108e6565b63ffffffff90811690911b8201600401166080840152610b39565b60808301805160040163ffffffff1690525b610b41610710565b98975050505050505050565b6000603f601a86901c81169086166020821015610f215760088263ffffffff1610158015610b815750600f8263ffffffff16105b15610c28578163ffffffff1660081415610b9d57506020610c23565b8163ffffffff1660091415610bb457506021610c23565b8163ffffffff16600a1415610bcb5750602a610c23565b8163ffffffff16600b1415610be25750602b610c23565b8163ffffffff16600c1415610bf957506024610c23565b8163ffffffff16600d1415610c1057506025610c23565b8163ffffffff16600e1415610c23575060265b600091505b63ffffffff8216610e7157601f600688901c16602063ffffffff83161015610d455760088263ffffffff1610610c6357869350505050610708565b63ffffffff8216610c835763ffffffff86811691161b9250610708915050565b8163ffffffff1660021415610ca75763ffffffff86811691161c9250610708915050565b8163ffffffff1660031415610cd2576103788163ffffffff168763ffffffff16901c826020036108e6565b8163ffffffff1660041415610cf6575050505063ffffffff8216601f84161b610708565b8163ffffffff1660061415610d1a575050505063ffffffff8216601f84161c610708565b8163ffffffff1660071415610d45576103788763ffffffff168763ffffffff16901c886020036108e6565b8163ffffffff1660201480610d6057508163ffffffff166021145b15610d72578587019350505050610708565b8163ffffffff1660221480610d8d57508163ffffffff166023145b15610d9f578587039350505050610708565b8163ffffffff1660241415610dbb578587169350505050610708565b8163ffffffff1660251415610dd7578587179350505050610708565b8163ffffffff1660261415610df3578587189350505050610708565b8163ffffffff1660271415610e0f575050505082821719610708565b8163ffffffff16602a1415610e42578560030b8760030b12610e32576000610e35565b60015b60ff169350505050610708565b8163ffffffff16602b1415610e6b578563ffffffff168763ffffffff1610610e32576000610e35565b50610f1c565b8163ffffffff16600f1415610e945760108563ffffffff16901b92505050610708565b8163ffffffff16601c1415610f1c578063ffffffff1660021415610ebd57505050828202610708565b8063ffffffff1660201480610ed857508063ffffffff166021145b15610f1c578063ffffffff1660201415610ef0579419945b60005b6380000000871615610f12576401fffffffe600197881b169601610ef3565b9250610708915050565b6111ac565b60288263ffffffff16101561108b578163ffffffff1660201415610f6e57610f658660031660080260180363ffffffff168563ffffffff16901c60ff1660086108e6565b92505050610708565b8163ffffffff1660211415610fa457610f658660021660080260100363ffffffff168563ffffffff16901c61ffff1660106108e6565b8163ffffffff1660221415610fd55750505063ffffffff60086003851602811681811b198416918316901b17610708565b8163ffffffff1660231415610fee578392505050610708565b8163ffffffff1660241415611022578560031660080260180363ffffffff168463ffffffff16901c60ff1692505050610708565b8163ffffffff1660251415611057578560021660080260100363ffffffff168463ffffffff16901c61ffff1692505050610708565b8163ffffffff1660261415610f1c5750505063ffffffff60086003851602601803811681811c198416918316901c17610708565b8163ffffffff16602814156110c35750505060ff63ffffffff60086003861602601803811682811b9091188316918416901b17610708565b8163ffffffff16602914156110fc5750505061ffff63ffffffff60086002861602601003811682811b9091188316918416901b17610708565b8163ffffffff16602a141561112d5750505063ffffffff60086003851602811681811c198316918416901c17610708565b8163ffffffff16602b1415611146578492505050610708565b8163ffffffff16602e141561117a5750505063ffffffff60086003851602601803811681811b198316918416901b17610708565b8163ffffffff1660301415611193578392505050610708565b8163ffffffff16603814156111ac578492505050610708565b604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e00000000000000000000000000604482015290519081900360640190fd5b600061121d611a62565b506080602063ffffffff86161061129557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c6964207265676973746572000000000000000000000000000000000000604482015290519081900360640190fd5b63ffffffff8516158015906112a75750825b156112d557838161016001518663ffffffff16602081106112c457fe5b63ffffffff90921660209290920201525b60808101805163ffffffff808216606085015260049091011690526109bb610710565b6000611302611a62565b506101e051604081015160808083015160a084015160c09094015191936000928392919063ffffffff8616610ffa141561137a5781610fff81161561134c57610fff811661100003015b63ffffffff84166113705760e08801805163ffffffff838201169091529550611374565b8395505b50611723565b8563ffffffff16610fcd14156113965763400000009450611723565b8563ffffffff1661101814156113af5760019450611723565b8563ffffffff1661109614156113e757600161012088015260ff83166101008801526113d9610710565b97505050505050505061081b565b8563ffffffff16610fa314156115a15763ffffffff83166114075761159c565b63ffffffff8316600514156115795760006114298363fffffffc16600161081e565b6000805460208b01516040808d015181517fe03110e1000000000000000000000000000000000000000000000000000000008152600481019390935263ffffffff16602483015280519495509293849373ffffffffffffffffffffffffffffffffffffffff9093169263e03110e19260448082019391829003018186803b1580156114b357600080fd5b505afa1580156114c7573d6000803e3d6000fd5b505050506040513d60408110156114dd57600080fd5b508051602090910151909250905060038516600481900382811015611500578092505b508185101561150d578491505b8260088302610100031c925082600882021b9250600180600883600403021b036001806008858560040301021b0391508119811690508381198616179450505061155f8563fffffffc16600185611954565b60408a018051820163ffffffff169052965061159c915050565b63ffffffff8316600314156115905780945061159c565b63ffffffff9450600993505b611723565b8563ffffffff16610fa414156116755763ffffffff8316600114806115cc575063ffffffff83166002145b806115dd575063ffffffff83166004145b156115ea5780945061159c565b63ffffffff83166006141561159057600061160c8363fffffffc16600161081e565b60208901519091506003841660040383811015611627578093505b83900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193850293841b0116911b1760208801526000604088015293508361159c565b8563ffffffff16610fd71415611723578163ffffffff16600314156117175763ffffffff831615806116ad575063ffffffff83166005145b806116be575063ffffffff83166003145b156116cc576000945061159c565b63ffffffff8316600114806116e7575063ffffffff83166002145b806116f8575063ffffffff83166006145b80611709575063ffffffff83166004145b15611590576001945061159c565b63ffffffff9450601693505b6101608701805163ffffffff808816604090920191909152905185821660e09091015260808801805180831660608b01526004019091169052611764610710565b97505050505050505090565b600061177a611a62565b5060806000601063ffffffff88161415611799575060c08101516118f1565b8663ffffffff16601114156117b95763ffffffff861660c08301526118f1565b8663ffffffff16601214156117d3575060a08101516118f1565b8663ffffffff16601314156117f35763ffffffff861660a08301526118f1565b8663ffffffff16601814156118285763ffffffff600387810b9087900b02602081901c821660c08501521660a08301526118f1565b8663ffffffff166019141561185a5763ffffffff86811681871602602081901c821660c08501521660a08301526118f1565b8663ffffffff16601a14156118a5578460030b8660030b8161187857fe5b0763ffffffff1660c0830152600385810b9087900b8161189457fe5b0563ffffffff1660a08301526118f1565b8663ffffffff16601b14156118f1578463ffffffff168663ffffffff16816118c957fe5b0663ffffffff90811660c0840152858116908716816118e457fe5b0463ffffffff1660a08301525b63ffffffff84161561192657808261016001518563ffffffff166020811061191557fe5b63ffffffff90921660209290920201525b60808201805163ffffffff80821660608601526004909101169052611949610710565b979650505050505050565b600061195f836119f0565b9050600384161561196f57600080fd5b6020810190601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b8110156119e55760208401933582821c60011680156119bd57600181146119ce576119db565b6119c78286610845565b94506119db565b6119d88583610845565b94505b5050600101611995565b505060805250505050565b60ff81166103800261016681019036906104e601811015611a5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611aed6023913960400191505060405180910390fd5b50919050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101611ac8611acd565b905290565b604051806104000160405280602090602082028036833750919291505056fe636865636b207468617420746865726520697320656e6f7567682063616c6c64617461a164736f6c6343000706000a"
var MIPSDeployedSourceMap = "1025:22394:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1423:45;;;:::i;:::-;;;;;;;;;;;;;;;;;;;1791:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;14355:4789;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;14355:4789:0;;-1:-1:-1;14355:4789:0;-1:-1:-1;14355:4789:0;:::i;:::-;;;;;;;;;;;;;;;;1423:45;1458:10;1423:45;:::o;1791:29::-;;;;;;:::o;14355:4789::-;14433:7;14448:18;;:::i;:::-;14548:4;14541:5;14538:15;14528:2;;14609:1;14607;14600:11;14528:2;14645:4;14639:11;14652;14636:28;14626:2;;14710:1;14708;14701:11;14626:2;14758:3;14740:16;14737:25;14727:2;;14824:1;14822;14815:11;14727:2;14868:3;14854:12;14851:21;14841:2;;14933:1;14931;14924:11;14841:2;14950:370;;;15168:24;;15156:2;15152:13;;;15149:1;15145:21;15141:52;;;;15202:20;;15248:21;;;15294:18;;;15028:292::o;:::-;15336:16;15387:4;15420:18;15435:2;15432:1;15429;15420:18;:::i;:::-;15412:26;;;;15464:18;15479:2;15476:1;15473;15464:18;:::i;:::-;15456:26;;;;15512:17;15527:1;15524;15521;15512:17;:::i;:::-;15504:25;;;;15562:17;15577:1;15574;15571;15562:17;:::i;:::-;15554:25;;;;15600:17;15615:1;15612;15609;15600:17;:::i;:::-;15592:25;;;;15642:17;15657:1;15654;15651;15642:17;:::i;:::-;15634:25;;;;15680:17;15695:1;15692;15689;15680:17;:::i;:::-;15672:25;;;;15718:17;15733:1;15730;15727;15718:17;:::i;:::-;15710:25;;;;15758:17;15773:1;15770;15767;15758:17;:::i;:::-;15750:25;;;;15802:17;15817:1;15814;15811;15802:17;:::i;:::-;15794:25;;;;15844:17;15859:1;15856;15853;15844:17;:::i;:::-;15893:2;15886:10;;15876:21;;;;15836:25;;-1:-1:-1;15886:10:0;-1:-1:-1;15964:1:0;15949:77;15974:2;15971:1;15968:9;15949:77;;;16007:17;16022:1;16019;16016;16007:17;:::i;:::-;15999:25;;-1:-1:-1;15999:25:0;-1:-1:-1;15992:1:0;15985:9;15949:77;;;15953:14;;;16053:5;:12;;;16050:86;;;16116:13;:11;:13::i;:::-;16109:20;;;;;16050:86;16141:10;;;:15;;16155:1;16141:15;;;;;16210:8;;;;-1:-1:-1;;16202:20:0;;-1:-1:-1;16202:7:0;:20::i;:::-;16188:34;-1:-1:-1;16245:10:0;16253:2;16245:10;;;;16306:1;16296:11;;;:26;;;16311:6;:11;;16321:1;16311:11;16296:26;16292:308;;;16531:62;16542:6;:11;;16552:1;16542:11;:20;;16560:2;16542:20;;;16556:1;16542:20;16531:62;;16591:1;16564:23;16567:4;16572:10;16567:15;16584:2;16564;:23::i;:::-;:28;;;;16531:10;:62::i;:::-;16524:69;;;;;;;16292:308;16801:15;;;;16628:9;;;;16749:4;16743:2;16735:10;;;16734:19;;;16801:15;16826:2;16818:10;;;16817:19;16801:36;;;;;;;;;;;;-1:-1:-1;16858:5:0;16873:11;;;;;:29;;;16888:6;:14;;16898:4;16888:14;16873:29;16869:636;;;16945:5;:15;;;16961:5;16945:22;;;;;;;;;;;;;;-1:-1:-1;;16998:4:0;16992:2;16984:10;;;16983:19;16869:636;;;17028:4;17019:6;:13;;;17015:490;;;17119:6;:13;;17129:3;17119:13;:30;;;;17136:6;:13;;17146:3;17136:13;17119:30;:47;;;;17153:6;:13;;17163:3;17153:13;17119:47;17115:181;;;17205:4;17210:6;17205:11;17200:16;;17115:181;;;17268:19;17271:4;17276:6;17271:11;17284:2;17268;:19::i;:::-;17263:24;;17115:181;17015:490;;;17322:4;17312:6;:14;;;;:32;;;;17330:6;:14;;17340:4;17330:14;17312:32;:50;;;;17348:6;:14;;17358:4;17348:14;17312:50;17308:197;;;17412:5;:15;;;17428:5;17412:22;;;;;;;;;;;;;17407:27;;17493:5;17485:13;;17308:197;17526:1;17516:6;:11;;;;:25;;;;;17540:1;17531:6;:10;;;17516:25;17515:42;;;;17546:6;:11;;17556:1;17546:11;17515:42;17511:107;;;17574:37;17587:6;17595:4;17601:5;17608:2;17574:12;:37::i;:::-;17567:44;;;;;;;;;;;17511:107;17643:13;17624:16;17763:4;17753:14;;;;17749:328;;17812:19;17815:4;17820:6;17815:11;17828:2;17812;:19::i;:::-;17806:25;;;;17858:10;17853:15;;17882:16;17853:15;17896:1;17882:7;:16::i;:::-;17876:22;;17920:4;17910:6;:14;;;;:32;;;;;17928:6;:14;;17938:4;17928:14;;17910:32;17906:165;;;17983:4;17971:16;;18061:1;18053:9;;17906:165;17749:328;;18094:10;18107:26;18115:4;18121:2;18125;18129:3;18107:7;:26::i;:::-;18136:10;18107:39;;;;-1:-1:-1;18224:4:0;18217:11;;;18248;;;:24;;;;;18271:1;18263:4;:9;;;;18248:24;:39;;;;;18283:4;18276;:11;;;18248:39;18244:589;;;18301:4;:9;;18309:1;18301:9;:22;;;;18314:4;:9;;18322:1;18314:9;18301:22;18297:102;;;18353:37;18364:4;:9;;18372:1;18364:9;:21;;18380:5;18364:21;;;18376:1;18364:21;18387:2;18353:10;:37::i;:::-;18346:44;;;;;;;;;;;;;;;18297:102;18411:4;:11;;18419:3;18411:11;18407:79;;;18449:28;18458:5;18465:2;18469:7;;;;18449:8;:28::i;18407:79::-;18497:4;:11;;18505:3;18497:11;18493:79;;;18535:28;18544:5;18551:2;18555:7;;;;;18535:8;:28::i;18493:79::-;18622:4;:11;;18630:3;18622:11;18618:58;;;18652:15;:13;:15::i;18618:58::-;18749:4;18741;:12;;;;:27;;;;;18764:4;18757;:11;;;18741:27;18737:90;;;18787:31;18798:4;18804:2;18808;18812:5;18787:10;:31::i;18737:90::-;18877:6;:14;;18887:4;18877:14;:28;;;;-1:-1:-1;18895:10:0;;;;;18877:28;18873:75;;;18940:1;18915:5;:15;;;18931:5;18915:22;;;;;;;;;:26;;;;:22;;;;;;:26;18873:75;18978:9;:26;;18991:13;18978:26;18974:74;;19014:27;19023:9;19034:1;19037:3;19014:8;:27::i;:::-;19113:26;19122:5;19129:3;19134:4;19113:8;:26::i;:::-;19106:33;;;;;;;;;;;;;14355:4789;;;;;;;:::o;2085:1331::-;2126:11;2254:176;;;2346:2;2342:13;;;2332:24;;2326:31;2315:43;;2378:13;;2409;;;2305:125::o;:::-;2449:4;2488;2482:11;2526:5;2550:21;2568:2;2564;2558:4;2550:21;:::i;:::-;2538:33;;;;2601:21;2619:2;2615;2609:4;2601:21;:::i;:::-;2589:33;;;;2656:20;2674:1;2670:2;2664:4;2656:20;:::i;:::-;2644:32;;;;2713:20;2731:1;2727:2;2721:4;2713:20;:::i;:::-;2701:32;;;;2758:20;2776:1;2772:2;2766:4;2758:20;:::i;:::-;2746:32;;;;2807:20;2825:1;2821:2;2815:4;2807:20;:::i;:::-;2795:32;;;;2852:20;2870:1;2866:2;2860:4;2852:20;:::i;:::-;2840:32;;;;2897:20;2915:1;2911:2;2905:4;2897:20;:::i;:::-;2885:32;;;;2944:20;2962:1;2958:2;2952:4;2944:20;:::i;:::-;2932:32;;;;2995:20;3013:1;3009:2;3003:4;2995:20;:::i;:::-;2983:32;;;;3044:20;3062:1;3058:2;3052:4;3044:20;:::i;:::-;3097:2;3087:13;;;;-1:-1:-1;3032:32:0;-1:-1:-1;3145:1:0;3130:84;3155:2;3152:1;3149:9;3130:84;;;3192:20;3210:1;3206:2;3200:4;3192:20;:::i;:::-;3180:32;;-1:-1:-1;3180:32:0;-1:-1:-1;3173:1:0;3166:9;3130:84;;;3134:14;3245:1;3241:2;3234:13;3290:5;3286:2;3282:14;3275:5;3270:27;3375:14;;;3358:32;;;-1:-1:-1;;2085:1331:0;;:::o;11757:1270::-;11828:10;11846:14;11863:23;11875:10;11863:11;:23::i;:::-;11846:40;;11922:1;11916:4;11912:12;11909:2;;;11937:1;11934;11927:12;11909:2;12039;12027:15;;;11990:20;12049:169;;;;12088:12;;;12174:2;12167:13;;;;12207:2;12194:16;;;12078:140::o;:::-;12244:4;12241:1;12237:12;12268:4;12391:1;12376:273;12401:2;12398:1;12395:9;12376:273;;;12500:2;12488:15;;;12449:20;12523:12;;;12537:1;12519:20;12548:42;;;;12604:1;12599:42;;;;12512:129;;12548:42;12565:23;12580:7;12574:4;12565:23;:::i;:::-;12557:31;;12548:42;;12599;12616:23;12634:4;12625:7;12616:23;:::i;:::-;12608:31;;12512:129;-1:-1:-1;;12419:1:0;12412:9;12376:273;;;12380:14;12677:4;12671:11;12656:26;;12746:7;12740:4;12737:17;12727:2;;12803:10;12800:1;12793:21;12833:2;12830:1;12823:13;12727:2;-1:-1:-1;;12949:2:0;12939:13;;12927:10;12923:30;12920:1;12916:38;12972:16;12990:10;12968:33;;-1:-1:-1;;11757:1270:0;;;;:::o;1825:256::-;1884:6;1915:14;;;;1923:5;;;;1915:14;;;;;;1914:21;;;;;1927:1;1966:2;:6;;;1960:13;;;;;1959:19;;1958:28;;;;;;;2008:8;;2007:14;1914:21;2053;;2073:1;2053:21;;;2064:6;2053:21;2041:8;;;;;:34;;-1:-1:-1;;;1825:256:0;;;;:::o;10429:401::-;10496:7;10511:18;;:::i;:::-;-1:-1:-1;10592:8:0;;;10617:12;;;10606:23;;;;;;;10635:19;;;;;10561:4;;10664:12;;;10660:140;;10713:6;10720:1;10713:8;10686:5;:15;;;10702:7;10686:24;;;;;;;;;:35;;;;:24;;;;;;:35;10660:140;10812:13;:11;:13::i;:::-;10805:20;10429:401;-1:-1:-1;;;;;10429:401:0:o;8271:1063::-;8364:7;8379:18;;:::i;:::-;-1:-1:-1;8429:4:0;8444:17;8490:1;8480:11;;;;;:26;;;8495:6;:11;;8505:1;8495:11;8480:26;8476:514;;;8529:9;8541:5;:15;;;8557:5;8541:22;;;;;;;;;;;;;8529:34;;8593:2;8587:8;;:2;:8;;;:23;;;;;8599:6;:11;;8609:1;8599:11;8587:23;8586:54;;;;8622:2;8616:8;;:2;:8;;;;:23;;;;;8628:6;:11;;8638:1;8628:11;8616:23;8571:69;;8476:514;;;;8657:6;:11;;8667:1;8657:11;8653:337;;;8700:1;8693:2;8687:14;;;;8672:29;;8653:337;;;8726:6;:11;;8736:1;8726:11;8722:268;;;8768:1;8762:2;8756:13;;;8741:28;;8722:268;;;8794:6;:11;;8804:1;8794:11;8790:200;;;8860:4;8854:2;8846:10;;;8845:19;8877:8;8873:42;;8914:1;8908:2;8902:13;;;8887:28;;8873:42;8936:3;:8;;8943:1;8936:8;8932:43;;;8974:1;8967:2;8961:14;;;;8946:29;;8932:43;8790:200;;9012:8;;;;;9037:12;;;;9026:23;;;;;9087:216;;;;9163:1;9142:19;9145:4;9150:6;9145:11;9158:2;9142;:19::i;:::-;:22;;;;;;;9128:37;;9137:1;9128:37;9113:52;:12;;;:52;9087:216;;;9260:12;;;;;9275:1;9260:16;9245:31;;;;9087:216;9316:13;:11;:13::i;:::-;9309:20;8271:1063;-1:-1:-1;;;;;;;;8271:1063:0:o;19148:4269::-;19235:6;19265:10;19273:2;19265:10;;;;;;19308:11;;19404:4;19395:13;;19391:3986;;;19505:1;19495:6;:11;;;;:27;;;;;19519:3;19510:6;:12;;;19495:27;19491:462;;;19538:6;:11;;19548:1;19538:11;19534:383;;;-1:-1:-1;19560:4:0;19534:383;;;19600:6;:11;;19610:1;19600:11;19596:321;;;-1:-1:-1;19622:4:0;19596:321;;;19658:6;:13;;19668:3;19658:13;19654:263;;;-1:-1:-1;19682:4:0;19654:263;;;19715:6;:13;;19725:3;19715:13;19711:206;;;-1:-1:-1;19739:4:0;19711:206;;;19773:6;:13;;19783:3;19773:13;19769:148;;;-1:-1:-1;19797:4:0;19769:148;;;19830:6;:13;;19840:3;19830:13;19826:91;;;-1:-1:-1;19854:4:0;19826:91;;;19886:6;:13;;19896:3;19886:13;19882:35;;;-1:-1:-1;19910:4:0;19882:35;19943:1;19934:10;;19491:462;19994:11;;;19990:1701;;20046:4;20041:1;20033:9;;;20032:18;20071:4;20033:9;20064:11;;;20060:588;;;20101:4;20093;:12;;;20089:549;;20116:2;20109:9;;;;;;;20089:549;20196:12;;;20192:446;;20219:11;;;;;;;;-1:-1:-1;20212:18:0;;-1:-1:-1;;20212:18:0;20192:446;20265:4;:12;;20273:4;20265:12;20261:377;;;20288:11;;;;;;;;-1:-1:-1;20281:18:0;;-1:-1:-1;;20281:18:0;20261:377;20334:4;:12;;20342:4;20334:12;20330:308;;;20357:25;20366:5;20360:11;;:2;:11;;;;20376:5;20373:2;:8;20357:2;:25::i;20330:308::-;20417:4;:12;;20425:4;20417:12;20413:225;;;-1:-1:-1;;;;20440:15:0;;;20450:4;20447:7;;20440:15;20433:22;;20413:225;20494:4;:12;;20502:4;20494:12;20490:148;;;-1:-1:-1;;;;20517:15:0;;;20527:4;20524:7;;20517:15;20510:22;;20490:148;20571:4;:12;;20579:4;20571:12;20567:71;;;20594:19;20603:2;20597:8;;:2;:8;;;;20610:2;20607;:5;20594:2;:19::i;20567:71::-;20736:4;:12;;20744:4;20736:12;:28;;;;20752:4;:12;;20760:4;20752:12;20736:28;20732:602;;;20778:2;20775;:5;20768:12;;;;;;;20732:602;20818:4;:12;;20826:4;20818:12;:28;;;;20834:4;:12;;20842:4;20834:12;20818:28;20814:520;;;20860:2;20857;:5;20850:12;;;;;;;20814:520;20900:4;:12;;20908:4;20900:12;20896:438;;;20926:2;20923;:5;20916:12;;;;;;;20896:438;20967:4;:12;;20975:4;20967:12;20963:371;;;20994:2;20991;:5;20983:14;;;;;;;20963:371;21033:4;:12;;21041:4;21033:12;21029:305;;;21060:2;21057;:5;21049:14;;;;;;;21029:305;21100:4;:12;;21108:4;21100:12;21096:238;;;-1:-1:-1;;;;21125:5:0;;;21123:8;21116:15;;21096:238;21167:4;:12;;21175:4;21167:12;21163:171;;;21216:2;21200:19;;21206:2;21200:19;;;:27;;21226:1;21200:27;;;21222:1;21200:27;21193:34;;;;;;;;;21163:171;21255:4;:12;;21263:4;21255:12;21251:83;;;21291:2;21288:5;;:2;:5;;;:13;;21300:1;21288:13;;21251:83;19990:1701;;;;21352:6;:13;;21362:3;21352:13;21348:343;;;21380:2;21376;:6;;;;21369:13;;;;;;21348:343;21408:6;:14;;21418:4;21408:14;21404:287;;;21451:4;:9;;21459:1;21451:9;21447:49;;;-1:-1:-1;;;21476:19:0;;;21462:34;;21447:49;21517:4;:12;;21525:4;21517:12;:28;;;;21533:4;:12;;21541:4;21533:12;21517:28;21513:170;;;21570:4;:12;;21578:4;21570:12;21566:26;;;21589:3;;;21566:26;21604:8;21618:45;21628:10;21625:13;;:18;21618:45;;21652:8;21647:3;21652:8;;;;;21647:3;21618:45;;;21671:1;-1:-1:-1;21664:8:0;;-1:-1:-1;;21664:8:0;21513:170;19391:3986;;;21716:4;21707:6;:13;;;21703:1674;;;21734:6;:14;;21744:4;21734:14;21730:776;;;21774:36;21790:2;21793:1;21790:4;21796:1;21789:8;21786:2;:11;21778:20;;:3;:20;;;;21802:4;21777:29;21808:1;21774:2;:36::i;:::-;21767:43;;;;;;21730:776;21829:6;:14;;21839:4;21829:14;21825:681;;;21869:39;21885:2;21888:1;21885:4;21891:1;21884:8;21881:2;:11;21873:20;;:3;:20;;;;21897:6;21872:31;21905:2;21869;:39::i;21825:681::-;21927:6;:14;;21937:4;21927:14;21923:583;;;-1:-1:-1;;;21974:17:0;21989:1;21986;21983:4;;21982:8;21974:17;;22015:32;;;22070:5;22065:10;;21974:17;;;;;22064:18;22057:25;;21923:583;22101:6;:14;;22111:4;22101:14;22097:409;;;22126:3;22119:10;;;;;;22097:409;22156:6;:14;;22166:4;22156:14;22152:354;;;22210:2;22213:1;22210:4;22216:1;22209:8;22206:2;:11;22198:20;;:3;:20;;;;22222:4;22197:29;22190:36;;;;;;22152:354;22245:6;:14;;22255:4;22245:14;22241:265;;;22299:2;22302:1;22299:4;22305:1;22298:8;22295:2;:11;22287:20;;:3;:20;;;;22311:6;22286:31;22279:38;;;;;;22241:265;22336:6;:14;;22346:4;22336:14;22332:174;;;-1:-1:-1;;;22383:20:0;22401:1;22398;22395:4;;22394:8;22391:2;:11;22383:20;;22427:35;;;22485:5;22480:10;;22383:20;;;;;22479:18;22472:25;;21703:1674;22522:6;:14;;22532:4;22522:14;22518:859;;;-1:-1:-1;;;22569:4:0;22565:26;22589:1;22586;22583:4;;22582:8;22579:2;:11;22565:26;;22633:21;;;22613:42;;;22671:10;;22566:7;;;22565:26;;22670:18;22663:25;;22518:859;22705:6;:14;;22715:4;22705:14;22701:676;;;-1:-1:-1;;;22752:6:0;22748:28;22774:1;22771;22768:4;;22767:8;22764:2;:11;22748:28;;22818:23;;;22798:44;;;22858:10;;22749:9;;;22748:28;;22857:18;22850:25;;22701:676;22892:6;:14;;22902:4;22892:14;22888:489;;;-1:-1:-1;;;22937:16:0;22951:1;22948;22945:4;;22944:8;22937:16;;22975:32;;;23029:5;23023:11;;22937:16;;;;;23022:19;23015:26;;22888:489;23058:6;:14;;23068:4;23058:14;23054:323;;;23095:2;23088:9;;;;;;23054:323;23114:6;:14;;23124:4;23114:14;23110:267;;;-1:-1:-1;;;23159:19:0;23176:1;23173;23170:4;;23169:8;23166:2;:11;23159:19;;23200:35;;;23257:5;23251:11;;23159:19;;;;;23250;23243:26;;23110:267;23286:6;:14;;23296:4;23286:14;23282:95;;;23311:3;23304:10;;;;;;23282:95;23337:6;:14;;23347:4;23337:14;23333:44;;;23362:2;23355:9;;;;;;23333:44;23383:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10834:455;10917:7;10932:18;;:::i;:::-;-1:-1:-1;10982:4:0;11016:2;11005:13;;;;10997:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11115:13;;;;;;;:28;;;11132:11;11115:28;11111:80;;;11181:3;11153:5;:15;;;11169:8;11153:25;;;;;;;;;:31;;;;:25;;;;;;:31;11111:80;11208:12;;;;;11197:23;;;;:8;;;:23;11256:1;11241:16;;;11226:31;;;11271:13;:11;:13::i;3420:4847::-;3463:7;3478:18;;:::i;:::-;-1:-1:-1;3563:15:0;;:18;;;;3528:4;3638:18;;;;3674;;;;3710;;;;;3528:4;;3543:17;;;;3638:18;3674;3739;;;3753:4;3739:18;3735:4375;;;3793:2;3810:4;3807:7;;:12;3803:98;;3887:4;3884:7;;3876:4;:16;3870:22;3803:98;3912:7;;;3908:105;;3936:10;;;;;3956:16;;;;;;;;3936:10;-1:-1:-1;3908:105:0;;;4002:2;3997:7;;3908:105;3735:4375;;;;4029:10;:18;;4043:4;4029:18;4025:4085;;;1458:10;4070:14;;4025:4085;;;4101:10;:18;;4115:4;4101:18;4097:4013;;;4165:1;4160:6;;4097:4013;;;4183:10;:18;;4197:4;4183:18;4179:3931;;;4246:4;4231:12;;;:19;4258:26;;;:14;;;:26;4299:13;:11;:13::i;:::-;4292:20;;;;;;;;;;;4179:3931;4329:10;:18;;4343:4;4329:18;4325:3785;;;4458:14;;;4454:1768;;;;;4549:22;;;1679:1;4549:22;4545:1677;;;4670:10;4683:27;4691:2;4696:10;4691:15;4708:1;4683:7;:27::i;:::-;4761:11;4792:6;;4812:17;;;;4831:20;;;;;4792:60;;;;;;;;;;;;;;;;;;;;4670:40;;-1:-1:-1;4761:11:0;;;;4792:6;;;;;:19;;:60;;;;;;;;;;;:6;:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4792:60:0;;;;;;;;;-1:-1:-1;4792:60:0;-1:-1:-1;4965:1:0;4957:10;;5045:1;5041:17;;;5106;;;5103:2;;;5136:5;5126:15;;5103:2;;5205:6;5201:2;5198:14;5195:2;;;5225;5215:12;;5195:2;5317:3;5312:1;5304:6;5300:14;5295:3;5291:24;5287:34;5280:41;;5382:3;5378:1;5367:9;5363:17;5359:27;5352:34;;5492:1;5488;5484;5472:9;5469:1;5465:17;5461:25;5457:33;5453:41;5605:1;5601;5597;5588:6;5576:9;5573:1;5569:17;5565:30;5561:38;5557:46;5553:54;5535:72;;5691:10;5687:15;5681:4;5677:26;5669:34;;5793:3;5785:4;5781:9;5776:3;5772:19;5769:28;5762:35;;;;5873:33;5882:2;5887:10;5882:15;5899:1;5902:3;5873:8;:33::i;:::-;5916:20;;;:38;;;;;;;;;-1:-1:-1;4545:1677:0;;-1:-1:-1;;4545:1677:0;;6002:18;;;1602:1;6002:18;5998:224;;;6151:2;6146:7;;5998:224;;;6183:10;6178:15;;1750:3;6203:10;;5998:224;4325:3785;;;6238:10;:18;;6252:4;6238:18;6234:1876;;;6371:15;;;1533:1;6371:15;;:34;;-1:-1:-1;6390:15:0;;;1566:1;6390:15;6371:34;:57;;;-1:-1:-1;6409:19:0;;;1639:1;6409:19;6371:57;6367:1172;;;6445:2;6440:7;;6367:1172;;;6509:23;;;1720:1;6509:23;6505:1034;;;6564:10;6577:27;6585:2;6590:10;6585:15;6602:1;6577:7;:27::i;:::-;6668:17;;;;6564:40;;-1:-1:-1;6798:1:0;6790:10;;6878:1;6874:17;6939:13;;;6936:2;;;6961:5;6955:11;;6936:2;7205:14;;;7039:1;7201:22;;;7197:32;;;;7108:26;7132:1;7031:10;;;7112:18;;;7108:26;7193:43;7027:20;;7287:12;7337:17;;;:23;7393:1;7370:20;;;:24;7035:2;-1:-1:-1;7035:2:0;6505:1034;;6234:1876;7555:10;:18;;7569:4;7555:18;7551:559;;;7629:2;:7;;7635:1;7629:7;7625:479;;;7690:14;;;;;:40;;-1:-1:-1;7708:22:0;;;1679:1;7708:22;7690:40;:62;;;-1:-1:-1;7734:18:0;;;1602:1;7734:18;7690:62;7686:312;;;7771:1;7766:6;;7686:312;;;7805:15;;;1533:1;7805:15;;:34;;-1:-1:-1;7824:15:0;;;1566:1;7824:15;7805:34;:61;;;-1:-1:-1;7843:23:0;;;1720:1;7843:23;7805:61;:84;;;-1:-1:-1;7870:19:0;;;1639:1;7870:19;7805:84;7801:197;;;7908:1;7903:6;;7801:197;;7625:479;8027:10;8022:15;;1782:4;8047:11;;7625:479;8116:15;;;;;:23;;;;:18;;;;:23;;;;8145:15;;:23;;;:18;;;;:23;-1:-1:-1;8186:12:0;;;;8175:23;;;:8;;;:23;8234:1;8219:16;8204:31;;;;;8249:13;:11;:13::i;:::-;8242:20;;;;;;;;;3420:4847;:::o;9338:1087::-;9428:7;9443:18;;:::i;:::-;-1:-1:-1;9493:4:0;9508:10;9536:4;9528:12;;;;9524:732;;;-1:-1:-1;9548:8:0;;;;9524:732;;;9579:4;:12;;9587:4;9579:12;9575:681;;;9593:13;;;:8;;;:13;9575:681;;;9629:4;:12;;9637:4;9629:12;9625:631;;;-1:-1:-1;9649:8:0;;;;9625:631;;;9680:4;:12;;9688:4;9680:12;9676:580;;;9694:13;;;:8;;;:13;9676:580;;;9730:4;:12;;9738:4;9730:12;9726:530;;;9840:7;9797:16;9780;;;9797;;;;9780:33;9845:2;9840:7;;;;;9822:8;;;:26;9856:22;:8;;;:22;9726:530;;;9895:4;:12;;9903:4;9895:12;9891:365;;;9957:10;9946;;;9957;;;9946:21;9999:2;9994:7;;;;;9976:8;;;:26;10010:22;:8;;;:22;9891:365;;;10049:4;:12;;10057:4;10049:12;10045:211;;;10112:2;10096:19;;10102:2;10096:19;;;;;;;;10078:38;;:8;;;:38;10142:19;;;;;;;;;;;;;;10124:38;;:8;;;:38;10045:211;;;10179:4;:12;;10187:4;10179:12;10175:81;;;10223:2;10220:5;;:2;:5;;;;;;;;10209:16;;;;:8;;;:16;10244:5;;;;;;;;;;;;10233:16;;:8;;;:16;10175:81;10266:13;;;;10262:65;;10317:3;10289:5;:15;;;10305:8;10289:25;;;;;;;;;:31;;;;:25;;;;;;:31;10262:65;10344:12;;;;;10333:23;;;;:8;;;:23;10392:1;10377:16;;;10362:31;;;10407:13;:11;:13::i;:::-;10400:20;9338:1087;-1:-1:-1;;;;;;;9338:1087:0:o;13150:1145::-;13233:14;13250:23;13262:10;13250:11;:23::i;:::-;13233:40;;13309:1;13303:4;13299:12;13296:2;;;13324:1;13321;13314:12;13296:2;13432;13595:15;;;13450:2;13440:13;;13428:10;13424:30;13421:1;13417:38;13560:17;;;13377:20;;13545:10;13534:22;;;13530:27;13520:38;13517:61;13812:4;13809:1;13805:12;13959:1;13944:273;13969:2;13966:1;13963:9;13944:273;;;14068:2;14056:15;;;14017:20;14091:12;;;14105:1;14087:20;14116:42;;;;14172:1;14167:42;;;;14080:129;;14116:42;14133:23;14148:7;14142:4;14133:23;:::i;:::-;14125:31;;14116:42;;14167;14184:23;14202:4;14193:7;14184:23;:::i;:::-;14176:31;;14080:129;-1:-1:-1;;13987:1:0;13980:9;13944:273;;;-1:-1:-1;;14231:4:0;14224:18;-1:-1:-1;;;;13288:1003:0:o;11293:460::-;11568:19;;;11591:5;11568:29;11561:3;:37;;;11639:14;;11674;;11668:21;;;11660:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11735:13;11293:460;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o"
func init() {
if err := json.Unmarshal([]byte(MIPSStorageLayoutJSON), MIPSStorageLayout); err != nil {
panic(err)
}
layouts["MIPS"] = MIPSStorageLayout
deployedBytecodes["MIPS"] = MIPSDeployedBin
}
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindings
import (
"errors"
"math/big"
"strings"
ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = errors.New
_ = big.NewInt
_ = strings.NewReader
_ = ethereum.NotFound
_ = bind.Bind
_ = common.Big1
_ = types.BloomLookup
_ = event.NewSubscription
)
// PreimageOracleMetaData contains all meta data concerning the PreimageOracle contract.
var PreimageOracleMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"partOffset\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"key\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"part\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"size\",\"type\":\"uint256\"}],\"name\":\"cheat\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"partOffset\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"preimage\",\"type\":\"bytes\"}],\"name\":\"loadKeccak256PreimagePart\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"preimageLengths\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"preimagePartOk\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"preimageParts\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"key\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"}],\"name\":\"readPreimage\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"dat\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"datLen\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
Bin: "0x608060405234801561001057600080fd5b50610509806100206000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063e159261111610050578063e15926111461011b578063fe4ac08e14610130578063fef2b4ed146101a557600080fd5b806361238bde146100775780638542cf50146100b5578063e03110e1146100f3575b600080fd5b6100a26100853660046103b5565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6100e36100c33660046103b5565b600260209081526000928352604080842090915290825290205460ff1681565b60405190151581526020016100ac565b6101066101013660046103b5565b6101c5565b604080519283526020830191909152016100ac565b61012e6101293660046103d7565b6102b6565b005b61012e61013e366004610453565b6000838152600260209081526040808320878452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558684528252808320968352958152858220939093559283529082905291902055565b6100a26101b3366004610485565b60006020819052908152604090205481565b6000828152600260209081526040808320848452909152812054819060ff1661024e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f707265696d616765206d75737420657869737400000000000000000000000000604482015260640160405180910390fd5b506000838152602081815260409091205461026a8160086104cd565b6102758560206104cd565b1061029357836102868260086104cd565b61029091906104e5565b91505b506000938452600160209081526040808620948652939052919092205492909150565b6044356000806008830186106102cb57600080fd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b600080604083850312156103c857600080fd5b50508035926020909101359150565b6000806000604084860312156103ec57600080fd5b83359250602084013567ffffffffffffffff8082111561040b57600080fd5b818601915086601f83011261041f57600080fd5b81358181111561042e57600080fd5b87602082850101111561044057600080fd5b6020830194508093505050509250925092565b6000806000806080858703121561046957600080fd5b5050823594602084013594506040840135936060013592509050565b60006020828403121561049757600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156104e0576104e061049e565b500190565b6000828210156104f7576104f761049e565b50039056fea164736f6c634300080f000a",
}
// PreimageOracleABI is the input ABI used to generate the binding from.
// Deprecated: Use PreimageOracleMetaData.ABI instead.
var PreimageOracleABI = PreimageOracleMetaData.ABI
// PreimageOracleBin is the compiled bytecode used for deploying new contracts.
// Deprecated: Use PreimageOracleMetaData.Bin instead.
var PreimageOracleBin = PreimageOracleMetaData.Bin
// DeployPreimageOracle deploys a new Ethereum contract, binding an instance of PreimageOracle to it.
func DeployPreimageOracle(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *PreimageOracle, error) {
parsed, err := PreimageOracleMetaData.GetAbi()
if err != nil {
return common.Address{}, nil, nil, err
}
if parsed == nil {
return common.Address{}, nil, nil, errors.New("GetABI returned nil")
}
address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(PreimageOracleBin), backend)
if err != nil {
return common.Address{}, nil, nil, err
}
return address, tx, &PreimageOracle{PreimageOracleCaller: PreimageOracleCaller{contract: contract}, PreimageOracleTransactor: PreimageOracleTransactor{contract: contract}, PreimageOracleFilterer: PreimageOracleFilterer{contract: contract}}, nil
}
// PreimageOracle is an auto generated Go binding around an Ethereum contract.
type PreimageOracle struct {
PreimageOracleCaller // Read-only binding to the contract
PreimageOracleTransactor // Write-only binding to the contract
PreimageOracleFilterer // Log filterer for contract events
}
// PreimageOracleCaller is an auto generated read-only Go binding around an Ethereum contract.
type PreimageOracleCaller struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// PreimageOracleTransactor is an auto generated write-only Go binding around an Ethereum contract.
type PreimageOracleTransactor struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// PreimageOracleFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
type PreimageOracleFilterer struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// PreimageOracleSession is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type PreimageOracleSession struct {
Contract *PreimageOracle // Generic contract binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// PreimageOracleCallerSession is an auto generated read-only Go binding around an Ethereum contract,
// with pre-set call options.
type PreimageOracleCallerSession struct {
Contract *PreimageOracleCaller // Generic contract caller binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
}
// PreimageOracleTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
// with pre-set transact options.
type PreimageOracleTransactorSession struct {
Contract *PreimageOracleTransactor // Generic contract transactor binding to set the session for
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// PreimageOracleRaw is an auto generated low-level Go binding around an Ethereum contract.
type PreimageOracleRaw struct {
Contract *PreimageOracle // Generic contract binding to access the raw methods on
}
// PreimageOracleCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
type PreimageOracleCallerRaw struct {
Contract *PreimageOracleCaller // Generic read-only contract binding to access the raw methods on
}
// PreimageOracleTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
type PreimageOracleTransactorRaw struct {
Contract *PreimageOracleTransactor // Generic write-only contract binding to access the raw methods on
}
// NewPreimageOracle creates a new instance of PreimageOracle, bound to a specific deployed contract.
func NewPreimageOracle(address common.Address, backend bind.ContractBackend) (*PreimageOracle, error) {
contract, err := bindPreimageOracle(address, backend, backend, backend)
if err != nil {
return nil, err
}
return &PreimageOracle{PreimageOracleCaller: PreimageOracleCaller{contract: contract}, PreimageOracleTransactor: PreimageOracleTransactor{contract: contract}, PreimageOracleFilterer: PreimageOracleFilterer{contract: contract}}, nil
}
// NewPreimageOracleCaller creates a new read-only instance of PreimageOracle, bound to a specific deployed contract.
func NewPreimageOracleCaller(address common.Address, caller bind.ContractCaller) (*PreimageOracleCaller, error) {
contract, err := bindPreimageOracle(address, caller, nil, nil)
if err != nil {
return nil, err
}
return &PreimageOracleCaller{contract: contract}, nil
}
// NewPreimageOracleTransactor creates a new write-only instance of PreimageOracle, bound to a specific deployed contract.
func NewPreimageOracleTransactor(address common.Address, transactor bind.ContractTransactor) (*PreimageOracleTransactor, error) {
contract, err := bindPreimageOracle(address, nil, transactor, nil)
if err != nil {
return nil, err
}
return &PreimageOracleTransactor{contract: contract}, nil
}
// NewPreimageOracleFilterer creates a new log filterer instance of PreimageOracle, bound to a specific deployed contract.
func NewPreimageOracleFilterer(address common.Address, filterer bind.ContractFilterer) (*PreimageOracleFilterer, error) {
contract, err := bindPreimageOracle(address, nil, nil, filterer)
if err != nil {
return nil, err
}
return &PreimageOracleFilterer{contract: contract}, nil
}
// bindPreimageOracle binds a generic wrapper to an already deployed contract.
func bindPreimageOracle(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader(PreimageOracleABI))
if err != nil {
return nil, err
}
return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_PreimageOracle *PreimageOracleRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _PreimageOracle.Contract.PreimageOracleCaller.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_PreimageOracle *PreimageOracleRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _PreimageOracle.Contract.PreimageOracleTransactor.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_PreimageOracle *PreimageOracleRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _PreimageOracle.Contract.PreimageOracleTransactor.contract.Transact(opts, method, params...)
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_PreimageOracle *PreimageOracleCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _PreimageOracle.Contract.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_PreimageOracle *PreimageOracleTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _PreimageOracle.Contract.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_PreimageOracle *PreimageOracleTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _PreimageOracle.Contract.contract.Transact(opts, method, params...)
}
// PreimageLengths is a free data retrieval call binding the contract method 0xfef2b4ed.
//
// Solidity: function preimageLengths(bytes32 ) view returns(uint256)
func (_PreimageOracle *PreimageOracleCaller) PreimageLengths(opts *bind.CallOpts, arg0 [32]byte) (*big.Int, error) {
var out []interface{}
err := _PreimageOracle.contract.Call(opts, &out, "preimageLengths", arg0)
if err != nil {
return *new(*big.Int), err
}
out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
return out0, err
}
// PreimageLengths is a free data retrieval call binding the contract method 0xfef2b4ed.
//
// Solidity: function preimageLengths(bytes32 ) view returns(uint256)
func (_PreimageOracle *PreimageOracleSession) PreimageLengths(arg0 [32]byte) (*big.Int, error) {
return _PreimageOracle.Contract.PreimageLengths(&_PreimageOracle.CallOpts, arg0)
}
// PreimageLengths is a free data retrieval call binding the contract method 0xfef2b4ed.
//
// Solidity: function preimageLengths(bytes32 ) view returns(uint256)
func (_PreimageOracle *PreimageOracleCallerSession) PreimageLengths(arg0 [32]byte) (*big.Int, error) {
return _PreimageOracle.Contract.PreimageLengths(&_PreimageOracle.CallOpts, arg0)
}
// PreimagePartOk is a free data retrieval call binding the contract method 0x8542cf50.
//
// Solidity: function preimagePartOk(bytes32 , uint256 ) view returns(bool)
func (_PreimageOracle *PreimageOracleCaller) PreimagePartOk(opts *bind.CallOpts, arg0 [32]byte, arg1 *big.Int) (bool, error) {
var out []interface{}
err := _PreimageOracle.contract.Call(opts, &out, "preimagePartOk", arg0, arg1)
if err != nil {
return *new(bool), err
}
out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
return out0, err
}
// PreimagePartOk is a free data retrieval call binding the contract method 0x8542cf50.
//
// Solidity: function preimagePartOk(bytes32 , uint256 ) view returns(bool)
func (_PreimageOracle *PreimageOracleSession) PreimagePartOk(arg0 [32]byte, arg1 *big.Int) (bool, error) {
return _PreimageOracle.Contract.PreimagePartOk(&_PreimageOracle.CallOpts, arg0, arg1)
}
// PreimagePartOk is a free data retrieval call binding the contract method 0x8542cf50.
//
// Solidity: function preimagePartOk(bytes32 , uint256 ) view returns(bool)
func (_PreimageOracle *PreimageOracleCallerSession) PreimagePartOk(arg0 [32]byte, arg1 *big.Int) (bool, error) {
return _PreimageOracle.Contract.PreimagePartOk(&_PreimageOracle.CallOpts, arg0, arg1)
}
// PreimageParts is a free data retrieval call binding the contract method 0x61238bde.
//
// Solidity: function preimageParts(bytes32 , uint256 ) view returns(bytes32)
func (_PreimageOracle *PreimageOracleCaller) PreimageParts(opts *bind.CallOpts, arg0 [32]byte, arg1 *big.Int) ([32]byte, error) {
var out []interface{}
err := _PreimageOracle.contract.Call(opts, &out, "preimageParts", arg0, arg1)
if err != nil {
return *new([32]byte), err
}
out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte)
return out0, err
}
// PreimageParts is a free data retrieval call binding the contract method 0x61238bde.
//
// Solidity: function preimageParts(bytes32 , uint256 ) view returns(bytes32)
func (_PreimageOracle *PreimageOracleSession) PreimageParts(arg0 [32]byte, arg1 *big.Int) ([32]byte, error) {
return _PreimageOracle.Contract.PreimageParts(&_PreimageOracle.CallOpts, arg0, arg1)
}
// PreimageParts is a free data retrieval call binding the contract method 0x61238bde.
//
// Solidity: function preimageParts(bytes32 , uint256 ) view returns(bytes32)
func (_PreimageOracle *PreimageOracleCallerSession) PreimageParts(arg0 [32]byte, arg1 *big.Int) ([32]byte, error) {
return _PreimageOracle.Contract.PreimageParts(&_PreimageOracle.CallOpts, arg0, arg1)
}
// ReadPreimage is a free data retrieval call binding the contract method 0xe03110e1.
//
// Solidity: function readPreimage(bytes32 key, uint256 offset) view returns(bytes32 dat, uint256 datLen)
func (_PreimageOracle *PreimageOracleCaller) ReadPreimage(opts *bind.CallOpts, key [32]byte, offset *big.Int) (struct {
Dat [32]byte
DatLen *big.Int
}, error) {
var out []interface{}
err := _PreimageOracle.contract.Call(opts, &out, "readPreimage", key, offset)
outstruct := new(struct {
Dat [32]byte
DatLen *big.Int
})
if err != nil {
return *outstruct, err
}
outstruct.Dat = *abi.ConvertType(out[0], new([32]byte)).(*[32]byte)
outstruct.DatLen = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int)
return *outstruct, err
}
// ReadPreimage is a free data retrieval call binding the contract method 0xe03110e1.
//
// Solidity: function readPreimage(bytes32 key, uint256 offset) view returns(bytes32 dat, uint256 datLen)
func (_PreimageOracle *PreimageOracleSession) ReadPreimage(key [32]byte, offset *big.Int) (struct {
Dat [32]byte
DatLen *big.Int
}, error) {
return _PreimageOracle.Contract.ReadPreimage(&_PreimageOracle.CallOpts, key, offset)
}
// ReadPreimage is a free data retrieval call binding the contract method 0xe03110e1.
//
// Solidity: function readPreimage(bytes32 key, uint256 offset) view returns(bytes32 dat, uint256 datLen)
func (_PreimageOracle *PreimageOracleCallerSession) ReadPreimage(key [32]byte, offset *big.Int) (struct {
Dat [32]byte
DatLen *big.Int
}, error) {
return _PreimageOracle.Contract.ReadPreimage(&_PreimageOracle.CallOpts, key, offset)
}
// Cheat is a paid mutator transaction binding the contract method 0xfe4ac08e.
//
// Solidity: function cheat(uint256 partOffset, bytes32 key, bytes32 part, uint256 size) returns()
func (_PreimageOracle *PreimageOracleTransactor) Cheat(opts *bind.TransactOpts, partOffset *big.Int, key [32]byte, part [32]byte, size *big.Int) (*types.Transaction, error) {
return _PreimageOracle.contract.Transact(opts, "cheat", partOffset, key, part, size)
}
// Cheat is a paid mutator transaction binding the contract method 0xfe4ac08e.
//
// Solidity: function cheat(uint256 partOffset, bytes32 key, bytes32 part, uint256 size) returns()
func (_PreimageOracle *PreimageOracleSession) Cheat(partOffset *big.Int, key [32]byte, part [32]byte, size *big.Int) (*types.Transaction, error) {
return _PreimageOracle.Contract.Cheat(&_PreimageOracle.TransactOpts, partOffset, key, part, size)
}
// Cheat is a paid mutator transaction binding the contract method 0xfe4ac08e.
//
// Solidity: function cheat(uint256 partOffset, bytes32 key, bytes32 part, uint256 size) returns()
func (_PreimageOracle *PreimageOracleTransactorSession) Cheat(partOffset *big.Int, key [32]byte, part [32]byte, size *big.Int) (*types.Transaction, error) {
return _PreimageOracle.Contract.Cheat(&_PreimageOracle.TransactOpts, partOffset, key, part, size)
}
// LoadKeccak256PreimagePart is a paid mutator transaction binding the contract method 0xe1592611.
//
// Solidity: function loadKeccak256PreimagePart(uint256 partOffset, bytes preimage) returns()
func (_PreimageOracle *PreimageOracleTransactor) LoadKeccak256PreimagePart(opts *bind.TransactOpts, partOffset *big.Int, preimage []byte) (*types.Transaction, error) {
return _PreimageOracle.contract.Transact(opts, "loadKeccak256PreimagePart", partOffset, preimage)
}
// LoadKeccak256PreimagePart is a paid mutator transaction binding the contract method 0xe1592611.
//
// Solidity: function loadKeccak256PreimagePart(uint256 partOffset, bytes preimage) returns()
func (_PreimageOracle *PreimageOracleSession) LoadKeccak256PreimagePart(partOffset *big.Int, preimage []byte) (*types.Transaction, error) {
return _PreimageOracle.Contract.LoadKeccak256PreimagePart(&_PreimageOracle.TransactOpts, partOffset, preimage)
}
// LoadKeccak256PreimagePart is a paid mutator transaction binding the contract method 0xe1592611.
//
// Solidity: function loadKeccak256PreimagePart(uint256 partOffset, bytes preimage) returns()
func (_PreimageOracle *PreimageOracleTransactorSession) LoadKeccak256PreimagePart(partOffset *big.Int, preimage []byte) (*types.Transaction, error) {
return _PreimageOracle.Contract.LoadKeccak256PreimagePart(&_PreimageOracle.TransactOpts, partOffset, preimage)
}
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindings
import (
"encoding/json"
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const PreimageOracleStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"contracts/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"preimageLengths\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_bytes32,t_uint256)\"},{\"astId\":1001,\"contract\":\"contracts/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"preimageParts\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes32))\"},{\"astId\":1002,\"contract\":\"contracts/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"preimagePartOk\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_mapping(t_bytes32,t_mapping(t_uint256,t_bool))\"}],\"types\":{\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_mapping(t_uint256,t_bool))\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e mapping(uint256 =\u003e bool))\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_mapping(t_uint256,t_bool)\"},\"t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes32))\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e mapping(uint256 =\u003e bytes32))\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_mapping(t_uint256,t_bytes32)\"},\"t_mapping(t_bytes32,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_uint256\"},\"t_mapping(t_uint256,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_bool\"},\"t_mapping(t_uint256,t_bytes32)\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e bytes32)\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_bytes32\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
var PreimageOracleStorageLayout = new(solc.StorageLayout)
var PreimageOracleDeployedBin = "0x608060405234801561001057600080fd5b50600436106100725760003560e01c8063e159261111610050578063e15926111461011b578063fe4ac08e14610130578063fef2b4ed146101a557600080fd5b806361238bde146100775780638542cf50146100b5578063e03110e1146100f3575b600080fd5b6100a26100853660046103b5565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6100e36100c33660046103b5565b600260209081526000928352604080842090915290825290205460ff1681565b60405190151581526020016100ac565b6101066101013660046103b5565b6101c5565b604080519283526020830191909152016100ac565b61012e6101293660046103d7565b6102b6565b005b61012e61013e366004610453565b6000838152600260209081526040808320878452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558684528252808320968352958152858220939093559283529082905291902055565b6100a26101b3366004610485565b60006020819052908152604090205481565b6000828152600260209081526040808320848452909152812054819060ff1661024e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f707265696d616765206d75737420657869737400000000000000000000000000604482015260640160405180910390fd5b506000838152602081815260409091205461026a8160086104cd565b6102758560206104cd565b1061029357836102868260086104cd565b61029091906104e5565b91505b506000938452600160209081526040808620948652939052919092205492909150565b6044356000806008830186106102cb57600080fd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b600080604083850312156103c857600080fd5b50508035926020909101359150565b6000806000604084860312156103ec57600080fd5b83359250602084013567ffffffffffffffff8082111561040b57600080fd5b818601915086601f83011261041f57600080fd5b81358181111561042e57600080fd5b87602082850101111561044057600080fd5b6020830194508093505050509250925092565b6000806000806080858703121561046957600080fd5b5050823594602084013594506040840135936060013592509050565b60006020828403121561049757600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156104e0576104e061049e565b500190565b6000828210156104f7576104f761049e565b50039056fea164736f6c634300080f000a"
var PreimageOracleDeployedSourceMap = "57:2945:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;143:68;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;413:25:1;;;401:2;386:18;143:68:0;;;;;;;;217:66;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;614:14:1;;607:22;589:41;;577:2;562:18;217:66:0;449:187:1;290:454:0;;;;;;:::i;:::-;;:::i;:::-;;;;815:25:1;;;871:2;856:18;;849:34;;;;788:18;290:454:0;641:248:1;1537:1463:0;;;;;;:::i;:::-;;:::i;:::-;;1086:262;;;;;;:::i;:::-;1219:19;;;;:14;:19;;;;;;;;:31;;;;;;;;:38;;;;1253:4;1219:38;;;;;;1267:18;;;;;;;;:30;;;;;;;;;:37;;;;1314:20;;;;;;;;;;:27;1086:262;87:50;;;;;;:::i;:::-;;;;;;;;;;;;;;;290:454;388:11;439:19;;;:14;:19;;;;;;;;:27;;;;;;;;;388:11;;439:27;;431:59;;;;;;;2517:2:1;431:59:0;;;2499:21:1;2556:2;2536:18;;;2529:30;2595:21;2575:18;;;2568:49;2634:18;;431:59:0;;;;;;;;-1:-1:-1;521:14:0;538:20;;;509:2;538:20;;;;;;;;631:10;538:20;640:1;631:10;:::i;:::-;616:11;:6;625:2;616:11;:::i;:::-;:25;612:84;;679:6;666:10;:6;675:1;666:10;:::i;:::-;:19;;;;:::i;:::-;657:28;;612:84;-1:-1:-1;711:18:0;;;;:13;:18;;;;;;;;:26;;;;;;;;;;;;290:454;;-1:-1:-1;290:454:0:o;1537:1463::-;1831:4;1818:18;1636:12;;1966:1;1956:12;;1941:28;;1931:84;;1999:1;1996;1989:12;1931:84;2258:3;2254:14;;;2158:4;2242:27;2289:11;2263:4;2408:15;2289:11;2390:40;2620:28;;;2624:11;2620:28;2614:35;2671:20;;;;2818:19;2811:27;2840:11;2808:44;2871:19;;;;2849:1;2871:19;;;;;;;;:31;;;;;;;;:38;;;;2905:4;2871:38;;;;;;2919:18;;;;;;;;:30;;;;;;;;;:37;;;;2966:20;;;;;;;;;;;:27;;;;-1:-1:-1;;;;1537:1463:0:o;14:248:1:-;82:6;90;143:2;131:9;122:7;118:23;114:32;111:52;;;159:1;156;149:12;111:52;-1:-1:-1;;182:23:1;;;252:2;237:18;;;224:32;;-1:-1:-1;14:248:1:o;894:659::-;973:6;981;989;1042:2;1030:9;1021:7;1017:23;1013:32;1010:52;;;1058:1;1055;1048:12;1010:52;1094:9;1081:23;1071:33;;1155:2;1144:9;1140:18;1127:32;1178:18;1219:2;1211:6;1208:14;1205:34;;;1235:1;1232;1225:12;1205:34;1273:6;1262:9;1258:22;1248:32;;1318:7;1311:4;1307:2;1303:13;1299:27;1289:55;;1340:1;1337;1330:12;1289:55;1380:2;1367:16;1406:2;1398:6;1395:14;1392:34;;;1422:1;1419;1412:12;1392:34;1467:7;1462:2;1453:6;1449:2;1445:15;1441:24;1438:37;1435:57;;;1488:1;1485;1478:12;1435:57;1519:2;1515;1511:11;1501:21;;1541:6;1531:16;;;;;894:659;;;;;:::o;1558:385::-;1644:6;1652;1660;1668;1721:3;1709:9;1700:7;1696:23;1692:33;1689:53;;;1738:1;1735;1728:12;1689:53;-1:-1:-1;;1761:23:1;;;1831:2;1816:18;;1803:32;;-1:-1:-1;1882:2:1;1867:18;;1854:32;;1933:2;1918:18;1905:32;;-1:-1:-1;1558:385:1;-1:-1:-1;1558:385:1:o;1948:180::-;2007:6;2060:2;2048:9;2039:7;2035:23;2031:32;2028:52;;;2076:1;2073;2066:12;2028:52;-1:-1:-1;2099:23:1;;1948:180;-1:-1:-1;1948:180:1:o;2663:184::-;2715:77;2712:1;2705:88;2812:4;2809:1;2802:15;2836:4;2833:1;2826:15;2852:128;2892:3;2923:1;2919:6;2916:1;2913:13;2910:39;;;2929:18;;:::i;:::-;-1:-1:-1;2965:9:1;;2852:128::o;2985:125::-;3025:4;3053:1;3050;3047:8;3044:34;;;3058:18;;:::i;:::-;-1:-1:-1;3095:9:1;;2985:125::o"
func init() {
if err := json.Unmarshal([]byte(PreimageOracleStorageLayoutJSON), PreimageOracleStorageLayout); err != nil {
panic(err)
}
layouts["PreimageOracle"] = PreimageOracleStorageLayout
deployedBytecodes["PreimageOracle"] = PreimageOracleDeployedBin
}
......@@ -2,9 +2,11 @@ package main
import (
"encoding/json"
"errors"
"flag"
"log"
"os"
"path"
"path/filepath"
"strings"
"text/template"
......@@ -14,29 +16,45 @@ import (
)
type flags struct {
ArtifactsDir string
Contracts string
OutDir string
Package string
ArtifactsDir string
ForgeArtifacts string
Contracts string
SourceMaps string
OutDir string
Package string
}
type data struct {
Name string
StorageLayout string
DeployedBin string
Package string
Name string
StorageLayout string
DeployedBin string
Package string
DeployedSourceMap string
}
type forgeArtifact struct {
DeployedBytecode struct {
SourceMap string `json:"sourceMap"`
} `json:"deployedBytecode"`
}
func main() {
var f flags
flag.StringVar(&f.ArtifactsDir, "artifacts", "", "Comma-separated list of directories containing artifacts and build info")
flag.StringVar(&f.ForgeArtifacts, "forge-artifacts", "", "Forge artifacts directory, to load sourcemaps from, if available")
flag.StringVar(&f.OutDir, "out", "", "Output directory to put code in")
flag.StringVar(&f.Contracts, "contracts", "", "Comma-separated list of contracts to generate code for")
flag.StringVar(&f.SourceMaps, "source-maps", "", "Comma-separated list of contracts to generate source-maps for")
flag.StringVar(&f.Package, "package", "artifacts", "Go package name")
flag.Parse()
artifacts := strings.Split(f.ArtifactsDir, ",")
contracts := strings.Split(f.Contracts, ",")
sourceMaps := strings.Split(f.SourceMaps, ",")
sourceMapsSet := make(map[string]struct{})
for _, k := range sourceMaps {
sourceMapsSet[k] = struct{}{}
}
if len(artifacts) == 0 {
log.Fatalf("must define a list of artifacts")
......@@ -71,11 +89,28 @@ func main() {
}
serStr := strings.Replace(string(ser), "\"", "\\\"", -1)
deployedSourceMap := ""
if _, ok := sourceMapsSet[name]; ok {
// directory has .sol extension
forgeArtifactData, err := os.ReadFile(path.Join(f.ForgeArtifacts, name+".sol", name+".json"))
if errors.Is(err, os.ErrNotExist) {
log.Printf("cannot find forge-artifact with source-map data of %q\n", name)
}
if err == nil {
var artifact forgeArtifact
if err := json.Unmarshal(forgeArtifactData, &artifact); err != nil {
log.Fatalf("failed to parse forge artifact of %q: %v\n", name, err)
}
deployedSourceMap = artifact.DeployedBytecode.SourceMap
}
}
d := data{
Name: name,
StorageLayout: serStr,
DeployedBin: art.DeployedBytecode.String(),
Package: f.Package,
Name: name,
StorageLayout: serStr,
DeployedBin: art.DeployedBytecode.String(),
Package: f.Package,
DeployedSourceMap: deployedSourceMap,
}
fname := filepath.Join(f.OutDir, strings.ToLower(name)+"_more.go")
......@@ -112,7 +147,9 @@ const {{.Name}}StorageLayoutJSON = "{{.StorageLayout}}"
var {{.Name}}StorageLayout = new(solc.StorageLayout)
var {{.Name}}DeployedBin = "{{.DeployedBin}}"
{{if .DeployedSourceMap}}
var {{.Name}}DeployedSourceMap = "{{.DeployedSourceMap}}"
{{end}}
func init() {
if err := json.Unmarshal([]byte({{.Name}}StorageLayoutJSON), {{.Name}}StorageLayout); err != nil {
panic(err)
......
......@@ -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{}
......
......@@ -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() {
......
......@@ -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"),
}
)
......
......@@ -244,6 +244,11 @@ func BuildL1DeveloperGenesis(config *DeployConfig) (*core.Genesis, error) {
return nil, err
}
if config.FundDevAccounts {
FundDevAccounts(stateDB)
SetPrecompileBalances(stateDB)
}
for _, dep := range deployments {
st, err := stateDB.StorageTrie(dep.Address)
if err != nil {
......
package srcmap
import (
"fmt"
"io"
"math/big"
"os"
"strconv"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
)
type LineCol struct {
Line uint32
Col uint32
}
type InstrMapping struct {
S int32 // start offset in bytes within source (negative when non-existent!)
L int32 // length in bytes within source (negative when non-existent!)
F int32 // file index of source (negative when non-existent!)
J byte // jump type (i=into, o=out, -=regular)
M int32 // modifier depth
}
func parseInstrMapping(last InstrMapping, v string) (InstrMapping, error) {
data := strings.Split(v, ":")
out := last
if len(data) < 1 {
return out, nil
}
if len(data) > 5 {
return out, fmt.Errorf("unexpected length: %d", len(data))
}
var err error
parse := func(x string) int32 {
p, e := strconv.ParseInt(x, 10, 32)
err = e
return int32(p)
}
if data[0] != "" {
out.S = parse(data[0])
}
if len(data) < 2 || err != nil {
return out, err
}
if data[1] != "" {
out.L = parse(data[1])
}
if len(data) < 3 || err != nil {
return out, err
}
if data[2] != "" {
out.F = parse(data[2])
}
if len(data) < 4 || err != nil {
return out, err
}
if data[3] != "" {
out.J = data[3][0]
}
if len(data) < 5 || err != nil {
return out, err
}
if data[4] != "" {
out.M = parse(data[4])
}
return out, err
}
type SourceMap struct {
// source names
Sources []string
// per source, source offset -> line/col
PosData [][]LineCol
// per bytecode byte, byte index -> instr
Instr []InstrMapping
}
func (s *SourceMap) Info(pc uint64) (source string, line uint32, col uint32) {
instr := s.Instr[pc]
if instr.F < 0 {
return "generated", 0, 0
}
if instr.F >= int32(len(s.Sources)) {
source = "unknown"
return
}
source = s.Sources[instr.F]
if instr.S < 0 {
return
}
if s.PosData[instr.F] == nil { // when the source file is known to be unavailable
return
}
lc := s.PosData[instr.F][instr.S]
line = lc.Line
col = lc.Col
return
}
func (s *SourceMap) FormattedInfo(pc uint64) string {
f, l, c := s.Info(pc)
return fmt.Sprintf("%s:%d:%d", f, l, c)
}
// ParseSourceMap parses a solidity sourcemap: mapping bytecode indices to source references.
// See https://docs.soliditylang.org/en/latest/internals/source_mappings.html
//
// Sources is the list of source files, which will be read from the filesystem
// to transform token numbers into line/column numbers.
// The sources are as referenced in the source-map by index.
// Not all sources are necessary, some indices may be unknown.
func ParseSourceMap(sources []string, bytecode []byte, sourceMap string) (*SourceMap, error) {
instructions := strings.Split(sourceMap, ";")
srcMap := &SourceMap{
Sources: sources,
PosData: make([][]LineCol, 0, len(sources)),
Instr: make([]InstrMapping, 0, len(bytecode)),
}
// map source code position byte offsets to line/column pairs
for i, s := range sources {
if strings.HasPrefix(s, "~") {
srcMap.PosData = append(srcMap.PosData, nil)
continue
}
dat, err := os.ReadFile(s)
if err != nil {
return nil, fmt.Errorf("failed to read source %d %q: %w", i, s, err)
}
datStr := string(dat)
out := make([]LineCol, len(datStr))
line := uint32(1)
lastLinePos := uint32(0)
for i, b := range datStr { // iterate the utf8 or the bytes?
col := uint32(i) - lastLinePos
out[i] = LineCol{Line: line, Col: col}
if b == '\n' {
lastLinePos = uint32(i)
line += 1
}
}
srcMap.PosData = append(srcMap.PosData, out)
}
instIndex := 0
// bytecode offset to instruction
lastInstr := InstrMapping{}
for i := 0; i < len(bytecode); {
inst := bytecode[i]
instLen := 1
if inst >= 0x60 && inst <= 0x7f { // push instructions
pushDataLen := inst - 0x60 + 1
instLen += int(pushDataLen)
}
var instMapping string
if instIndex >= len(instructions) {
// truncated source-map? Or some instruction that's longer than we accounted for?
// probably the contract-metadata bytes that are not accounted for in source map
} else {
instMapping = instructions[instIndex]
}
m, err := parseInstrMapping(lastInstr, instMapping)
if err != nil {
return nil, fmt.Errorf("failed to parse instr element in source map: %w", err)
}
for j := 0; j < instLen; j++ {
srcMap.Instr = append(srcMap.Instr, m)
}
i += instLen
instIndex += 1
}
return srcMap, nil
}
func NewSourceMapTracer(srcMaps map[common.Address]*SourceMap, out io.Writer) *SourceMapTracer {
return &SourceMapTracer{srcMaps, out}
}
type SourceMapTracer struct {
srcMaps map[common.Address]*SourceMap
out io.Writer
}
func (s *SourceMapTracer) CaptureTxStart(gasLimit uint64) {}
func (s *SourceMapTracer) CaptureTxEnd(restGas uint64) {}
func (s *SourceMapTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
}
func (s *SourceMapTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {}
func (s *SourceMapTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
}
func (s *SourceMapTracer) CaptureExit(output []byte, gasUsed uint64, err error) {}
func (s *SourceMapTracer) info(codeAddr *common.Address, pc uint64) string {
info := "non-contract"
if codeAddr != nil {
srcMap, ok := s.srcMaps[*codeAddr]
if ok {
info = srcMap.FormattedInfo(pc)
} else {
info = "unknown-contract"
}
}
return info
}
func (s *SourceMapTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
fmt.Fprintf(s.out, "%-40s : pc %x opcode %s\n", s.info(scope.Contract.CodeAddr, pc), pc, op.String())
}
func (s *SourceMapTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
fmt.Fprintf(s.out, "%-40s: pc %x opcode %s FAULT %v\n", s.info(scope.Contract.CodeAddr, pc), pc, op.String(), err)
fmt.Println("----")
fmt.Fprintf(s.out, "calldata: %x\n", scope.Contract.Input)
fmt.Println("----")
fmt.Fprintf(s.out, "memory: %x\n", scope.Memory.Data())
fmt.Println("----")
fmt.Fprintf(s.out, "stack:\n")
stack := scope.Stack.Data()
for i := range stack {
fmt.Fprintf(s.out, "%3d: %x\n", -i, stack[len(stack)-1-i].Bytes32())
}
}
var _ vm.EVMLogger = (*SourceMapTracer)(nil)
package srcmap
import (
"strings"
"testing"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
)
func TestSourcemap(t *testing.T) {
sourcePath := "../../packages/contracts-bedrock/contracts/cannon/MIPS.sol"
deployedByteCode := hexutil.MustDecode(bindings.MIPSDeployedBin)
srcMap, err := ParseSourceMap(
[]string{sourcePath},
deployedByteCode,
bindings.MIPSDeployedSourceMap)
require.NoError(t, err)
for i := 0; i < len(deployedByteCode); i++ {
info := srcMap.FormattedInfo(uint64(i))
if !strings.HasPrefix(info, "generated:") && !strings.HasPrefix(info, sourcePath) {
t.Fatalf("unexpected info: %q", info)
}
}
}
......@@ -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,
......
package watch
import (
"github.com/urfave/cli"
"github.com/urfave/cli/v2"
"github.com/ethereum-optimism/optimism/op-challenger/config"
)
......
......@@ -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
}
......
......@@ -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"
)
......
package fault
import (
"math/big"
"strings"
"github.com/ethereum/go-ethereum/common"
)
// AlphabetProvider is a [TraceProvider] that provides claims for specific
// indices in the given trace.
type AlphabetProvider struct {
state []string
maxLen uint64
}
// NewAlphabetProvider returns a new [AlphabetProvider].
func NewAlphabetProvider(state string, depth uint64) *AlphabetProvider {
return &AlphabetProvider{
state: strings.Split(state, ""),
maxLen: (1 << depth),
}
}
// Get returns the claim value at the given index in the trace.
func (ap *AlphabetProvider) Get(i uint64) (common.Hash, error) {
// The index cannot be larger than the maximum index as computed by the depth.
if i >= ap.maxLen {
return common.Hash{}, ErrIndexTooLarge
}
// We extend the deepest hash to the maximum depth if the trace is not expansive.
if i >= uint64(len(ap.state)) {
return ap.Get(uint64(len(ap.state)) - 1)
}
return ap.ComputeAlphabetClaim(i), nil
}
// ComputeAlphabetClaim computes the claim for the given index in the trace.
func (ap *AlphabetProvider) ComputeAlphabetClaim(i uint64) common.Hash {
concatenated := append(IndexToBytes(i), []byte(ap.state[i])...)
return common.BytesToHash(concatenated)
}
// IndexToBytes converts an index to a byte slice big endian
func IndexToBytes(i uint64) []byte {
big := new(big.Int)
big.SetUint64(i)
return big.Bytes()
}
package fault
import (
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
// FuzzIndexToBytes tests the IndexToBytes function.
func FuzzIndexToBytes(f *testing.F) {
f.Fuzz(func(t *testing.T, index uint64) {
translated := IndexToBytes(index)
original := new(big.Int)
original.SetBytes(translated)
require.Equal(t, original.Uint64(), index)
})
}
// TestComputeAlphabetClaim tests the ComputeAlphabetClaim function.
func TestComputeAlphabetClaim(t *testing.T) {
ap := NewAlphabetProvider("abc", 2)
claim := ap.ComputeAlphabetClaim(0)
concatenated := append(IndexToBytes(0), []byte("a")...)
expected := common.BytesToHash(concatenated)
require.Equal(t, expected, claim)
}
// TestGet tests the Get function.
func TestGet(t *testing.T) {
ap := NewAlphabetProvider("abc", 2)
claim, err := ap.Get(0)
require.NoError(t, err)
concatenated := append(IndexToBytes(0), []byte("a")...)
expected := common.BytesToHash(concatenated)
require.Equal(t, expected, claim)
}
// TestGet_IndexTooLarge tests the Get function with an index
// greater than the number of indices: 2^depth - 1.
func TestGet_IndexTooLarge(t *testing.T) {
ap := NewAlphabetProvider("abc", 2)
_, err := ap.Get(4)
require.ErrorIs(t, err, ErrIndexTooLarge)
}
// TestGet_Extends tests the Get function with an index that is larger
// than the trace, but smaller than the maximum depth.
func TestGet_Extends(t *testing.T) {
ap := NewAlphabetProvider("abc", 2)
claim, err := ap.Get(3)
require.NoError(t, err)
concatenated := append(IndexToBytes(2), []byte("c")...)
expected := common.BytesToHash(concatenated)
require.Equal(t, expected, claim)
}
package main
import (
"github.com/ethereum-optimism/optimism/op-challenger/fault"
)
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)
// GIN: 1 Trace Position is 0 Trace Depth is: 0 Trace Index is: 8
// GIN: 10 Trace Position is 0 Trace Depth is: 1 Trace Index is: 4
// GIN: 110 Trace Position is 10 Trace Depth is: 2 Trace Index is: 6
// GIN: 1100 Trace Position is 100 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
}
package fault
import "fmt"
// Position is a golang wrapper around the dispute game Position type.
type Position struct {
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) int {
// 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 p.indexAtDepth<<rd | ((1 << rd) - 1)
}
// move goes to the left or right child.
func (p *Position) move(right bool) {
p.depth++
p.indexAtDepth = (p.indexAtDepth << 1) | boolToInt(right)
}
func boolToInt(b bool) int {
if b {
return 1
} else {
return 0
}
}
// parent moves up to the parent.
func (p *Position) parent() {
p.depth--
p.indexAtDepth = p.indexAtDepth >> 1
}
// Attack moves this position to a position to the left which disagrees with this position.
func (p *Position) Attack() {
p.move(false)
}
// Defend moves this position to the right which agrees with this position. Note:
func (p *Position) Defend() {
p.parent()
p.move(true)
p.move(false)
}
func (p *Position) Print(maxDepth int) {
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<<p.depth | p.indexAtDepth)
}
// MSBIndex returns the index of the most significant bit
func MSBIndex(x uint64) int {
if x == 0 {
return 0
}
out := 0
for ; x != 0; out++ {
x = x >> 1
}
return out - 1
}
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 int
}
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)
}
}
package fault
import (
"errors"
"github.com/ethereum/go-ethereum/common"
)
var (
ErrNegativeIndex = errors.New("index cannot be negative")
ErrIndexTooLarge = errors.New("index is larger than the maximum index")
)
// TraceProvider is a generic way to get a claim value at a specific
// step in the trace.
// The [AlphabetProvider] is a minimal implementation of this interface.
type TraceProvider interface {
Get(i uint64) (common.Hash, error)
}
type Claim struct {
Value common.Hash
Position
}
type Response struct {
Attack bool // note: can we flip this to true == going right / defending??
Value common.Hash
}
......@@ -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
......
......@@ -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()
}
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
......
......@@ -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 (
......
......@@ -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),
......
......@@ -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"),
}
)
......
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
)
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=
......@@ -14,7 +14,7 @@ import (
"syscall"
"time"
"github.com/urfave/cli"
"github.com/urfave/cli/v2"
"github.com/ethereum/go-ethereum/log"
......
......@@ -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",
......
......@@ -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)",
......
......@@ -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",
},
......
......@@ -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,
......
......@@ -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) {
......
......@@ -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
......
......@@ -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
......
......@@ -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"),
}
)
......
......@@ -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"
}
......@@ -174,8 +174,8 @@ func loadDiscoveryOpts(conf *p2p.Config, ctx *cli.Context) error {
return fmt.Errorf("failed to open discovery db: %w", err)
}
conf.Bootnodes = p2p.DefaultBootnodes
records := strings.Split(ctx.GlobalString(flags.Bootnodes.Name), ",")
bootnodes := make([]*enode.Node, 0)
records := strings.Split(ctx.String(flags.Bootnodes.Name), ",")
for i, recordB64 := range records {
recordB64 = strings.TrimSpace(recordB64)
if recordB64 == "" { // ignore empty records
......@@ -185,14 +185,19 @@ func loadDiscoveryOpts(conf *p2p.Config, ctx *cli.Context) error {
if err != nil {
return fmt.Errorf("bootnode record %d (of %d) is invalid: %q err: %w", i, len(records), recordB64, err)
}
conf.Bootnodes = append(conf.Bootnodes, nodeRecord)
bootnodes = append(bootnodes, nodeRecord)
}
if len(bootnodes) > 0 {
conf.Bootnodes = bootnodes
} else {
conf.Bootnodes = p2p.DefaultBootnodes
}
return nil
}
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 == "" {
......@@ -205,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":
......@@ -217,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 {
......@@ -235,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")
}
......@@ -265,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")
}
......@@ -319,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
}
......@@ -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).
......
......@@ -276,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)
......@@ -501,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)
......
......@@ -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
......
# op-preimage
`op-preimage` offers simple Go bindings to interact as client or sever over the Pre-image Oracle ABI.
Read more about the Preimage Oracle in the [specs](../specs/fault-proof.md).
See [op-program](../op-program) and [Cannon client examples](../cannon/example) for client-side usage.
See [Cannon `mipsevm`](../cannon/mipsevm) for server-side usage.
package preimage
import (
"io"
"os"
)
// FileChannel is a unidirectional channel for file I/O
type FileChannel interface {
io.ReadWriteCloser
// Reader returns the file that is used for reading.
Reader() *os.File
// Writer returns the file that is used for writing.
Writer() *os.File
}
type ReadWritePair struct {
r *os.File
w *os.File
}
// NewReadWritePair creates a new FileChannel that uses the given files
func NewReadWritePair(r *os.File, w *os.File) *ReadWritePair {
return &ReadWritePair{r: r, w: w}
}
func (rw *ReadWritePair) Read(p []byte) (int, error) {
return rw.r.Read(p)
}
func (rw *ReadWritePair) Write(p []byte) (int, error) {
return rw.w.Write(p)
}
func (rw *ReadWritePair) Reader() *os.File {
return rw.r
}
func (rw *ReadWritePair) Writer() *os.File {
return rw.w
}
func (rw *ReadWritePair) Close() error {
if err := rw.r.Close(); err != nil {
return err
}
return rw.w.Close()
}
// CreateBidirectionalChannel creates a pair of FileChannels that are connected to each other.
func CreateBidirectionalChannel() (FileChannel, FileChannel, error) {
ar, bw, err := os.Pipe()
if err != nil {
return nil, nil, err
}
br, aw, err := os.Pipe()
if err != nil {
return nil, nil, err
}
return NewReadWritePair(ar, aw), NewReadWritePair(br, bw), nil
}
const (
HClientRFd = 3
HClientWFd = 4
PClientRFd = 5
PClientWFd = 6
)
func ClientHinterChannel() *ReadWritePair {
r := os.NewFile(HClientRFd, "preimage-hint-read")
w := os.NewFile(HClientWFd, "preimage-hint-write")
return NewReadWritePair(r, w)
}
// ClientPreimageChannel returns a FileChannel for the preimage oracle in a detached context
func ClientPreimageChannel() *ReadWritePair {
r := os.NewFile(PClientRFd, "preimage-oracle-read")
w := os.NewFile(PClientWFd, "preimage-oracle-write")
return NewReadWritePair(r, w)
}
package preimage
import "golang.org/x/crypto/sha3"
func Keccak256(v []byte) (out [32]byte) {
s := sha3.NewLegacyKeccak256()
s.Write(v)
s.Sum(out[:0])
return
}
......@@ -2,14 +2,13 @@ package preimage
import (
"encoding/binary"
"github.com/ethereum/go-ethereum/common"
"encoding/hex"
)
type Key interface {
// PreimageKey changes the Key commitment into a
// 32-byte type-prefixed preimage key.
PreimageKey() common.Hash
PreimageKey() [32]byte
}
type Oracle interface {
......@@ -40,27 +39,27 @@ const (
// LocalIndexKey is a key local to the program, indexing a special program input.
type LocalIndexKey uint64
func (k LocalIndexKey) PreimageKey() (out common.Hash) {
func (k LocalIndexKey) PreimageKey() (out [32]byte) {
out[0] = byte(LocalKeyType)
binary.BigEndian.PutUint64(out[24:], uint64(k))
return
}
// Keccak256Key wraps a keccak256 hash to use it as a typed pre-image key.
type Keccak256Key common.Hash
type Keccak256Key [32]byte
func (k Keccak256Key) PreimageKey() (out common.Hash) {
out = common.Hash(k) // copy the keccak hash
func (k Keccak256Key) PreimageKey() (out [32]byte) {
out = k // copy the keccak hash
out[0] = byte(Keccak256KeyType) // apply prefix
return
}
func (k Keccak256Key) String() string {
return common.Hash(k).String()
return "0x" + hex.EncodeToString(k[:])
}
func (k Keccak256Key) TerminalString() string {
return common.Hash(k).String()
return "0x" + hex.EncodeToString(k[:])
}
// Hint is an interface to enable any program type to function as a hint,
......
......@@ -4,8 +4,6 @@ import (
"encoding/binary"
"fmt"
"io"
"github.com/ethereum/go-ethereum/common"
)
// OracleClient implements the Oracle by writing the pre-image key to the given stream,
......@@ -47,10 +45,10 @@ func NewOracleServer(rw io.ReadWriter) *OracleServer {
return &OracleServer{rw: rw}
}
type PreimageGetter func(key common.Hash) ([]byte, error)
type PreimageGetter func(key [32]byte) ([]byte, error)
func (o *OracleServer) NextPreimageRequest(getPreimage PreimageGetter) error {
var key common.Hash
var key [32]byte
if _, err := io.ReadFull(o.rw, key[:]); err != nil {
if err == io.EOF {
return io.EOF
......
......@@ -8,8 +8,6 @@ import (
"sync"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require"
)
......@@ -30,13 +28,13 @@ func TestOracle(t *testing.T) {
cl := NewOracleClient(a)
srv := NewOracleServer(b)
preimageByHash := make(map[common.Hash][]byte)
preimageByHash := make(map[[32]byte][]byte)
for _, p := range preimages {
k := Keccak256Key(crypto.Keccak256Hash(p))
k := Keccak256Key(Keccak256(p))
preimageByHash[k.PreimageKey()] = p
}
for _, p := range preimages {
k := Keccak256Key(crypto.Keccak256Hash(p))
k := Keccak256Key(Keccak256(p))
var wg sync.WaitGroup
wg.Add(2)
......@@ -49,7 +47,7 @@ func TestOracle(t *testing.T) {
}(k, p)
go func() {
err := srv.NextPreimageRequest(func(key common.Hash) ([]byte, error) {
err := srv.NextPreimageRequest(func(key [32]byte) ([]byte, error) {
dat, ok := preimageByHash[key]
if !ok {
return nil, fmt.Errorf("cannot find %s", key)
......
......@@ -6,6 +6,7 @@ RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash
# build op-program with the shared go.mod & go.sum files
COPY ./op-program /app/op-program
COPY ./op-preimage /app/op-preimage
COPY ./op-node /app/op-node
COPY ./op-chain-ops /app/op-chain-ops
COPY ./op-service /app/op-service
......
......@@ -5,7 +5,7 @@ import (
"encoding/json"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-program/preimage"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
)
......
......@@ -6,7 +6,7 @@ import (
"testing"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-program/preimage"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
......
......@@ -3,7 +3,7 @@ package l1
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum-optimism/optimism/op-program/preimage"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
)
const (
......
......@@ -8,8 +8,8 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum-optimism/optimism/op-node/eth"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-program/client/mpt"
"github.com/ethereum-optimism/optimism/op-program/preimage"
)
type Oracle interface {
......
......@@ -15,8 +15,8 @@ import (
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/testutils"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-program/client/mpt"
"github.com/ethereum-optimism/optimism/op-program/preimage"
)
// testBlock tests that the given block with receipts can be passed through the preimage oracle.
......
......@@ -3,7 +3,7 @@ package l2
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum-optimism/optimism/op-program/preimage"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
)
const (
......
......@@ -8,8 +8,8 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum-optimism/optimism/op-node/eth"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-program/client/mpt"
"github.com/ethereum-optimism/optimism/op-program/preimage"
)
// StateOracle defines the high-level API used to retrieve L2 state data pre-images
......
......@@ -15,8 +15,8 @@ import (
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/testutils"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-program/client/mpt"
"github.com/ethereum-optimism/optimism/op-program/preimage"
)
func mockPreimageOracle(t *testing.T) (po *PreimageOracle, hintsMock *mock.Mock, preimages map[common.Hash][]byte) {
......
......@@ -13,11 +13,11 @@ import (
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
cldr "github.com/ethereum-optimism/optimism/op-program/client/driver"
"github.com/ethereum-optimism/optimism/op-program/client/l1"
"github.com/ethereum-optimism/optimism/op-program/client/l2"
oppio "github.com/ethereum-optimism/optimism/op-program/io"
"github.com/ethereum-optimism/optimism/op-program/preimage"
)
// Main executes the client program in a detached context and exits the current process.
......
......@@ -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 (
......
......@@ -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
}
......
......@@ -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
......
......@@ -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()
}
......@@ -6,13 +6,13 @@ import (
"fmt"
"io"
"io/fs"
"math"
"os"
"os/exec"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-node/client"
"github.com/ethereum-optimism/optimism/op-node/sources"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
cl "github.com/ethereum-optimism/optimism/op-program/client"
"github.com/ethereum-optimism/optimism/op-program/client/driver"
"github.com/ethereum-optimism/optimism/op-program/host/config"
......@@ -20,15 +20,11 @@ import (
"github.com/ethereum-optimism/optimism/op-program/host/kvstore"
"github.com/ethereum-optimism/optimism/op-program/host/prefetcher"
oppio "github.com/ethereum-optimism/optimism/op-program/io"
"github.com/ethereum-optimism/optimism/op-program/preimage"
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(rpc, maxRPCRetries), nil
}
func routeHints(logger log.Logger, hHostRW io.ReadWriter, hinter preimage.HintHandler) chan error {
chErr := make(chan error)
hintReader := preimage.NewHintReader(hHostRW)
......
......@@ -8,12 +8,12 @@ import (
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-node/testlog"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-program/client"
"github.com/ethereum-optimism/optimism/op-program/client/l1"
"github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum-optimism/optimism/op-program/host/kvstore"
"github.com/ethereum-optimism/optimism/op-program/io"
"github.com/ethereum-optimism/optimism/op-program/preimage"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
......
......@@ -27,7 +27,7 @@ var (
)
func (s *LocalPreimageSource) Get(key common.Hash) ([]byte, error) {
switch key {
switch [32]byte(key) {
case l1HeadKey:
return s.config.L1Head.Bytes(), nil
case l2HeadKey:
......
......@@ -6,8 +6,8 @@ import (
"testing"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum-optimism/optimism/op-program/preimage"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
......
package kvstore
import (
"github.com/ethereum-optimism/optimism/op-program/preimage"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum/go-ethereum/common"
)
......@@ -19,7 +19,7 @@ func NewPreimageSourceSplitter(local PreimageSource, global PreimageSource) *Pre
}
}
func (s *PreimageSourceSplitter) Get(key common.Hash) ([]byte, error) {
func (s *PreimageSourceSplitter) Get(key [32]byte) ([]byte, error) {
if key[0] == byte(preimage.LocalKeyType) {
return s.local(key)
}
......
......@@ -3,7 +3,7 @@ package kvstore
import (
"testing"
"github.com/ethereum-optimism/optimism/op-program/preimage"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
......
......@@ -7,11 +7,11 @@ import (
"strings"
"github.com/ethereum-optimism/optimism/op-node/eth"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-program/client/l1"
"github.com/ethereum-optimism/optimism/op-program/client/l2"
"github.com/ethereum-optimism/optimism/op-program/client/mpt"
"github.com/ethereum-optimism/optimism/op-program/host/kvstore"
"github.com/ethereum-optimism/optimism/op-program/preimage"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
......@@ -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,
}
}
......
......@@ -15,11 +15,11 @@ import (
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/testutils"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-program/client/l1"
"github.com/ethereum-optimism/optimism/op-program/client/l2"
"github.com/ethereum-optimism/optimism/op-program/client/mpt"
"github.com/ethereum-optimism/optimism/op-program/host/kvstore"
"github.com/ethereum-optimism/optimism/op-program/preimage"
)
func TestNoHint(t *testing.T) {
......
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)
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)
......@@ -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)",
......
......@@ -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,
......
......@@ -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
......
......@@ -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),
......
......@@ -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"
......
......@@ -2,7 +2,7 @@ test:
go test -v ./...
lint:
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint -e "errors.As" -e "errors.Is" ./...
golangci-lint run -E asciicheck,goimports,misspell ./...
generate-mocks:
go generate ./...
......
package client
import (
"context"
"time"
"github.com/ethereum/go-ethereum"
"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 {
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(c client.RPC, retries int, strategy ...backoff.Strategy) *retryingClient {
if len(strategy) == 0 {
strategy = []backoff.Strategy{ExponentialBackoff}
}
return &retryingClient{
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()
return b.c.CallContext(cCtx, result, method, args...)
})
}
// 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 {
// 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
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...)
return err
})
return sub, err
}
package client_test
import (
"context"
"errors"
"testing"
"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(mockRpc, 0)
require.Equal(t, backoffClient.BackoffStrategy(), client.ExponentialBackoff)
fixedStrategy := &backoff.FixedStrategy{}
backoffClient = client.NewRetryingClient(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(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(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(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(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(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(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(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(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(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))
}
......@@ -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 {
......
......@@ -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),
......
......@@ -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),
}
}
......@@ -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),
}
}
......@@ -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)),
}
}
......@@ -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),
}
}
......
......@@ -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{}{}
}
}
......
......@@ -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",
},
}
......
......@@ -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")...)
......
......@@ -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,
}
......
......@@ -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,
......
# @eth-optimism/drippie-mon
## 0.4.0
### Minor Changes
- d6388be4a: Added a new service wallet-mon to identify unexpected transfers from key accounts
### Patch Changes
- 287d317d3: Fixed an issue with logging the wrong timestamp.
- Updated dependencies [8d7dcc70c]
- Updated dependencies [119754c2f]
- Updated dependencies [d6388be4a]
- Updated dependencies [af292562f]
- @eth-optimism/core-utils@0.12.1
- @eth-optimism/sdk@3.0.0
- @eth-optimism/contracts-bedrock@0.15.0
- @eth-optimism/common-ts@0.8.2
## 0.3.1
### Patch Changes
......
{
"private": true,
"name": "@eth-optimism/chain-mon",
"version": "0.3.1",
"version": "0.4.0",
"description": "[Optimism] Chain monitoring services",
"main": "dist/index",
"types": "dist/index",
......@@ -34,11 +34,11 @@
"url": "https://github.com/ethereum-optimism/optimism.git"
},
"dependencies": {
"@eth-optimism/common-ts": "0.8.1",
"@eth-optimism/common-ts": "0.8.2",
"@eth-optimism/contracts-periphery": "1.0.8",
"@eth-optimism/contracts-bedrock": "0.14.0",
"@eth-optimism/core-utils": "0.12.0",
"@eth-optimism/sdk": "2.1.0",
"@eth-optimism/contracts-bedrock": "0.15.0",
"@eth-optimism/core-utils": "0.12.1",
"@eth-optimism/sdk": "3.0.0",
"ethers": "^5.7.0",
"@types/dateformat": "^5.0.0",
"chai-as-promised": "^7.1.1",
......
# @eth-optimism/common-ts
## 0.8.2
### Patch Changes
- Updated dependencies [8d7dcc70c]
- Updated dependencies [d6388be4a]
- @eth-optimism/core-utils@0.12.1
## 0.8.1
### Patch Changes
......
{
"name": "@eth-optimism/common-ts",
"version": "0.8.1",
"version": "0.8.2",
"description": "[Optimism] Advanced typescript tooling used by various services",
"main": "dist/index",
"types": "dist/index",
......@@ -33,7 +33,7 @@
"url": "https://github.com/ethereum-optimism/optimism.git"
},
"dependencies": {
"@eth-optimism/core-utils": "0.12.0",
"@eth-optimism/core-utils": "0.12.1",
"@sentry/node": "^6.3.1",
"bcfg": "^0.1.7",
"body-parser": "^1.20.0",
......
......@@ -32,19 +32,24 @@ 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: 26474)
FaultDisputeGame_Test:test_defendRoot_reverts() (gas: 13258)
FaultDisputeGame_Test:test_duplicateClaim_reverts() (gas: 103381)
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: 5907275)
FaultDisputeGame_Test:test_gameDepthExceeded_reverts() (gas: 5907231)
FaultDisputeGame_Test:test_gameStart_succeeds() (gas: 10337)
FaultDisputeGame_Test:test_gameType_succeeds() (gas: 8194)
FaultDisputeGame_Test:test_initialRootClaimData_succeeds() (gas: 17580)
FaultDisputeGame_Test:test_moveAgainstNonexistentParent_reverts() (gas: 24587)
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_rootClaim_succeeds() (gas: 8191)
FaultDisputeGame_Test:test_simpleAttack_succeeds() (gas: 107367)
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)
FeeVault_Test:test_constructor_succeeds() (gas: 18185)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 352135)
......
......@@ -14,3 +14,7 @@ deployments
# Other autogenerated files
gasReporterOutput.json
slither.db.json
# MIPS.sol has special VM formatting, not like other contracts.
# Prettier also fails to handle YUL functions with multiple return variables.
contracts/cannon/MIPS.sol
......@@ -3,3 +3,6 @@ node_modules
lib
contracts/test/*.t.sol
contracts/vendor/*.sol
# MIPS.sol has special VM formatting, not like other contracts.
contracts/cannon/MIPS.sol
# @eth-optimism/contracts-bedrock
## 0.15.0
### Minor Changes
- af292562f: Fix issue with deposits running out of gas
### Patch Changes
- Updated dependencies [8d7dcc70c]
- Updated dependencies [d6388be4a]
- @eth-optimism/core-utils@0.12.1
## 0.14.0
### Minor Changes
......
......@@ -10,8 +10,8 @@ with priority on the `L2OutputOracle` and `OptimismPortal`.
#### Comments
We use [Seaport](https://github.com/ProjectOpenSea/seaport/blob/main/contracts/Seaport.sol)-style comments with some minor modifications.
Some basic rules:
Optimism smart contracts follow the triple-slash [solidity natspec comment style](https://docs.soliditylang.org/en/develop/natspec-format.html#documentation-example)
with additional rules. These are:
- Always use `@notice` since it has the same general effect as `@dev` but avoids confusion about when to use one over the other.
- Include a newline between `@notice` and the first `@param`.
......@@ -28,13 +28,19 @@ We also have the following custom tags:
#### Errors
- Use `require` statements when making simple assertions.
- Use `revert` if throwing an error where an assertion is not being made (no custom errors). See [here](https://github.com/ethereum-optimism/optimism/blob/861ae315a6db698a8c0adb1f8eab8311fd96be4c/packages/contracts-bedrock/contracts/L2/OVM_ETH.sol#L31) for an example of this in practice.
- Use `revert(string)` if throwing an error where an assertion is not being made (no custom errors).
See [here](https://github.com/ethereum-optimism/optimism/blob/861ae315a6db698a8c0adb1f8eab8311fd96be4c/packages/contracts-bedrock/contracts/L2/OVM_ETH.sol#L31)
for an example of this in practice.
- Error strings MUST have the format `"{ContractName}: {message}"` where `message` is a lower case string.
#### Function Parameters
- Function parameters should be prefixed with an underscore.
#### Function Return Arguments
- Arguments returned by functions should be suffixed with an underscore.
#### Event Parameters
- Event parameters should NOT be prefixed with an underscore.
......@@ -42,16 +48,21 @@ We also have the following custom tags:
#### Spacers
We use spacer variables to account for old storage slots that are no longer being used.
The name of a spacer variable MUST be in the format `spacer_<slot>_<offset>_<length>` where `<slot>` is the original storage slot number, `<offset>` is the original offset position within the storage slot, and `<length>` is the original size of the variable.
The name of a spacer variable MUST be in the format `spacer_<slot>_<offset>_<length>` where
`<slot>` is the original storage slot number, `<offset>` is the original offset position
within the storage slot, and `<length>` is the original size of the variable.
Spacers MUST be `private`.
### Proxy by Default
All contracts should be assumed to live behind proxies (except in certain special circumstances).
This means that new contracts MUST be built under the assumption of upgradeability.
We use a minimal [`Proxy`](./contracts/universal/Proxy.sol) contract designed to be owned by a corresponding [`ProxyAdmin`](./contracts/universal/ProxyAdmin.sol) which follow the interfaces of OpenZeppelin's `Proxy` and `ProxyAdmin` contracts, respectively.
We use a minimal [`Proxy`](./contracts/universal/Proxy.sol) contract designed to be owned by a
corresponding [`ProxyAdmin`](./contracts/universal/ProxyAdmin.sol) which follow the interfaces
of OpenZeppelin's `Proxy` and `ProxyAdmin` contracts, respectively.
Unless explicitly discussed otherwise, you MUST include the following basic upgradeability pattern for each new implementation contract:
Unless explicitly discussed otherwise, you MUST include the following basic upgradeability
pattern for each new implementation contract:
1. Extend OpenZeppelin's `Initializable` base contract.
2. Include a `uint8 public constant VERSION = X` at the TOP of your contract.
......@@ -60,11 +71,13 @@ Unless explicitly discussed otherwise, you MUST include the following basic upgr
### Versioning
All (non-library and non-abstract) contracts MUST extend the `Semver` base contract which exposes a `version()` function that returns a semver-compliant version string.
During the Bedrock development process the `Semver` value for all contracts SHOULD return `0.0.1` (this is not particularly important, but it's an easy standard to follow).
When the initial Bedrock upgrade is released, the `Semver` value MUST be updated to `1.0.0`.
All (non-library and non-abstract) contracts MUST extend the `Semver` base contract which
exposes a `version()` function that returns a semver-compliant version string.
Contracts must have a `Semver` of `1.0.0` or greater to be production ready. Contracts
with `Semver` values less than `1.0.0` should only be used locally or on devnets.
After the initial Bedrock upgrade, contracts MUST use the following versioning scheme:
Additionally, contracts MUST use the following versioning scheme:
- `patch` releases are to be used only for changes that do NOT modify contract bytecode (such as updating comments).
- `minor` releases are to be used for changes that modify bytecode OR changes that expand the contract ABI provided that these changes do NOT break the existing interface.
......@@ -72,7 +85,8 @@ After the initial Bedrock upgrade, contracts MUST use the following versioning s
#### Exceptions
We have made an exception to the `Semver` rule for the `WETH` contract to avoid making changes to a well-known, simple, and recognizable contract.
We have made an exception to the `Semver` rule for the `WETH` contract to avoid
making changes to a well-known, simple, and recognizable contract.
### Dependencies
......
// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
interface IPreimageOracle {
function readPreimage(bytes32 key, uint256 offset) external view returns (bytes32 dat, uint256 datLen);
}
// https://inst.eecs.berkeley.edu/~cs61c/resources/MIPS_Green_Sheet.pdf
// https://uweb.engr.arizona.edu/~ece369/Resources/spim/MIPSReference.pdf
// https://en.wikibooks.org/wiki/MIPS_Assembly/Instruction_Formats
// https://www.cs.cmu.edu/afs/cs/academic/class/15740-f97/public/doc/mips-isa.pdf
// page A-177
// MIPS linux kernel errors used by Go runtime:
// https://github.com/golang/go/blob/master/src/syscall/zerrors_linux_mips.go
// This MIPS contract emulates a single MIPS instruction.
//
// Note that delay slots are isolated instructions:
// the nextPC in the state pre-schedules where the VM jumps next.
//
// The Step input is a packed VM state, with binary-merkle-tree witness data for memory reads/writes.
// The Step outputs a keccak256 hash of the packed VM State, and logs the resulting state for offchain usage.
contract MIPS {
struct State {
bytes32 memRoot;
bytes32 preimageKey;
uint32 preimageOffset;
uint32 pc;
uint32 nextPC; // State is executing a branch/jump delay slot if nextPC != pc+4
uint32 lo;
uint32 hi;
uint32 heap;
uint8 exitCode;
bool exited;
uint64 step;
uint32[32] registers;
}
// total State size: 32+32+6*4+1+1+8+32*4 = 226 bytes
uint32 constant public BRK_START = 0x40000000;
uint32 constant FD_STDIN = 0;
uint32 constant FD_STDOUT = 1;
uint32 constant FD_STDERR = 2;
uint32 constant FD_HINT_READ = 3;
uint32 constant FD_HINT_WRITE = 4;
uint32 constant FD_PREIMAGE_READ = 5;
uint32 constant FD_PREIMAGE_WRITE = 6;
uint32 constant EBADF = 0x9;
uint32 constant EINVAL = 0x16;
IPreimageOracle public oracle;
function SE(uint32 dat, uint32 idx) internal pure returns (uint32) {
bool isSigned = (dat >> (idx-1)) != 0;
uint256 signed = ((1 << (32-idx)) - 1) << idx;
uint256 mask = (1 << idx) - 1;
return uint32(dat&mask | (isSigned ? signed : 0));
}
function outputState() internal returns (bytes32 out) {
assembly {
// copies 'size' bytes, right-aligned in word at 'from', to 'to', incl. trailing data
function copyMem(from, to, size) -> fromOut, toOut {
mstore(to, mload(add(from, sub(32, size))))
fromOut := add(from, 32)
toOut := add(to, size)
}
let from := 0x80 // state
let start := mload(0x40) // free mem ptr
let to := start
from, to := copyMem(from, to, 32) // memRoot
from, to := copyMem(from, to, 32) // preimageKey
from, to := copyMem(from, to, 4) // preimageOffset
from, to := copyMem(from, to, 4) // pc
from, to := copyMem(from, to, 4) // nextPC
from, to := copyMem(from, to, 4) // lo
from, to := copyMem(from, to, 4) // hi
from, to := copyMem(from, to, 4) // heap
from, to := copyMem(from, to, 1) // exitCode
from, to := copyMem(from, to, 1) // exited
from, to := copyMem(from, to, 8) // step
from := add(from, 32) // offset to registers
for { let i := 0 } lt(i, 32) { i := add(i, 1) } { from, to := copyMem(from, to, 4) } // registers
mstore(to, 0) // clean up end
log0(start, sub(to, start)) // log the resulting MIPS state, for debugging
out := keccak256(start, sub(to, start))
}
return out;
}
function handleSyscall() internal returns (bytes32) {
State memory state;
assembly {
state := 0x80
}
uint32 syscall_no = state.registers[2];
uint32 v0 = 0;
uint32 v1 = 0;
uint32 a0 = state.registers[4];
uint32 a1 = state.registers[5];
uint32 a2 = state.registers[6];
if (syscall_no == 4090) {
// mmap
uint32 sz = a1;
if (sz&4095 != 0) { // adjust size to align with page size
sz += 4096 - (sz&4095);
}
if (a0 == 0) {
v0 = state.heap;
state.heap += sz;
} else {
v0 = a0;
}
} else if (syscall_no == 4045) {
// brk
v0 = BRK_START;
} else if (syscall_no == 4120) {
// clone (not supported)
v0 = 1;
} else if (syscall_no == 4246) {
// exit group
state.exited = true;
state.exitCode = uint8(a0);
return outputState();
} else if (syscall_no == 4003) { // read
// args: a0 = fd, a1 = addr, a2 = count
// returns: v0 = read, v1 = err code
if (a0 == FD_STDIN) {
// leave v0 and v1 zero: read nothing, no error
} else if (a0 == FD_PREIMAGE_READ) { // pre-image oracle
// verify proof 1 is correct, and get the existing memory.
uint32 mem = readMem(a1 & 0xFFffFFfc, 1); // mask the addr to align it to 4 bytes
(bytes32 dat, uint256 datLen) = oracle.readPreimage(state.preimageKey, state.preimageOffset);
assembly { // assembly for more precise ops, and no var count limit
let alignment := and(a1, 3) // the read might not start at an aligned address
let space := sub(4, alignment) // remaining space in memory word
if lt(space, datLen) { datLen := space } // if less space than data, shorten data
if lt(a2, datLen) { datLen := a2 } // if requested to read less, read less
dat := shr(sub(256, mul(datLen, 8)), dat) // right-align data
dat := shl(mul(alignment, 8), dat) // position data to insert into memory word
let mask := sub(shl(mul(sub(4, alignment), 8), 1), 1) // mask all bytes after start
let suffixMask := sub(shl(mul(add(sub(4, alignment), datLen), 8), 1), 1) // mask of all bytes starting from end, maybe none
mask := and(mask, not(suffixMask)) // reduce mask to just cover the data we insert
mem := or(and(mem, not(mask)), dat) // clear masked part of original memory, and insert data
}
writeMem(a1 & 0xFFffFFfc, 1, mem);
state.preimageOffset += uint32(datLen);
v0 = uint32(datLen);
} else if (a0 == FD_HINT_READ) { // hint response
// don't actually read into memory, just say we read it all, we ignore the result anyway
v0 = a2;
} else {
v0 = 0xFFffFFff;
v1 = EBADF;
}
} else if (syscall_no == 4004) { // write
// args: a0 = fd, a1 = addr, a2 = count
// returns: v0 = written, v1 = err code
if (a0 == FD_STDOUT || a0 == FD_STDERR || a0 == FD_HINT_WRITE) {
v0 = a2; // tell program we have written everything
} else if (a0 == FD_PREIMAGE_WRITE) { // pre-image oracle
uint32 mem = readMem(a1 & 0xFFffFFfc, 1); // mask the addr to align it to 4 bytes
bytes32 key = state.preimageKey;
assembly { // assembly for more precise ops, and no var count limit
let alignment := and(a1, 3) // the read might not start at an aligned address
let space := sub(4, alignment) // remaining space in memory word
if lt(space, a2) { a2 := space } // if less space than data, shorten data
key := shl(mul(a2, 8), key) // shift key, make space for new info
let mask := sub(shl(mul(a2, 8), 1), 1) // mask for extracting value from memory
mem := and(shr(mul(sub(space, a2), 8), mem), mask) // align value to right, mask it
key := or(key, mem) // insert into key
}
state.preimageKey = key;
state.preimageOffset = 0; // reset offset, to read new pre-image data from the start
v0 = a2;
} else {
v0 = 0xFFffFFff;
v1 = EBADF;
}
} else if (syscall_no == 4055) { // fcntl
// args: a0 = fd, a1 = cmd
if (a1 == 3) { // F_GETFL: get file descriptor flags
if (a0 == FD_STDIN || a0 == FD_PREIMAGE_READ || a0 == FD_HINT_READ) {
v0 = 0; // O_RDONLY
} else if (a0 == FD_STDOUT || a0 == FD_STDERR || a0 == FD_PREIMAGE_WRITE || a0 == FD_HINT_WRITE) {
v0 = 1; // O_WRONLY
} else {
v0 = 0xFFffFFff;
v1 = EBADF;
}
} else {
v0 = 0xFFffFFff;
v1 = EINVAL; // cmd not recognized by this kernel
}
}
state.registers[2] = v0;
state.registers[7] = v1;
state.pc = state.nextPC;
state.nextPC = state.nextPC + 4;
return outputState();
}
function handleBranch(uint32 opcode, uint32 insn, uint32 rtReg, uint32 rs) internal returns (bytes32) {
State memory state;
assembly {
state := 0x80
}
bool shouldBranch = false;
if (opcode == 4 || opcode == 5) { // beq/bne
uint32 rt = state.registers[rtReg];
shouldBranch = (rs == rt && opcode == 4) || (rs != rt && opcode == 5);
} else if (opcode == 6) { shouldBranch = int32(rs) <= 0; // blez
} else if (opcode == 7) { shouldBranch = int32(rs) > 0; // bgtz
} else if (opcode == 1) {
// regimm
uint32 rtv = ((insn >> 16) & 0x1F);
if (rtv == 0) shouldBranch = int32(rs) < 0; // bltz
if (rtv == 1) shouldBranch = int32(rs) >= 0; // bgez
}
uint32 prevPC = state.pc;
state.pc = state.nextPC; // execute the delay slot first
if (shouldBranch) {
state.nextPC = prevPC + 4 + (SE(insn&0xFFFF, 16)<<2); // then continue with the instruction the branch jumps to.
} else {
state.nextPC = state.nextPC + 4; // branch not taken
}
return outputState();
}
function handleHiLo(uint32 func, uint32 rs, uint32 rt, uint32 storeReg) internal returns (bytes32) {
State memory state;
assembly {
state := 0x80
}
uint32 val;
if (func == 0x10) val = state.hi; // mfhi
else if (func == 0x11) state.hi = rs; // mthi
else if (func == 0x12) val = state.lo; // mflo
else if (func == 0x13) state.lo = rs; // mtlo
else if (func == 0x18) { // mult
uint64 acc = uint64(int64(int32(rs))*int64(int32(rt)));
state.hi = uint32(acc>>32);
state.lo = uint32(acc);
} else if (func == 0x19) { // multu
uint64 acc = uint64(uint64(rs)*uint64(rt));
state.hi = uint32(acc>>32);
state.lo = uint32(acc);
} else if (func == 0x1a) { // div
state.hi = uint32(int32(rs)%int32(rt));
state.lo = uint32(int32(rs)/int32(rt));
} else if (func == 0x1b) { // divu
state.hi = rs%rt;
state.lo = rs/rt;
}
if (storeReg != 0) {
state.registers[storeReg] = val;
}
state.pc = state.nextPC;
state.nextPC = state.nextPC + 4;
return outputState();
}
function handleJump(uint32 linkReg, uint32 dest) internal returns (bytes32) {
State memory state;
assembly {
state := 0x80
}
uint32 prevPC = state.pc;
state.pc = state.nextPC;
state.nextPC = dest;
if (linkReg != 0) {
state.registers[linkReg] = prevPC+8; // set the link-register to the instr after the delay slot instruction.
}
return outputState();
}
function handleRd(uint32 storeReg, uint32 val, bool conditional) internal returns (bytes32) {
State memory state;
assembly {
state := 0x80
}
require(storeReg < 32, "valid register");
// never write to reg 0, and it can be conditional (movz, movn)
if (storeReg != 0 && conditional) {
state.registers[storeReg] = val;
}
state.pc = state.nextPC;
state.nextPC = state.nextPC + 4;
return outputState();
}
function proofOffset(uint8 proofIndex) internal pure returns (uint256 offset) {
// A proof of 32 bit memory, with 32-byte leaf values, is (32-5)=27 bytes32 entries.
// And the leaf value itself needs to be encoded as well. And proof.offset == 358
offset = 358 + (uint256(proofIndex) * (28*32));
uint256 s = 0;
assembly { s := calldatasize() }
require(s >= (offset + 28*32), "check that there is enough calldata");
return offset;
}
function readMem(uint32 addr, uint8 proofIndex) internal pure returns (uint32 out) {
uint256 offset = proofOffset(proofIndex);
assembly {
if and(addr, 3) { revert(0, 0) } // quick addr alignment check
let leaf := calldataload(offset)
offset := add(offset, 32)
function hashPair(a, b) -> h {
mstore(0, a) // use scratch space slots to hash the two nodes together
mstore(32, b)
h := keccak256(0, 64)
}
let path := shr(5, addr)
let node := leaf // starting from the leaf node, work back up by combining with siblings, to reconstruct the root
for { let i := 0 } lt(i, 27) { i := add(i, 1) } {
let sibling := calldataload(offset)
offset := add(offset, 32)
switch and(shr(i, path), 1)
case 0 { node := hashPair(node, sibling) }
case 1 { node := hashPair(sibling, node) }
}
let memRoot := mload(0x80) // load memRoot, first field of state
if iszero(eq(node, memRoot)) { // verify the root matches
mstore(0, 0x0badf00d)
revert(0, 32)
}
// bits to shift = (32 - 4 - (addr % 32)) * 8
let shamt := shl(3, sub(sub(32, 4), and(addr, 31)))
out := and(shr(shamt, leaf), 0xFFffFFff)
}
return out;
}
// writeMem writes the value by first overwriting the part of the leaf, and then recomputing the memory merkle root.
function writeMem(uint32 addr, uint8 proofIndex, uint32 value) internal pure {
uint256 offset = proofOffset(proofIndex);
assembly {
if and(addr, 3) { revert(0, 0) } // quick addr alignment check
let leaf := calldataload(offset)
let shamt := shl(3, sub(sub(32, 4), and(addr, 31)))
// mask out 4 bytes, and OR in the value
leaf := or(and(leaf, not(shl(shamt, 0xFFffFFff))), shl(shamt, value))
offset := add(offset, 32)
function hashPair(a, b) -> h {
mstore(0, a) // use scratch space slots to hash the two nodes together
mstore(32, b)
h := keccak256(0, 64)
}
let path := shr(5, addr)
let node := leaf // starting from the leaf node, work back up by combining with siblings, to reconstruct the root
for { let i := 0 } lt(i, 27) { i := add(i, 1) } {
let sibling := calldataload(offset)
offset := add(offset, 32)
switch and(shr(i, path), 1)
case 0 { node := hashPair(node, sibling) }
case 1 { node := hashPair(sibling, node) }
}
mstore(0x80, node) // store new memRoot, first field of state
}
}
// will revert if any required input state is missing
function Step(bytes calldata stateData, bytes calldata proof) public returns (bytes32) {
State memory state;
// packed data is ~6 times smaller
assembly {
if iszero(eq(state, 0x80)) { // expected state mem offset check
revert(0,0)
}
if iszero(eq(mload(0x40), mul(32, 48))) { // expected memory check
revert(0,0)
}
if iszero(eq(stateData.offset, 100)) { // 32*3+4=100 expected state data offset
revert(0,0)
}
if iszero(eq(proof.offset, 358)) { // 100+32+226=358 expected proof offset
revert(0,0)
}
function putField(callOffset, memOffset, size) -> callOffsetOut, memOffsetOut {
// calldata is packed, thus starting left-aligned, shift-right to pad and right-align
let w := shr(shl(3, sub(32, size)), calldataload(callOffset))
mstore(memOffset, w)
callOffsetOut := add(callOffset, size)
memOffsetOut := add(memOffset, 32)
}
let c := stateData.offset // calldata offset
let m := 0x80 // mem offset
c, m := putField(c, m, 32) // memRoot
c, m := putField(c, m, 32) // preimageKey
c, m := putField(c, m, 4) // preimageOffset
c, m := putField(c, m, 4) // pc
c, m := putField(c, m, 4) // nextPC
c, m := putField(c, m, 4) // lo
c, m := putField(c, m, 4) // hi
c, m := putField(c, m, 4) // heap
c, m := putField(c, m, 1) // exitCode
c, m := putField(c, m, 1) // exited
c, m := putField(c, m, 8) // step
mstore(m, add(m, 32)) // offset to registers
m := add(m, 32)
for { let i := 0 } lt(i, 32) { i := add(i, 1) } { c, m := putField(c, m, 4) } // registers
}
if(state.exited) { // don't change state once exited
return outputState();
}
state.step += 1;
// instruction fetch
uint32 insn = readMem(state.pc, 0);
uint32 opcode = insn >> 26; // 6-bits
// j-type j/jal
if (opcode == 2 || opcode == 3) {
// TODO(CLI-4136): likely bug in original code: MIPS spec says this should be in the "current" region;
// a 256 MB aligned region (i.e. use top 4 bits of branch delay slot (pc+4))
return handleJump(opcode == 2 ? 0 : 31, SE(insn&0x03FFFFFF, 26) << 2);
}
// register fetch
uint32 rs; // source register 1 value
uint32 rt; // source register 2 / temp value
uint32 rtReg = (insn >> 16) & 0x1F;
// R-type or I-type (stores rt)
rs = state.registers[(insn >> 21) & 0x1F];
uint32 rdReg = rtReg;
if (opcode == 0 || opcode == 0x1c) {
// R-type (stores rd)
rt = state.registers[rtReg];
rdReg = (insn >> 11) & 0x1F;
} else if (opcode < 0x20) {
// rt is SignExtImm
// don't sign extend for andi, ori, xori
if (opcode == 0xC || opcode == 0xD || opcode == 0xe) {
// ZeroExtImm
rt = insn&0xFFFF;
} else {
// SignExtImm
rt = SE(insn&0xFFFF, 16);
}
} else if (opcode >= 0x28 || opcode == 0x22 || opcode == 0x26) {
// store rt value with store
rt = state.registers[rtReg];
// store actual rt with lwl and lwr
rdReg = rtReg;
}
if ((opcode >= 4 && opcode < 8) || opcode == 1) {
return handleBranch(opcode, insn, rtReg, rs);
}
uint32 storeAddr = 0xFF_FF_FF_FF;
// memory fetch (all I-type)
// we do the load for stores also
uint32 mem;
if (opcode >= 0x20) {
// M[R[rs]+SignExtImm]
rs += SE(insn&0xFFFF, 16);
uint32 addr = rs & 0xFFFFFFFC;
mem = readMem(addr, 1);
if (opcode >= 0x28 && opcode != 0x30) {
// store
storeAddr = addr;
// store opcodes don't write back to a register
rdReg = 0;
}
}
// ALU
uint32 val = execute(insn, rs, rt, mem) & 0xffFFffFF; // swr outputs more than 4 bytes without the mask
uint32 func = insn & 0x3f; // 6-bits
if (opcode == 0 && func >= 8 && func < 0x1c) {
if (func == 8 || func == 9) { // jr/jalr
return handleJump(func == 8 ? 0 : rdReg, rs);
}
if (func == 0xa) { // movz
return handleRd(rdReg, rs, rt == 0);
}
if (func == 0xb) { // movn
return handleRd(rdReg, rs, rt != 0);
}
// syscall (can read and write)
if (func == 0xC) {
return handleSyscall();
}
// lo and hi registers
// can write back
if (func >= 0x10 && func < 0x1c) {
return handleHiLo(func, rs, rt, rdReg);
}
}
// stupid sc, write a 1 to rt
if (opcode == 0x38 && rtReg != 0) {
state.registers[rtReg] = 1;
}
// write memory
if (storeAddr != 0xFF_FF_FF_FF) {
writeMem(storeAddr, 1, val);
}
// write back the value to destination register
return handleRd(rdReg, val, true);
}
function execute(uint32 insn, uint32 rs, uint32 rt, uint32 mem) internal pure returns (uint32) {
uint32 opcode = insn >> 26; // 6-bits
uint32 func = insn & 0x3f; // 6-bits
// TODO(CLI-4136): deref the immed into a register
if (opcode < 0x20) {
// transform ArithLogI
// TODO(CLI-4136): replace with table
if (opcode >= 8 && opcode < 0xF) {
if (opcode == 8) { func = 0x20; } // addi
else if (opcode == 9) { func = 0x21; } // addiu
else if (opcode == 0xa) { func = 0x2a; } // slti
else if (opcode == 0xb) { func = 0x2B; } // sltiu
else if (opcode == 0xc) { func = 0x24; } // andi
else if (opcode == 0xd) { func = 0x25; } // ori
else if (opcode == 0xe) { func = 0x26; } // xori
opcode = 0;
}
// 0 is opcode SPECIAL
if (opcode == 0) {
uint32 shamt = (insn >> 6) & 0x1f;
if (func < 0x20) {
if (func >= 0x08) { return rs; // jr/jalr/div + others
// Shift and ShiftV
} else if (func == 0x00) { return rt << shamt; // sll
} else if (func == 0x02) { return rt >> shamt; // srl
} else if (func == 0x03) { return SE(rt >> shamt, 32-shamt); // sra
} else if (func == 0x04) { return rt << (rs&0x1F); // sllv
} else if (func == 0x06) { return rt >> (rs&0x1F); // srlv
} else if (func == 0x07) { return SE(rt >> rs, 32-rs); // srav
}
}
// 0x10-0x13 = mfhi, mthi, mflo, mtlo
// R-type (ArithLog)
if (func == 0x20 || func == 0x21) { return rs+rt; // add or addu
} else if (func == 0x22 || func == 0x23) { return rs-rt; // sub or subu
} else if (func == 0x24) { return rs&rt; // and
} else if (func == 0x25) { return (rs|rt); // or
} else if (func == 0x26) { return (rs^rt); // xor
} else if (func == 0x27) { return ~(rs|rt); // nor
} else if (func == 0x2a) {
return int32(rs)<int32(rt) ? 1 : 0; // slt
} else if (func == 0x2B) {
return rs<rt ? 1 : 0; // sltu
}
} else if (opcode == 0xf) { return rt<<16; // lui
} else if (opcode == 0x1c) { // SPECIAL2
if (func == 2) return uint32(int32(rs)*int32(rt)); // mul
if (func == 0x20 || func == 0x21) { // clo
if (func == 0x20) rs = ~rs;
uint32 i = 0; while (rs&0x80000000 != 0) { i++; rs <<= 1; } return i;
}
}
} else if (opcode < 0x28) {
if (opcode == 0x20) { // lb
return SE((mem >> (24-(rs&3)*8)) & 0xFF, 8);
} else if (opcode == 0x21) { // lh
return SE((mem >> (16-(rs&2)*8)) & 0xFFFF, 16);
} else if (opcode == 0x22) { // lwl
uint32 val = mem << ((rs&3)*8);
uint32 mask = uint32(0xFFFFFFFF) << ((rs&3)*8);
return (rt & ~mask) | val;
} else if (opcode == 0x23) { return mem; // lw
} else if (opcode == 0x24) { // lbu
return (mem >> (24-(rs&3)*8)) & 0xFF;
} else if (opcode == 0x25) { // lhu
return (mem >> (16-(rs&2)*8)) & 0xFFFF;
} else if (opcode == 0x26) { // lwr
uint32 val = mem >> (24-(rs&3)*8);
uint32 mask = uint32(0xFFFFFFFF) >> (24-(rs&3)*8);
return (rt & ~mask) | val;
}
} else if (opcode == 0x28) { // sb
uint32 val = (rt&0xFF) << (24-(rs&3)*8);
uint32 mask = 0xFFFFFFFF ^ uint32(0xFF << (24-(rs&3)*8));
return (mem & mask) | val;
} else if (opcode == 0x29) { // sh
uint32 val = (rt&0xFFFF) << (16-(rs&2)*8);
uint32 mask = 0xFFFFFFFF ^ uint32(0xFFFF << (16-(rs&2)*8));
return (mem & mask) | val;
} else if (opcode == 0x2a) { // swl
uint32 val = rt >> ((rs&3)*8);
uint32 mask = uint32(0xFFFFFFFF) >> ((rs&3)*8);
return (mem & ~mask) | val;
} else if (opcode == 0x2b) { // sw
return rt;
} else if (opcode == 0x2e) { // swr
uint32 val = rt << (24-(rs&3)*8);
uint32 mask = uint32(0xFFFFFFFF) << (24-(rs&3)*8);
return (mem & ~mask) | val;
} else if (opcode == 0x30) { return mem; // ll
} else if (opcode == 0x38) { return rt; // sc
}
revert("invalid instruction");
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
contract PreimageOracle {
mapping(bytes32 => uint256) public preimageLengths;
mapping(bytes32 => mapping(uint256 => bytes32)) public preimageParts;
mapping(bytes32 => mapping(uint256 => bool)) public preimagePartOk;
function readPreimage(bytes32 key, uint256 offset)
external
view
returns (bytes32 dat, uint256 datLen)
{
require(preimagePartOk[key][offset], "preimage must exist");
datLen = 32;
uint256 length = preimageLengths[key];
// add 8 for the length-prefix part
if (offset + 32 >= length + 8) {
datLen = length + 8 - offset;
}
dat = preimageParts[key][offset];
}
// TODO(CLI-4104):
// we need to mix-in the ID of the dispute for local-type keys to avoid collisions,
// and restrict local pre-image insertion to the dispute-managing contract.
// For now we permit anyone to write any pre-image unchecked, to make testing easy.
// This method is DANGEROUS. And NOT FOR PRODUCTION.
function cheat(
uint256 partOffset,
bytes32 key,
bytes32 part,
uint256 size
) external {
preimagePartOk[key][partOffset] = true;
preimageParts[key][partOffset] = part;
preimageLengths[key] = size;
}
// loadKeccak256PreimagePart prepares the pre-image to be read by keccak256 key,
// starting at the given offset, up to 32 bytes (clipped at preimage length, if out of data).
function loadKeccak256PreimagePart(uint256 partOffset, bytes calldata preimage) external {
uint256 size;
bytes32 key;
bytes32 part;
assembly {
// len(sig) + len(partOffset) + len(preimage offset) = 4 + 32 + 32 = 0x44
size := calldataload(0x44)
// revert if part offset >= size+8 (i.e. parts must be within bounds)
if iszero(lt(partOffset, add(size, 8))) {
revert(0, 0)
}
// we leave solidity slots 0x40 and 0x60 untouched,
// and everything after as scratch-memory.
let ptr := 0x80
// put size as big-endian uint64 at start of pre-image
mstore(ptr, shl(192, size))
ptr := add(ptr, 8)
// copy preimage payload into memory so we can hash and read it.
calldatacopy(ptr, preimage.offset, size)
// Note that it includes the 8-byte big-endian uint64 length prefix.
// this will be zero-padded at the end, since memory at end is clean.
part := mload(add(sub(ptr, 8), partOffset))
let h := keccak256(ptr, size) // compute preimage keccak256 hash
// mask out prefix byte, replace with type 2 byte
key := or(and(h, not(shl(248, 0xFF))), shl(248, 2))
}
preimagePartOk[key][partOffset] = true;
preimageParts[key][partOffset] = part;
preimageLengths[key] = size;
}
}
......@@ -219,9 +219,56 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone {
* @inheritdoc IDisputeGame
*/
function resolve() external returns (GameStatus status_) {
// TODO - Resolve the game
status = GameStatus.IN_PROGRESS;
status_ = status;
if (status != GameStatus.IN_PROGRESS) {
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
);
for (uint256 i = leftMostIndex; i < type(uint64).max; ) {
// Fetch the claim at the current index.
ClaimData storage claim = claimData[i];
// Decrement the loop counter; If it underflows, we've reached the root
// claim and can stop searching.
unchecked {
--i;
}
// 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) {
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) {
leftMostTraceIndex = traceIndex;
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) {
status_ = GameStatus.DEFENDER_WINS;
} else {
status_ = GameStatus.CHALLENGER_WINS;
}
// Update the game status
status = status_;
emit Resolved(status_);
}
/**
......
......@@ -268,6 +268,61 @@ contract FaultDisputeGame_Test is DisputeGameFactory_Init {
)
);
}
/**
* @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();
vm.expectRevert(GameNotInProgress.selector);
gameProxy.resolve();
}
/**
* @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))));
GameStatus status = gameProxy.resolve();
assertEq(uint8(status), uint8(GameStatus.CHALLENGER_WINS));
assertEq(uint8(gameProxy.status()), uint8(GameStatus.CHALLENGER_WINS));
}
/**
* @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))));
GameStatus status = gameProxy.resolve();
assertEq(uint8(status), uint8(GameStatus.DEFENDER_WINS));
assertEq(uint8(gameProxy.status()), uint8(GameStatus.DEFENDER_WINS));
}
/**
* @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))));
gameProxy.defend(1, Claim.wrap(bytes32(uint256(6))));
gameProxy.defend(1, Claim.wrap(bytes32(uint256(7))));
GameStatus status = gameProxy.resolve();
assertEq(uint8(status), uint8(GameStatus.CHALLENGER_WINS));
assertEq(uint8(gameProxy.status()), uint8(GameStatus.CHALLENGER_WINS));
}
}
/**
......
pragma solidity 0.8.15;
import { StdUtils } from "forge-std/Test.sol";
import { Vm } from "forge-std/Vm.sol";
import { OptimismPortal } from "../../L1/OptimismPortal.sol";
import { L2OutputOracle } from "../../L1/L2OutputOracle.sol";
import { AddressAliasHelper } from "../../vendor/AddressAliasHelper.sol";
import { SystemConfig } from "../../L1/SystemConfig.sol";
import { ResourceMetering } from "../../L1/ResourceMetering.sol";
import { Constants } from "../../libraries/Constants.sol";
import { Portal_Initializer } from "../CommonTest.t.sol";
import { Types } from "../../libraries/Types.sol";
contract OptimismPortal_Depositor is StdUtils, ResourceMetering {
Vm internal vm;
OptimismPortal internal portal;
bool public failedToComplete;
constructor(Vm _vm, OptimismPortal _portal) {
vm = _vm;
portal = _portal;
initialize();
}
function initialize() internal initializer {
__ResourceMetering_init();
}
function resourceConfig() public pure returns (ResourceMetering.ResourceConfig memory) {
return _resourceConfig();
}
function _resourceConfig()
internal
pure
override
returns (ResourceMetering.ResourceConfig memory)
{
ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();
return rcfg;
}
// A test intended to identify any unexpected halting conditions
function depositTransactionCompletes(
address _to,
uint256 _value,
uint64 _gasLimit,
bool _isCreation,
bytes memory _data
) public payable {
vm.assume((!_isCreation || _to == address(0)) && _data.length <= 120_000);
uint256 preDepositvalue = bound(_value, 0, type(uint128).max);
// Give the depositor some ether
vm.deal(address(this), preDepositvalue);
// cache the contract's eth balance
uint256 preDepositBalance = address(this).balance;
uint256 value = bound(preDepositvalue, 0, preDepositBalance);
(, uint64 cachedPrevBoughtGas, ) = ResourceMetering(address(portal)).params();
ResourceMetering.ResourceConfig memory rcfg = resourceConfig();
uint256 maxResourceLimit = uint64(rcfg.maxResourceLimit);
uint64 gasLimit = uint64(
bound(
_gasLimit,
portal.minimumGasLimit(uint64(_data.length)),
maxResourceLimit - cachedPrevBoughtGas
)
);
try portal.depositTransaction{ value: value }(_to, value, gasLimit, _isCreation, _data) {
// Do nothing; Call succeeded
} catch {
failedToComplete = true;
}
}
}
contract OptimismPortal_Invariant_Harness is Portal_Initializer {
// Reusable default values for a test withdrawal
Types.WithdrawalTransaction _defaultTx;
......@@ -57,6 +132,34 @@ contract OptimismPortal_Invariant_Harness is Portal_Initializer {
}
}
contract OptimismPortal_Deposit_Invariant is Portal_Initializer {
OptimismPortal_Depositor internal actor;
function setUp() public override {
super.setUp();
// Create a deposit actor.
actor = new OptimismPortal_Depositor(vm, op);
targetContract(address(actor));
bytes4[] memory selectors = new bytes4[](1);
selectors[0] = actor.depositTransactionCompletes.selector;
FuzzSelector memory selector = FuzzSelector({ addr: address(actor), selectors: selectors });
targetSelector(selector);
}
/**
* @custom:invariant Deposits of any value should always succeed unless
* `_to` = `address(0)` or `_isCreation` = `true`.
*
* All deposits, barring creation transactions and transactions sent to `address(0)`,
* should always succeed.
*/
function invariant_deposit_completes() external {
assertEq(actor.failedToComplete(), false);
}
}
contract OptimismPortal_CannotTimeTravel is OptimismPortal_Invariant_Harness {
function setUp() public override {
super.setUp();
......
# `OptimismPortal` Invariants
## Deposits of any value should always succeed unless `_to` = `address(0)` or `_isCreation` = `true`.
**Test:** [`OptimismPortal.t.sol#L158`](../contracts/test/invariants/OptimismPortal.t.sol#L158)
All deposits, barring creation transactions and transactions sent to `address(0)`, should always succeed.
## `finalizeWithdrawalTransaction` should revert if the finalization period has not elapsed.
**Test:** [`OptimismPortal.t.sol#L85`](../contracts/test/invariants/OptimismPortal.t.sol#L85)
**Test:** [`OptimismPortal.t.sol#L188`](../contracts/test/invariants/OptimismPortal.t.sol#L188)
A withdrawal that has been proven should not be able to be finalized until after the finalization period has elapsed.
## `finalizeWithdrawalTransaction` should revert if the withdrawal has already been finalized.
**Test:** [`OptimismPortal.t.sol#L122`](../contracts/test/invariants/OptimismPortal.t.sol#L122)
**Test:** [`OptimismPortal.t.sol#L225`](../contracts/test/invariants/OptimismPortal.t.sol#L225)
Ensures that there is no chain of calls that can be made that allows a withdrawal to be finalized twice.
## A withdrawal should **always** be able to be finalized `FINALIZATION_PERIOD_SECONDS` after it was successfully proven.
**Test:** [`OptimismPortal.t.sol#L157`](../contracts/test/invariants/OptimismPortal.t.sol#L157)
**Test:** [`OptimismPortal.t.sol#L260`](../contracts/test/invariants/OptimismPortal.t.sol#L260)
This invariant asserts that there is no chain of calls that can be made that will prevent a withdrawal from being finalized exactly `FINALIZATION_PERIOD_SECONDS` after it was successfully proven.
......
{
"name": "@eth-optimism/contracts-bedrock",
"version": "0.14.0",
"version": "0.15.0",
"description": "Contracts for Optimism Specs",
"main": "dist/index",
"types": "dist/index",
......@@ -53,7 +53,7 @@
"echidna:metering": "echidna-test --contract EchidnaFuzzResourceMetering --config ./echidna.yaml ."
},
"dependencies": {
"@eth-optimism/core-utils": "^0.12.0",
"@eth-optimism/core-utils": "^0.12.1",
"@openzeppelin/contracts": "4.7.3",
"@openzeppelin/contracts-upgradeable": "4.7.3",
"ethers": "^5.7.0"
......
......@@ -10,6 +10,6 @@
"hardhat_ignore_compile": false,
"disable_color": false,
"exclude_dependencies": true,
"filter_paths": "contracts/test,contracts/vendor,contracts/echidna,node_modules",
"filter_paths": "contracts/test,contracts/vendor,contracts/echidna,node_modules,contracts/cannon/MIPS.sol",
"foundry_out_directory": "artifacts"
}
......@@ -53,8 +53,8 @@
"url": "https://github.com/ethereum-optimism/optimism.git"
},
"devDependencies": {
"@eth-optimism/contracts-bedrock": "0.14.0",
"@eth-optimism/core-utils": "^0.12.0",
"@eth-optimism/contracts-bedrock": "0.15.0",
"@eth-optimism/core-utils": "^0.12.1",
"@eth-optimism/hardhat-deploy-config": "^0.2.6",
"@ethersproject/hardware-wallets": "^5.7.0",
"@nomiclabs/hardhat-ethers": "^2.0.2",
......
# @eth-optimism/core-utils
## 0.12.1
### Patch Changes
- 8d7dcc70c: Delete legacy core-utils
- d6388be4a: Added a new service wallet-mon to identify unexpected transfers from key accounts
## 0.12.0
### Minor Changes
......
{
"name": "@eth-optimism/core-utils",
"version": "0.12.0",
"version": "0.12.1",
"description": "[Optimism] Core typescript utilities",
"main": "dist/index",
"types": "dist/index",
......
declare module 'bufio' {
class BufferWriter {
public offset: number
constructor()
render(): Buffer
getSize(): number
seek(offset: number): this
destroy(): this
writeU8(n: number): this
writeU16(n: number): this
writeU16BE(n: number): this
writeU24(n: number): this
writeU24BE(n: number): this
writeU32(n: number): this
writeU32BE(n: number): this
writeU40(n: number): this
writeU40BE(n: number): this
writeU48(n: number): this
writeU48BE(n: number): this
writeU56(n: number): this
writeU56BE(n: number): this
writeU64(n: number): this
writeU64BE(n: number): this
writeBytes(b: Buffer): this
copy(value: number, start: number, end: number): this
}
class BufferReader {
constructor(data: Buffer, copy?: boolean)
getSize(): number
check(n: number): void
left(): number
seek(offset: number): this
start(): number
end(): number
destroy(): this
readU8(): number
readU16(): number
readU16BE(): number
readU24(): number
readU24BE(): number
readU32(): number
readU32BE(): number
readU40(): number
readU40BE(): number
readU48(): number
readU48BE(): number
readU56(): number
readU56BE(): number
readU64(): number
readU64BE(): number
readBytes(size: number, copy?: boolean): Buffer
}
class Struct {
constructor()
encode(extra?: object): Buffer
decode<T extends Struct>(data: Buffer, extra?: object): T
getSize(extra?: object): number
fromHex(s: string, extra?: object): this
toHex(): string
write(bw: BufferWriter, extra?: object): BufferWriter
read(br: BufferReader, extra?: object): this
static read<T extends Struct>(br: BufferReader, extra?: object): T
static decode<T extends Struct>(data: Buffer, extra?: object): T
static fromHex<T extends Struct>(s: string, extra?: object): T
}
}
# @eth-optimism/fault-detector
## 1.0.0
### Major Changes
- 119754c2f: Make optimism/sdk default to bedrock mode
### Patch Changes
- 16ccbee24: Fix false error to warning
- 685addec2: Add better source maps and developer support
- Updated dependencies [8d7dcc70c]
- Updated dependencies [119754c2f]
- Updated dependencies [d6388be4a]
- @eth-optimism/core-utils@0.12.1
- @eth-optimism/sdk@3.0.0
- @eth-optimism/common-ts@0.8.2
## 0.6.4
### Patch Changes
......
{
"private": true,
"name": "@eth-optimism/fault-detector",
"version": "0.6.4",
"version": "1.0.0",
"description": "[Optimism] Service for detecting faulty L2 output proposals",
"main": "dist/index",
"types": "dist/index",
......@@ -50,10 +50,10 @@
"tsx": "^3.12.7"
},
"dependencies": {
"@eth-optimism/common-ts": "^0.8.1",
"@eth-optimism/common-ts": "^0.8.2",
"@eth-optimism/contracts": "^0.6.0",
"@eth-optimism/core-utils": "^0.12.0",
"@eth-optimism/sdk": "^2.1.0",
"@eth-optimism/core-utils": "^0.12.1",
"@eth-optimism/sdk": "^3.0.0",
"@ethersproject/abstract-provider": "^5.7.0"
}
}
# @eth-optimism/replica-healthcheck
## 1.2.5
### Patch Changes
- Updated dependencies [8d7dcc70c]
- Updated dependencies [d6388be4a]
- @eth-optimism/core-utils@0.12.1
- @eth-optimism/common-ts@0.8.2
## 1.2.4
### Patch Changes
......
{
"private": true,
"name": "@eth-optimism/replica-healthcheck",
"version": "1.2.4",
"version": "1.2.5",
"description": "[Optimism] Service for monitoring the health of replica nodes",
"main": "dist/index",
"types": "dist/index",
......@@ -32,8 +32,8 @@
"url": "https://github.com/ethereum-optimism/optimism.git"
},
"dependencies": {
"@eth-optimism/common-ts": "0.8.1",
"@eth-optimism/core-utils": "0.12.0",
"@eth-optimism/common-ts": "0.8.2",
"@eth-optimism/core-utils": "0.12.1",
"@ethersproject/abstract-provider": "^5.7.0"
},
"devDependencies": {
......
# @eth-optimism/sdk
## 3.0.0
### Major Changes
- 119754c2f: Make optimism/sdk default to bedrock mode
### Patch Changes
- Updated dependencies [8d7dcc70c]
- Updated dependencies [d6388be4a]
- Updated dependencies [af292562f]
- @eth-optimism/core-utils@0.12.1
- @eth-optimism/contracts-bedrock@0.15.0
## 2.1.0
### Minor Changes
......
{
"name": "@eth-optimism/sdk",
"version": "2.1.0",
"version": "3.0.0",
"description": "[Optimism] Tools for working with Optimism",
"main": "dist/index",
"types": "dist/index",
......@@ -55,8 +55,8 @@
},
"dependencies": {
"@eth-optimism/contracts": "0.6.0",
"@eth-optimism/core-utils": "0.12.0",
"@eth-optimism/contracts-bedrock": "0.14.0",
"@eth-optimism/core-utils": "0.12.1",
"@eth-optimism/contracts-bedrock": "0.15.0",
"lodash": "^4.17.21",
"merkletreejs": "^0.2.27",
"rlp": "^2.2.7"
......
......@@ -778,6 +778,28 @@
"@ethersproject/abstract-provider" "^5.7.0"
"@ethersproject/abstract-signer" "^5.7.0"
"@eth-optimism/core-utils@0.12.0":
version "0.12.0"
resolved "https://registry.yarnpkg.com/@eth-optimism/core-utils/-/core-utils-0.12.0.tgz#6337e4599a34de23f8eceb20378de2a2de82b0ea"
integrity sha512-qW+7LZYCz7i8dRa7SRlUKIo1VBU8lvN0HeXCxJR+z+xtMzMQpPds20XJNCMclszxYQHkXY00fOT6GvFw9ZL6nw==
dependencies:
"@ethersproject/abi" "^5.7.0"
"@ethersproject/abstract-provider" "^5.7.0"
"@ethersproject/address" "^5.7.0"
"@ethersproject/bignumber" "^5.7.0"
"@ethersproject/bytes" "^5.7.0"
"@ethersproject/constants" "^5.7.0"
"@ethersproject/contracts" "^5.7.0"
"@ethersproject/hash" "^5.7.0"
"@ethersproject/keccak256" "^5.7.0"
"@ethersproject/properties" "^5.7.0"
"@ethersproject/providers" "^5.7.0"
"@ethersproject/rlp" "^5.7.0"
"@ethersproject/transactions" "^5.7.0"
"@ethersproject/web" "^5.7.0"
bufio "^1.0.7"
chai "^4.3.4"
"@ethereum-waffle/chai@^3.4.0":
version "3.4.0"
resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.0.tgz#2477877410a96bf370edd64df905b04fb9aba9d5"
......@@ -1692,6 +1714,32 @@
bech32 "1.1.4"
ws "7.4.6"
"@ethersproject/providers@^5.7.0":
version "5.7.2"
resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb"
integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==
dependencies:
"@ethersproject/abstract-provider" "^5.7.0"
"@ethersproject/abstract-signer" "^5.7.0"
"@ethersproject/address" "^5.7.0"
"@ethersproject/base64" "^5.7.0"
"@ethersproject/basex" "^5.7.0"
"@ethersproject/bignumber" "^5.7.0"
"@ethersproject/bytes" "^5.7.0"
"@ethersproject/constants" "^5.7.0"
"@ethersproject/hash" "^5.7.0"
"@ethersproject/logger" "^5.7.0"
"@ethersproject/networks" "^5.7.0"
"@ethersproject/properties" "^5.7.0"
"@ethersproject/random" "^5.7.0"
"@ethersproject/rlp" "^5.7.0"
"@ethersproject/sha2" "^5.7.0"
"@ethersproject/strings" "^5.7.0"
"@ethersproject/transactions" "^5.7.0"
"@ethersproject/web" "^5.7.0"
bech32 "1.1.4"
ws "7.4.6"
"@ethersproject/random@5.4.0", "@ethersproject/random@^5.4.0":
version "5.4.0"
resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.4.0.tgz#9cdde60e160d024be39cc16f8de3b9ce39191e16"
......@@ -5683,6 +5731,11 @@ bufferutil@^4.0.1:
dependencies:
node-gyp-build "^4.2.0"
bufio@^1.0.7:
version "1.2.0"
resolved "https://registry.yarnpkg.com/bufio/-/bufio-1.2.0.tgz#b9ad1c06b0d9010363c387c39d2810a7086d143f"
integrity sha512-UlFk8z/PwdhYQTXSQQagwGAdtRI83gib2n4uy4rQnenxUM2yQi8lBDzF230BNk+3wAoZDxYRoBwVVUPgHa9MCA==
builtin-modules@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment