diff --git a/.circleci/config.yml b/.circleci/config.yml index c27a554ffd6d..7f942f95292c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -222,7 +222,7 @@ jobs: condition: <> steps: - notify-failures-on-develop: - mentions: "@proofs-squad" + mentions: "@proofs-team" cannon-build-test-vectors: docker: @@ -721,6 +721,8 @@ jobs: command: interfaces-check-no-build - run-contracts-check: command: size-check + - run-contracts-check: + command: unused-imports-check-no-build contracts-bedrock-validate-spacers: docker: @@ -1142,7 +1144,7 @@ jobs: exit 1 fi - notify-failures-on-develop: - mentions: "@proofs-squad" + mentions: "@proofs-team" cannon-stf-verify: docker: @@ -1269,7 +1271,7 @@ jobs: make verify-sepolia working_directory: op-program - notify-failures-on-develop: - mentions: "@proofs-squad" + mentions: "@proofs-team" op-program-compat: docker: @@ -1367,7 +1369,7 @@ jobs: name: Build contracts environment: FOUNDRY_PROFILE: ci - command: just build + command: just forge-build working_directory: packages/contracts-bedrock - run: name: Publish artifacts @@ -1420,7 +1422,7 @@ workflows: - semgrep-scan - semgrep-scan: name: semgrep-scan-local - scan_command: semgrep scan --timeout=100 --config=./.semgrep --strict --error . + scan_command: semgrep scan --timeout=100 --config=./.semgrep --error . - go-lint: requires: - go-mod-download @@ -1726,7 +1728,7 @@ workflows: target: test-cannon parallelism: 8 notify: true - mentions: "@proofs-squad" + mentions: "@proofs-team" requires: - contracts-bedrock-build - cannon-prestate diff --git a/.semgrep/sol-rules.yaml b/.semgrep/sol-rules.yaml index fd4f154dd3e2..167b010dd8eb 100644 --- a/.semgrep/sol-rules.yaml +++ b/.semgrep/sol-rules.yaml @@ -2,14 +2,14 @@ rules: - id: sol-safety-deployutils-args languages: [solidity] severity: ERROR - pattern-regex: DeployUtils\.(create1|create2|create1AndSave|create2AndSave)\s*\(\s*\{[^}]*?_args\s*:\s*(?!\s*DeployUtils\.encodeConstructor\()\s*[^}]*?\}\s*\) message: _args parameter should be wrapped with DeployUtils.encodeConstructor + pattern-regex: DeployUtils\.(create1|create2|create1AndSave|create2AndSave)\s*\(\s*\{[^}]*?_args\s*:\s*(?!\s*DeployUtils\.encodeConstructor\()\s*[^}]*?\}\s*\) - id: sol-style-input-arg-fmt languages: [solidity] severity: ERROR - pattern-regex: function\s+\w+\s*\(\s*([^)]*?\b\w+\s+(?!_)(?!memory\b)(?!calldata\b)(?!storage\b)(?!payable\b)\w+\s*(?=,|\))) message: Named inputs to functions must be prepended with an underscore + pattern-regex: function\s+\w+\s*\(\s*([^)]*?\b\w+\s+(?!_)(?!memory\b)(?!calldata\b)(?!storage\b)(?!payable\b)\w+\s*(?=,|\))) paths: exclude: - op-chain-ops/script/testdata/scripts/ScriptExample.s.sol @@ -25,8 +25,8 @@ rules: - id: sol-style-return-arg-fmt languages: [solidity] severity: ERROR - pattern-regex: returns\s*(\w+\s*)?\(\s*([^)]*?\b\w+\s+(?!memory\b)(?!calldata\b)(?!storage\b)(?!payable\b)\w+(? **Table of Contents** +- [devnet with eigenda alt-da](#devnet-with-eigenda-alt-da) - [What is Optimism?](#what-is-optimism) - [Documentation](#documentation) - [Specification](#specification) @@ -26,6 +27,32 @@ +## devnet with eigenda alt-da + +First you will need to build the dev docker image for eigenda-proxy, until we make a new release. + +```bash +git clone https://github.com/Layr-Labs/eigenda-proxy.git +make docker-build +``` + +Now create a `.env` file in the root of this repository with the following content (you will need to add an ecdsa private key that is authorized on the eigenda disperser, as well as an ethereum rpc endpoint): + +```bash +MEMSTORE_ENABLED=false +EIGENDA_PROXY_EIGENDA_SERVICE_MANAGER_ADDR=0x54A03db2784E3D0aCC08344D05385d0b62d4F432 #holesky preprod +EIGENDA_PROXY_EIGENDA_SIGNER_PRIVATE_KEY_HEX= +EIGENDA_PROXY_EIGENDA_ETH_RPC= +``` + +Finally run `make altda-devnet-up` to start the devnet with the eigenda proxy as alt-da server, which sends batches to `disperser-preprod-holesky.eigenda.xyz:443`. + +This will also start a grafana instance, which you can access at `http://localhost:3000` with user:pw `admin:admin`. + +![](./ops-bedrock/monitoring/grafana/grafana-dashboard-overview-high-throughput.png) + +The devnet starts an instance of https://github.com/Layr-Labs/evm-tx-load-gen which is submitting transactions with large amounts of calldata to reach 1.5MB/s of throughput. + ## What is Optimism? [Optimism](https://www.optimism.io/) is a project dedicated to scaling Ethereum's technology and expanding its ability to coordinate people from across the world to build effective decentralized economies and governance systems. The [Optimism Collective](https://www.optimism.io/vision) builds open-source software that powers scalable blockchains and aims to address key governance and economic challenges in the wider Ethereum ecosystem. Optimism operates on the principle of **impact=profit**, the idea that individuals who positively impact the Collective should be proportionally rewarded with profit. **Change the incentives and you change the world.** diff --git a/bedrock-devnet/devnet/__init__.py b/bedrock-devnet/devnet/__init__.py index 8a3fb0ee4c99..3ed706342c0d 100644 --- a/bedrock-devnet/devnet/__init__.py +++ b/bedrock-devnet/devnet/__init__.py @@ -31,6 +31,7 @@ DEVNET_L2OO = os.getenv('DEVNET_L2OO') == "true" DEVNET_ALTDA = os.getenv('DEVNET_ALTDA') == "true" GENERIC_ALTDA = os.getenv('GENERIC_ALTDA') == "true" +TRAFFIC_GEN = os.getenv('TRAFFIC_GEN') == "true" class Bunch: def __init__(self, **kwds): @@ -173,6 +174,12 @@ def devnet_l2_allocs(paths): # Bring up the devnet where the contracts are deployed to L1 def devnet_deploy(paths): + + log.info('Starting peripheral telemetry services.') + run_command(['docker', 'compose', 'up', '-d', 'prometheus', 'grafana', 'loki', 'promtail', 'ethereum-metrics-exporter-l2'], cwd=paths.ops_bedrock_dir, env={ + 'PWD': paths.ops_bedrock_dir + }) + if os.path.exists(paths.genesis_l1_path): log.info('L1 genesis already generated.') else: @@ -247,11 +254,7 @@ def devnet_deploy(paths): wait_for_rpc_server('127.0.0.1:9545') # Print out the addresses being used for easier debugging. - l2_output_oracle = addresses['L2OutputOracleProxy'] - dispute_game_factory = addresses['DisputeGameFactoryProxy'] batch_inbox_address = rollup_config['batch_inbox_address'] - log.info(f'Using L2OutputOracle {l2_output_oracle}') - log.info(f'Using DisputeGameFactory {dispute_game_factory}') log.info(f'Using batch inbox {batch_inbox_address}') # Set up the base docker environment. @@ -264,7 +267,11 @@ def devnet_deploy(paths): # Must be done selectively because op-proposer throws if both are set. if DEVNET_L2OO: docker_env['L2OO_ADDRESS'] = l2_output_oracle + l2_output_oracle = addresses['L2OutputOracleProxy'] + log.info(f'Using L2OutputOracle {l2_output_oracle}') else: + dispute_game_factory = addresses['DisputeGameFactoryProxy'] + log.info(f'Using DisputeGameFactory {dispute_game_factory}') docker_env['DGF_ADDRESS'] = dispute_game_factory docker_env['DG_TYPE'] = '254' docker_env['PROPOSAL_INTERVAL'] = '12s' @@ -287,6 +294,11 @@ def devnet_deploy(paths): log.info('Bringing up `op-node`, `op-proposer` and `op-batcher`.') run_command(['docker', 'compose', 'up', '-d', 'op-node', 'op-proposer', 'op-batcher', 'artifact-server'], cwd=paths.ops_bedrock_dir, env=docker_env) + # Optionally bring up traffic-gen. + if TRAFFIC_GEN: + log.info('Bringing up `evm-tx-load-gen`.') + run_command(['docker', 'compose', 'up', '-d', 'evm-tx-load-gen'], cwd=paths.ops_bedrock_dir, env=docker_env) + # Optionally bring up op-challenger. if not DEVNET_L2OO: log.info('Bringing up `op-challenger`.') @@ -294,8 +306,8 @@ def devnet_deploy(paths): # Optionally bring up Alt-DA Mode components. if DEVNET_ALTDA: - log.info('Bringing up `da-server`, `sentinel`.') # TODO(10141): We don't have public sentinel images yet - run_command(['docker', 'compose', 'up', '-d', 'da-server'], cwd=paths.ops_bedrock_dir, env=docker_env) + log.info('Bringing up `da-server`, `redis-cache`.') # TODO(10141): We don't have public sentinel images yet + run_command(['docker', 'compose', 'up', '-d', 'da-server', 'redis-cache'], cwd=paths.ops_bedrock_dir, env=docker_env) # Fin. log.info('Devnet ready.') diff --git a/cannon/README.md b/cannon/README.md index a3b917193901..be1615b45f8a 100644 --- a/cannon/README.md +++ b/cannon/README.md @@ -29,8 +29,8 @@ cd ../cannon make cannon # Transform MIPS op-program client binary into first VM state. -# This outputs state.json (VM state) and meta.json (for debug symbols). -./bin/cannon load-elf --type singlethreaded --path=../op-program/bin/op-program-client.elf +# This outputs state.bin.gz (VM state) and meta.json (for debug symbols). +./bin/cannon load-elf --type singlethreaded-2 --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 --), @@ -45,7 +45,7 @@ make cannon --proof-at '=' \ --stop-at '=' \ --snapshot-at '%1000000000' \ - --input ./state.json \ + --input ./state.bin.gz \ -- \ ../op-program/bin/op-program \ --network op-mainnet \ diff --git a/cannon/cmd/load_elf.go b/cannon/cmd/load_elf.go index a844dd09c101..c76ebbe8f7cb 100644 --- a/cannon/cmd/load_elf.go +++ b/cannon/cmd/load_elf.go @@ -32,7 +32,7 @@ var ( LoadELFOutFlag = &cli.PathFlag{ Name: "out", Usage: "Output path to write state to. State is dumped to stdout if set to '-'. Not written if empty. Use file extension '.bin', '.bin.gz', or '.json' for binary, compressed binary, or JSON formats.", - Value: "state.json", + Value: "state.bin.gz", Required: false, } LoadELFMetaFlag = &cli.PathFlag{ diff --git a/cannon/mipsevm/multithreaded/state.go b/cannon/mipsevm/multithreaded/state.go index 0de74bdea330..a8a28367408c 100644 --- a/cannon/mipsevm/multithreaded/state.go +++ b/cannon/mipsevm/multithreaded/state.go @@ -234,7 +234,6 @@ func (s *State) EncodeThreadProof() []byte { out := make([]byte, 0, THREAD_WITNESS_SIZE) out = append(out, threadBytes[:]...) out = append(out, otherThreadsWitness[:]...) - return out } diff --git a/cannon/mipsevm/tests/evm_common_test.go b/cannon/mipsevm/tests/evm_common_test.go index 473e2041d5b9..0adb8d386e96 100644 --- a/cannon/mipsevm/tests/evm_common_test.go +++ b/cannon/mipsevm/tests/evm_common_test.go @@ -29,8 +29,8 @@ func TestEVM(t *testing.T) { cases := GetMipsVersionTestCases(t) skippedTests := map[string][]string{ - "multi-threaded": []string{"clone.bin"}, - "single-threaded": []string{}, + "multi-threaded": {"clone.bin"}, + "single-threaded": {}, } for _, c := range cases { @@ -248,31 +248,31 @@ func TestEVMSingleStep_LoadStore(t *testing.T) { versions := GetMipsVersionTestCases(t) cases := []struct { name string - rs uint32 - rt uint32 + rs Word + rt Word isUnAligned bool opcode uint32 - memVal uint32 - expectMemVal uint32 - expectRes uint32 + memVal Word + expectMemVal Word + expectRes Word }{ - {name: "lb", opcode: uint32(0x20), memVal: uint32(0x12_00_00_00), expectRes: uint32(0x12)}, // lb $t0, 4($t1) - {name: "lh", opcode: uint32(0x21), memVal: uint32(0x12_23_00_00), expectRes: uint32(0x12_23)}, // lh $t0, 4($t1) - {name: "lw", opcode: uint32(0x23), memVal: uint32(0x12_23_45_67), expectRes: uint32(0x12_23_45_67)}, // lw $t0, 4($t1) - {name: "lbu", opcode: uint32(0x24), memVal: uint32(0x12_23_00_00), expectRes: uint32(0x12)}, // lbu $t0, 4($t1) - {name: "lhu", opcode: uint32(0x25), memVal: uint32(0x12_23_00_00), expectRes: uint32(0x12_23)}, // lhu $t0, 4($t1) - {name: "lwl", opcode: uint32(0x22), rt: uint32(0xaa_bb_cc_dd), memVal: uint32(0x12_34_56_78), expectRes: uint32(0x12_34_56_78)}, // lwl $t0, 4($t1) - {name: "lwl unaligned address", opcode: uint32(0x22), rt: uint32(0xaa_bb_cc_dd), isUnAligned: true, memVal: uint32(0x12_34_56_78), expectRes: uint32(0x34_56_78_dd)}, // lwl $t0, 5($t1) - {name: "lwr", opcode: uint32(0x26), rt: uint32(0xaa_bb_cc_dd), memVal: uint32(0x12_34_56_78), expectRes: uint32(0xaa_bb_cc_12)}, // lwr $t0, 4($t1) - {name: "lwr unaligned address", opcode: uint32(0x26), rt: uint32(0xaa_bb_cc_dd), isUnAligned: true, memVal: uint32(0x12_34_56_78), expectRes: uint32(0xaa_bb_12_34)}, // lwr $t0, 5($t1) - {name: "sb", opcode: uint32(0x28), rt: uint32(0xaa_bb_cc_dd), expectMemVal: uint32(0xdd_00_00_00)}, // sb $t0, 4($t1) - {name: "sh", opcode: uint32(0x29), rt: uint32(0xaa_bb_cc_dd), expectMemVal: uint32(0xcc_dd_00_00)}, // sh $t0, 4($t1) - {name: "swl", opcode: uint32(0x2a), rt: uint32(0xaa_bb_cc_dd), expectMemVal: uint32(0xaa_bb_cc_dd)}, // swl $t0, 4($t1) - {name: "sw", opcode: uint32(0x2b), rt: uint32(0xaa_bb_cc_dd), expectMemVal: uint32(0xaa_bb_cc_dd)}, // sw $t0, 4($t1) - {name: "swr unaligned address", opcode: uint32(0x2e), rt: uint32(0xaa_bb_cc_dd), isUnAligned: true, expectMemVal: uint32(0xcc_dd_00_00)}, // swr $t0, 5($t1) + {name: "lb", opcode: uint32(0x20), memVal: Word(0x12_00_00_00), expectRes: Word(0x12)}, // lb $t0, 4($t1) + {name: "lh", opcode: uint32(0x21), memVal: Word(0x12_23_00_00), expectRes: Word(0x12_23)}, // lh $t0, 4($t1) + {name: "lw", opcode: uint32(0x23), memVal: Word(0x12_23_45_67), expectRes: Word(0x12_23_45_67)}, // lw $t0, 4($t1) + {name: "lbu", opcode: uint32(0x24), memVal: Word(0x12_23_00_00), expectRes: Word(0x12)}, // lbu $t0, 4($t1) + {name: "lhu", opcode: uint32(0x25), memVal: Word(0x12_23_00_00), expectRes: Word(0x12_23)}, // lhu $t0, 4($t1) + {name: "lwl", opcode: uint32(0x22), rt: Word(0xaa_bb_cc_dd), memVal: Word(0x12_34_56_78), expectRes: Word(0x12_34_56_78)}, // lwl $t0, 4($t1) + {name: "lwl unaligned address", opcode: uint32(0x22), rt: Word(0xaa_bb_cc_dd), isUnAligned: true, memVal: Word(0x12_34_56_78), expectRes: Word(0x34_56_78_dd)}, // lwl $t0, 5($t1) + {name: "lwr", opcode: uint32(0x26), rt: Word(0xaa_bb_cc_dd), memVal: Word(0x12_34_56_78), expectRes: Word(0xaa_bb_cc_12)}, // lwr $t0, 4($t1) + {name: "lwr unaligned address", opcode: uint32(0x26), rt: Word(0xaa_bb_cc_dd), isUnAligned: true, memVal: Word(0x12_34_56_78), expectRes: Word(0xaa_bb_12_34)}, // lwr $t0, 5($t1) + {name: "sb", opcode: uint32(0x28), rt: Word(0xaa_bb_cc_dd), expectMemVal: Word(0xdd_00_00_00)}, // sb $t0, 4($t1) + {name: "sh", opcode: uint32(0x29), rt: Word(0xaa_bb_cc_dd), expectMemVal: Word(0xcc_dd_00_00)}, // sh $t0, 4($t1) + {name: "swl", opcode: uint32(0x2a), rt: Word(0xaa_bb_cc_dd), expectMemVal: Word(0xaa_bb_cc_dd)}, // swl $t0, 4($t1) + {name: "sw", opcode: uint32(0x2b), rt: Word(0xaa_bb_cc_dd), expectMemVal: Word(0xaa_bb_cc_dd)}, // sw $t0, 4($t1) + {name: "swr unaligned address", opcode: uint32(0x2e), rt: Word(0xaa_bb_cc_dd), isUnAligned: true, expectMemVal: Word(0xcc_dd_00_00)}, // swr $t0, 5($t1) } - var t1 uint32 = 0x100 + var t1 Word = 0x100 var baseReg uint32 = 9 var rtReg uint32 = 8 for _, v := range versions { @@ -292,7 +292,7 @@ func TestEVMSingleStep_LoadStore(t *testing.T) { state.GetRegistersRef()[baseReg] = t1 state.GetMemory().SetUint32(0, insn) - state.GetMemory().SetUint32(t1+4, tt.memVal) + state.GetMemory().SetWord(t1+4, tt.memVal) step := state.GetStep() // Setup expectations @@ -300,7 +300,7 @@ func TestEVMSingleStep_LoadStore(t *testing.T) { expected.ExpectStep() if tt.expectMemVal != 0 { - expected.ExpectMemoryWrite(t1+4, tt.expectMemVal) + expected.ExpectMemoryWriteWord(t1+4, tt.expectMemVal) } else { expected.Registers[rtReg] = tt.expectRes } @@ -315,6 +315,69 @@ func TestEVMSingleStep_LoadStore(t *testing.T) { } } +func TestEVMSingleStep_MovzMovn(t *testing.T) { + var tracer *tracing.Hooks + versions := GetMipsVersionTestCases(t) + cases := []struct { + name string + funct uint32 + }{ + {name: "movz", funct: uint32(0xa)}, + {name: "movn", funct: uint32(0xb)}, + } + for _, v := range versions { + for i, tt := range cases { + testName := fmt.Sprintf("%v (%v)", tt.name, v.Name) + t.Run(testName, func(t *testing.T) { + goVm := v.VMFactory(nil, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithRandomization(int64(i)), testutil.WithPC(0), testutil.WithNextPC(4)) + state := goVm.GetState() + rsReg := uint32(9) + rtReg := uint32(10) + rdReg := uint32(8) + insn := rsReg<<21 | rtReg<<16 | rdReg<<11 | tt.funct + var t2 Word + if tt.funct == 0xa { + t2 = 0x0 + } else { + t2 = 0x1 + } + state.GetRegistersRef()[rtReg] = t2 + state.GetRegistersRef()[rsReg] = Word(0xb) + state.GetRegistersRef()[rdReg] = Word(0xa) + state.GetMemory().SetUint32(0, insn) + step := state.GetStep() + // Setup expectations + expected := testutil.NewExpectedState(state) + expected.ExpectStep() + expected.Registers[rdReg] = state.GetRegistersRef()[rsReg] + + stepWitness, err := goVm.Step(true) + require.NoError(t, err) + // Check expectations + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, tracer) + + if tt.funct == 0xa { + t2 = 0x1 + } else { + t2 = 0x0 + } + state.GetRegistersRef()[rtReg] = t2 + expected.ExpectStep() + expected.Registers[rtReg] = t2 + expected.Registers[rdReg] = state.GetRegistersRef()[rdReg] + + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + // Check expectations + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, tracer) + }) + } + } + +} + func TestEVM_MMap(t *testing.T) { var tracer *tracing.Hooks @@ -580,13 +643,15 @@ func TestEVMFault(t *testing.T) { versions := GetMipsVersionTestCases(t) cases := []struct { - name string - nextPC arch.Word - insn uint32 + name string + nextPC arch.Word + insn uint32 + errMsg string + memoryProofAddresses []uint32 }{ - {"illegal instruction", 0, 0xFF_FF_FF_FF}, - {"branch in delay-slot", 8, 0x11_02_00_03}, - {"jump in delay-slot", 8, 0x0c_00_00_0c}, + {"illegal instruction", 0, 0xFF_FF_FF_FF, "invalid instruction", []uint32{0xa7ef00cc}}, + {"branch in delay-slot", 8, 0x11_02_00_03, "branch in delay slot", []uint32{0}}, + {"jump in delay-slot", 8, 0x0c_00_00_0c, "jump in delay slot", []uint32{0}}, } for _, v := range versions { @@ -599,8 +664,9 @@ func TestEVMFault(t *testing.T) { // set the return address ($ra) to jump into when test completes state.GetRegistersRef()[31] = testutil.EndAddr + proofData := v.ProofGenerator(t, goVm.GetState(), tt.memoryProofAddresses...) require.Panics(t, func() { _, _ = goVm.Step(true) }) - testutil.AssertEVMReverts(t, state, v.Contracts, tracer) + testutil.AssertEVMReverts(t, state, v.Contracts, tracer, proofData, tt.errMsg) }) } } diff --git a/cannon/mipsevm/tests/evm_multithreaded_test.go b/cannon/mipsevm/tests/evm_multithreaded_test.go index 7b1fdcaf6878..21807c59f3f1 100644 --- a/cannon/mipsevm/tests/evm_multithreaded_test.go +++ b/cannon/mipsevm/tests/evm_multithreaded_test.go @@ -1183,10 +1183,12 @@ func TestEVM_UnsupportedSyscall(t *testing.T) { // Setup basic getThreadId syscall instruction state.Memory.SetUint32(state.GetPC(), syscallInsn) state.GetRegistersRef()[2] = Word(syscallNum) - + proofData := multiThreadedProofGenerator(t, state) // Set up post-state expectations require.Panics(t, func() { _, _ = goVm.Step(true) }) - testutil.AssertEVMReverts(t, state, contracts, tracer) + + errorMessage := "MIPS2: unimplemented syscall" + testutil.AssertEVMReverts(t, state, contracts, tracer, proofData, errorMessage) }) } } diff --git a/cannon/mipsevm/tests/helpers.go b/cannon/mipsevm/tests/helpers.go index d96940972a65..16a21131a88a 100644 --- a/cannon/mipsevm/tests/helpers.go +++ b/cannon/mipsevm/tests/helpers.go @@ -50,31 +50,68 @@ func multiThreadElfVmFactory(t require.TestingT, elfFile string, po mipsevm.Prei return fpvm } +type ProofGenerator func(t require.TestingT, state mipsevm.FPVMState, memoryProofAddresses ...uint32) []byte + +func singalThreadedProofGenerator(t require.TestingT, state mipsevm.FPVMState, memoryProofAddresses ...uint32) []byte { + var proofData []byte + + insnProof := state.GetMemory().MerkleProof(state.GetPC()) + proofData = append(proofData, insnProof[:]...) + + for _, addr := range memoryProofAddresses { + memProof := state.GetMemory().MerkleProof(addr) + proofData = append(proofData, memProof[:]...) + } + + return proofData +} + +func multiThreadedProofGenerator(t require.TestingT, state mipsevm.FPVMState, memoryProofAddresses ...uint32) []byte { + mtState, ok := state.(*multithreaded.State) + if !ok { + require.Fail(t, "Failed to cast FPVMState to multithreaded State type") + } + + proofData := mtState.EncodeThreadProof() + insnProof := mtState.GetMemory().MerkleProof(mtState.GetPC()) + proofData = append(proofData, insnProof[:]...) + + for _, addr := range memoryProofAddresses { + memProof := mtState.GetMemory().MerkleProof(addr) + proofData = append(proofData, memProof[:]...) + } + + return proofData +} + type VersionedVMTestCase struct { - Name string - Contracts *testutil.ContractMetadata - StateHashFn mipsevm.HashFn - VMFactory VMFactory - ElfVMFactory ElfVMFactory + Name string + Contracts *testutil.ContractMetadata + StateHashFn mipsevm.HashFn + VMFactory VMFactory + ElfVMFactory ElfVMFactory + ProofGenerator ProofGenerator } func GetSingleThreadedTestCase(t require.TestingT) VersionedVMTestCase { return VersionedVMTestCase{ - Name: "single-threaded", - Contracts: testutil.TestContractsSetup(t, testutil.MipsSingleThreaded), - StateHashFn: singlethreaded.GetStateHashFn(), - VMFactory: singleThreadedVmFactory, - ElfVMFactory: singleThreadElfVmFactory, + Name: "single-threaded", + Contracts: testutil.TestContractsSetup(t, testutil.MipsSingleThreaded), + StateHashFn: singlethreaded.GetStateHashFn(), + VMFactory: singleThreadedVmFactory, + ElfVMFactory: singleThreadElfVmFactory, + ProofGenerator: singalThreadedProofGenerator, } } func GetMultiThreadedTestCase(t require.TestingT) VersionedVMTestCase { return VersionedVMTestCase{ - Name: "multi-threaded", - Contracts: testutil.TestContractsSetup(t, testutil.MipsMultithreaded), - StateHashFn: multithreaded.GetStateHashFn(), - VMFactory: multiThreadedVmFactory, - ElfVMFactory: multiThreadElfVmFactory, + Name: "multi-threaded", + Contracts: testutil.TestContractsSetup(t, testutil.MipsMultithreaded), + StateHashFn: multithreaded.GetStateHashFn(), + VMFactory: multiThreadedVmFactory, + ElfVMFactory: multiThreadElfVmFactory, + ProofGenerator: multiThreadedProofGenerator, } } diff --git a/cannon/mipsevm/testutil/mips.go b/cannon/mipsevm/testutil/mips.go index 50d0ac48a608..a3afa527e1d7 100644 --- a/cannon/mipsevm/testutil/mips.go +++ b/cannon/mipsevm/testutil/mips.go @@ -8,6 +8,7 @@ import ( "math/big" "testing" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/state" @@ -182,12 +183,11 @@ func ValidateEVM(t *testing.T, stepWitness *mipsevm.StepWitness, step uint64, go } // AssertEVMReverts runs a single evm step from an FPVM prestate and asserts that the VM panics -func AssertEVMReverts(t *testing.T, state mipsevm.FPVMState, contracts *ContractMetadata, tracer *tracing.Hooks) { - insnProof := state.GetMemory().MerkleProof(state.GetPC()) +func AssertEVMReverts(t *testing.T, state mipsevm.FPVMState, contracts *ContractMetadata, tracer *tracing.Hooks, ProofData []byte, expectedReason string) { encodedWitness, _ := state.EncodeWitness() stepWitness := &mipsevm.StepWitness{ State: encodedWitness, - ProofData: insnProof[:], + ProofData: ProofData, } input := EncodeStepInput(t, stepWitness, mipsevm.LocalContext{}, contracts.Artifacts.MIPS) startingGas := uint64(30_000_000) @@ -195,8 +195,16 @@ func AssertEVMReverts(t *testing.T, state mipsevm.FPVMState, contracts *Contract env, evmState := NewEVMEnv(contracts) env.Config.Tracer = tracer sender := common.Address{0x13, 0x37} - _, _, err := env.Call(vm.AccountRef(sender), contracts.Addresses.MIPS, input, startingGas, common.U2560) + ret, _, err := env.Call(vm.AccountRef(sender), contracts.Addresses.MIPS, input, startingGas, common.U2560) require.EqualValues(t, err, vm.ErrExecutionReverted) + + require.Greater(t, len(ret), 4, "Return data length should be greater than 4 bytes") + + unpacked, decodeErr := abi.UnpackRevert(ret) + require.NoError(t, decodeErr, "Failed to unpack revert reason") + + require.Equal(t, expectedReason, unpacked, "Revert reason mismatch") + logs := evmState.Logs() require.Equal(t, 0, len(logs)) } diff --git a/cannon/mipsevm/testutil/state.go b/cannon/mipsevm/testutil/state.go index a9c219396a33..0c247a7fb26d 100644 --- a/cannon/mipsevm/testutil/state.go +++ b/cannon/mipsevm/testutil/state.go @@ -170,6 +170,11 @@ func (e *ExpectedState) ExpectMemoryWrite(addr arch.Word, val uint32) { e.MemoryRoot = e.expectedMemory.MerkleRoot() } +func (e *ExpectedState) ExpectMemoryWriteWord(addr arch.Word, val arch.Word) { + e.expectedMemory.SetWord(addr, val) + e.MemoryRoot = e.expectedMemory.MerkleRoot() +} + func (e *ExpectedState) Validate(t testing.TB, actualState mipsevm.FPVMState) { require.Equal(t, e.PreimageKey, actualState.GetPreimageKey(), fmt.Sprintf("Expect preimageKey = %v", e.PreimageKey)) require.Equal(t, e.PreimageOffset, actualState.GetPreimageOffset(), fmt.Sprintf("Expect preimageOffset = %v", e.PreimageOffset)) diff --git a/justfile b/justfile index 36b27c7e439e..c27d44904cd9 100644 --- a/justfile +++ b/justfile @@ -1,6 +1,9 @@ issues: ./ops/scripts/todo-checker.sh +semgrep-scan-local: + semgrep scan --config=.semgrep + lint-shellcheck: find . -type f -name '*.sh' -not -path '*/node_modules/*' -not -path './packages/contracts-bedrock/lib/*' -not -path './packages/contracts-bedrock/kout*/*' -exec sh -c 'echo \"Checking $1\"; shellcheck \"$1\"' _ {} \\; diff --git a/op-batcher/batcher/channel_config.go b/op-batcher/batcher/channel_config.go index 45dc1d4dcfa4..a23485873c60 100644 --- a/op-batcher/batcher/channel_config.go +++ b/op-batcher/batcher/channel_config.go @@ -49,6 +49,9 @@ type ChannelConfig struct { // UseBlobs indicates that this channel should be sent as a multi-blob // transaction with one blob per frame. UseBlobs bool + + // TODO(samlaf): temporary thing... just testing this out. Not sure if this is the right approach + UseAltDA bool } // ChannelConfig returns a copy of the receiver. @@ -93,7 +96,7 @@ func (cc *ChannelConfig) ReinitCompressorConfig() { } func (cc *ChannelConfig) MaxFramesPerTx() int { - if !cc.UseBlobs { + if !cc.UseBlobs && !cc.UseAltDA { return 1 } return cc.TargetNumFrames diff --git a/op-batcher/batcher/driver.go b/op-batcher/batcher/driver.go index 968e6de3e71a..ff7659e2fdac 100644 --- a/op-batcher/batcher/driver.go +++ b/op-batcher/batcher/driver.go @@ -592,10 +592,6 @@ func (l *BatchSubmitter) cancelBlockingTx(queue *txmgr.Queue[txRef], receiptsCh // publishToAltDAAndL1 posts the txdata to the DA Provider and then sends the commitment to L1. func (l *BatchSubmitter) publishToAltDAAndL1(txdata txData, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef], daGroup *errgroup.Group) { - // sanity checks - if nf := len(txdata.frames); nf != 1 { - l.Log.Crit("Unexpected number of frames in calldata tx", "num_frames", nf) - } if txdata.asBlob { l.Log.Crit("Unexpected blob txdata with AltDA enabled") } @@ -603,18 +599,20 @@ func (l *BatchSubmitter) publishToAltDAAndL1(txdata txData, queue *txmgr.Queue[t // when posting txdata to an external DA Provider, we use a goroutine to avoid blocking the main loop // since it may take a while for the request to return. goroutineSpawned := daGroup.TryGo(func() error { + l.Metr.RecordAltDARequestSubmitted() + l.Log.Info("Posting txdata to Alt DA") // TODO: probably shouldn't be using the global shutdownCtx here, see https://go.dev/blog/context-and-structs // but sendTransaction receives l.killCtx as an argument, which currently is only canceled after waiting for the main loop // to exit, which would wait on this DA call to finish, which would take a long time. // So we prefer to mimic the behavior of txmgr and cancel all pending DA/txmgr requests when the batcher is stopped. comm, err := l.AltDA.SetInput(l.shutdownCtx, txdata.CallData()) if err != nil { - l.Log.Error("Failed to post input to Alt DA", "error", err) // requeue frame if we fail to post to the DA Provider so it can be retried // note: this assumes that the da server caches requests, otherwise it might lead to resubmissions of the blobs l.recordFailedDARequest(txdata.ID(), err) return nil } + l.Metr.RecordAltDARequestSuccess() l.Log.Info("Set altda input", "commitment", comm, "tx", txdata.ID()) candidate := l.calldataTxCandidate(comm.TxData()) l.sendTx(txdata, false, candidate, queue, receiptsCh) @@ -624,7 +622,8 @@ func (l *BatchSubmitter) publishToAltDAAndL1(txdata txData, queue *txmgr.Queue[t // We couldn't start the goroutine because the errgroup.Group limit // is already reached. Since we can't send the txdata, we have to // return it for later processing. We use nil error to skip error logging. - l.recordFailedDARequest(txdata.ID(), nil) + // TODO: TxFailed pushes the databack but also increases tx_failed metric count, which we don't want. + l.state.TxFailed(txdata.ID()) } } @@ -718,9 +717,8 @@ func (l *BatchSubmitter) recordL1Tip(l1tip eth.L1BlockRef) { } func (l *BatchSubmitter) recordFailedDARequest(id txID, err error) { - if err != nil { - l.Log.Warn("DA request failed", logFields(id, err)...) - } + l.Metr.RecordAltDARequestFailed() + l.Log.Warn("DA request failed", logFields(id, err)...) l.state.TxFailed(id) } diff --git a/op-batcher/batcher/service.go b/op-batcher/batcher/service.go index 6ed906af15aa..1b28619eca31 100644 --- a/op-batcher/batcher/service.go +++ b/op-batcher/batcher/service.go @@ -99,6 +99,9 @@ func (bs *BatcherService) initFromCLIConfig(ctx context.Context, version string, bs.NetworkTimeout = cfg.TxMgrConfig.NetworkTimeout bs.CheckRecentTxsDepth = cfg.CheckRecentTxsDepth bs.WaitNodeSync = cfg.WaitNodeSync + bs.Log.Info("Batcher config", "poll_interval", bs.PollInterval, "max_pending_transactions", bs.MaxPendingTransactions, "max_concurrent_da_requests", bs.MaxConcurrentDARequests, + "network_timeout", bs.NetworkTimeout, "check_recent_txs_depth", bs.CheckRecentTxsDepth, "wait_node_sync", bs.WaitNodeSync, + ) if err := bs.initRPCClients(ctx, cfg); err != nil { return err } @@ -204,6 +207,7 @@ func (bs *BatcherService) initChannelConfig(cfg *CLIConfig) error { TargetNumFrames: cfg.TargetNumFrames, SubSafetyMargin: cfg.SubSafetyMargin, BatchType: cfg.BatchType, + UseAltDA: bs.UseAltDA, } switch cfg.DataAvailabilityType { diff --git a/op-batcher/metrics/metrics.go b/op-batcher/metrics/metrics.go index 417f927ee6f6..710cd461ff89 100644 --- a/op-batcher/metrics/metrics.go +++ b/op-batcher/metrics/metrics.go @@ -42,6 +42,10 @@ type Metricer interface { RecordChannelFullySubmitted(id derive.ChannelID) RecordChannelTimedOut(id derive.ChannelID) + RecordAltDARequestSubmitted() + RecordAltDARequestSuccess() + RecordAltDARequestFailed() + RecordBatchTxSubmitted() RecordBatchTxSuccess() RecordBatchTxFailed() @@ -83,6 +87,9 @@ type Metrics struct { batcherTxEvs opmetrics.EventVec blobUsedBytes prometheus.Histogram + + altdaInFlightRequests prometheus.Gauge + altdaRequestEvs opmetrics.EventVec } var _ Metricer = (*Metrics)(nil) @@ -193,6 +200,13 @@ func NewMetrics(procName string) *Metrics { }), batcherTxEvs: opmetrics.NewEventVec(factory, ns, "", "batcher_tx", "BatcherTx", []string{"stage"}), + + altdaRequestEvs: opmetrics.NewEventVec(factory, ns, "", "altda_request", "AltDARequest", []string{"stage"}), + altdaInFlightRequests: factory.NewGauge(prometheus.GaugeOpts{ + Namespace: ns, + Name: "altda_in_flight_requests", + Help: "Number of in-flight requests to the alt data availability layer.", + }), } } @@ -228,6 +242,10 @@ const ( StageFullySubmitted = "fully_submitted" StageTimedOut = "timed_out" + AltDAStageSubmitted = "submitted" + AltDAStageSuccess = "success" + AltDAStageFailed = "failed" + TxStageSubmitted = "submitted" TxStageSuccess = "success" TxStageFailed = "failed" @@ -318,6 +336,21 @@ func (m *Metrics) RecordBlobUsedBytes(num int) { m.blobUsedBytes.Observe(float64(num)) } +func (m *Metrics) RecordAltDARequestSubmitted() { + m.altdaInFlightRequests.Inc() + m.altdaRequestEvs.Record(AltDAStageSubmitted) +} + +func (m *Metrics) RecordAltDARequestSuccess() { + m.altdaInFlightRequests.Dec() + m.altdaRequestEvs.Record(AltDAStageSuccess) +} + +func (m *Metrics) RecordAltDARequestFailed() { + m.altdaInFlightRequests.Dec() + m.altdaRequestEvs.Record(AltDAStageFailed) +} + // estimateBatchSize estimates the size of the batch func estimateBatchSize(block *types.Block) uint64 { size := uint64(70) // estimated overhead of batch metadata diff --git a/op-batcher/metrics/noop.go b/op-batcher/metrics/noop.go index 36594efe47c7..3197221831e5 100644 --- a/op-batcher/metrics/noop.go +++ b/op-batcher/metrics/noop.go @@ -39,9 +39,14 @@ func (*noopMetrics) RecordChannelClosed(derive.ChannelID, int, int, int, int, er func (*noopMetrics) RecordChannelFullySubmitted(derive.ChannelID) {} func (*noopMetrics) RecordChannelTimedOut(derive.ChannelID) {} +func (*noopMetrics) RecordAltDARequestSubmitted() {} +func (*noopMetrics) RecordAltDARequestSuccess() {} +func (*noopMetrics) RecordAltDARequestFailed() {} + func (*noopMetrics) RecordBatchTxSubmitted() {} func (*noopMetrics) RecordBatchTxSuccess() {} func (*noopMetrics) RecordBatchTxFailed() {} + func (*noopMetrics) RecordBlobUsedBytes(int) {} func (*noopMetrics) StartBalanceMetrics(log.Logger, *ethclient.Client, common.Address) io.Closer { return nil diff --git a/op-chain-ops/deployer/opcm/implementations.go b/op-chain-ops/deployer/opcm/implementations.go index 0c61658dc429..8dd072eef246 100644 --- a/op-chain-ops/deployer/opcm/implementations.go +++ b/op-chain-ops/deployer/opcm/implementations.go @@ -16,6 +16,7 @@ type DeployImplementationsInput struct { ChallengePeriodSeconds *big.Int ProofMaturityDelaySeconds *big.Int DisputeGameFinalityDelaySeconds *big.Int + MipsVersion *big.Int // Release version to set OPCM implementations for, of the format `op-contracts/vX.Y.Z`. Release string SuperchainConfigProxy common.Address diff --git a/op-chain-ops/deployer/pipeline/implementations.go b/op-chain-ops/deployer/pipeline/implementations.go index 12000be720ec..8a743eeadf53 100644 --- a/op-chain-ops/deployer/pipeline/implementations.go +++ b/op-chain-ops/deployer/pipeline/implementations.go @@ -55,6 +55,7 @@ func DeployImplementations(ctx context.Context, env *Env, artifactsFS foundry.St ChallengePeriodSeconds: big.NewInt(86400), ProofMaturityDelaySeconds: big.NewInt(604800), DisputeGameFinalityDelaySeconds: big.NewInt(302400), + MipsVersion: big.NewInt(1), Release: intent.ContractsRelease, SuperchainConfigProxy: st.SuperchainDeployment.SuperchainConfigProxyAddress, ProtocolVersionsProxy: st.SuperchainDeployment.ProtocolVersionsProxyAddress, diff --git a/op-chain-ops/interopgen/configs.go b/op-chain-ops/interopgen/configs.go index 1008014c437a..942588a9929c 100644 --- a/op-chain-ops/interopgen/configs.go +++ b/op-chain-ops/interopgen/configs.go @@ -31,6 +31,7 @@ type SuperFaultProofConfig struct { ChallengePeriodSeconds *big.Int ProofMaturityDelaySeconds *big.Int DisputeGameFinalityDelaySeconds *big.Int + MipsVersion *big.Int } type OPCMImplementationsConfig struct { diff --git a/op-chain-ops/interopgen/deploy.go b/op-chain-ops/interopgen/deploy.go index 7f238023572a..bf86ccb5e1f2 100644 --- a/op-chain-ops/interopgen/deploy.go +++ b/op-chain-ops/interopgen/deploy.go @@ -166,6 +166,7 @@ func DeploySuperchainToL1(l1Host *script.Host, superCfg *SuperchainConfig) (*Sup ChallengePeriodSeconds: superCfg.Implementations.FaultProof.ChallengePeriodSeconds, ProofMaturityDelaySeconds: superCfg.Implementations.FaultProof.ProofMaturityDelaySeconds, DisputeGameFinalityDelaySeconds: superCfg.Implementations.FaultProof.DisputeGameFinalityDelaySeconds, + MipsVersion: superCfg.Implementations.FaultProof.MipsVersion, Release: superCfg.Implementations.Release, SuperchainConfigProxy: superDeployment.SuperchainConfigProxy, ProtocolVersionsProxy: superDeployment.ProtocolVersionsProxy, diff --git a/op-chain-ops/interopgen/recipe.go b/op-chain-ops/interopgen/recipe.go index 2d62de5c05c6..fa7c34267201 100644 --- a/op-chain-ops/interopgen/recipe.go +++ b/op-chain-ops/interopgen/recipe.go @@ -75,6 +75,7 @@ func (r *InteropDevRecipe) Build(addrs devkeys.Addresses) (*WorldConfig, error) ChallengePeriodSeconds: big.NewInt(120), ProofMaturityDelaySeconds: big.NewInt(12), DisputeGameFinalityDelaySeconds: big.NewInt(6), + MipsVersion: big.NewInt(1), }, UseInterop: true, StandardVersionsToml: opcm.StandardVersionsMainnetData, diff --git a/op-e2e/actions/interop/interop_test.go b/op-e2e/actions/interop/interop_test.go index 57c77aaec0b0..c345404907b0 100644 --- a/op-e2e/actions/interop/interop_test.go +++ b/op-e2e/actions/interop/interop_test.go @@ -1,22 +1,25 @@ package interop import ( + "context" "testing" - "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-node/rollup/interop" "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testutils" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) -var _ interop.InteropBackend = (*testutils.MockInteropBackend)(nil) +var _ interop.InteropBackend = (*testutils.FakeInteropBackend)(nil) func TestInteropVerifier(gt *testing.T) { t := helpers.NewDefaultTesting(gt) @@ -26,14 +29,14 @@ func TestInteropVerifier(gt *testing.T) { // The state genesis in this test is pre-interop however. sd.RollupCfg.InteropTime = new(uint64) logger := testlog.Logger(t, log.LevelDebug) - seqMockBackend := &testutils.MockInteropBackend{} + seqMockBackend := &testutils.FakeInteropBackend{} l1Miner, seqEng, seq := helpers.SetupSequencerTest(t, sd, logger, helpers.WithVerifierOpts(helpers.WithInteropBackend(seqMockBackend))) batcher := helpers.NewL2Batcher(logger, sd.RollupCfg, helpers.DefaultBatcherCfg(dp), seq.RollupClient(), l1Miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg)) - verMockBackend := &testutils.MockInteropBackend{} + verMockBackend := &testutils.FakeInteropBackend{} _, ver := helpers.SetupVerifier(t, sd, logger, l1Miner.L1Client(t, sd.RollupCfg), l1Miner.BlobStore(), &sync.Config{}, helpers.WithInteropBackend(verMockBackend)) @@ -42,12 +45,21 @@ func TestInteropVerifier(gt *testing.T) { ver.ActL2PipelineFull(t) l2ChainID := types.ChainIDFromBig(sd.RollupCfg.L2ChainID) - seqMockBackend.ExpectCheckBlock(l2ChainID, 1, types.LocalUnsafe, nil) + seqMockBackend.UpdateLocalUnsafeFn = func(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error { + require.Equal(t, chainID, l2ChainID) + require.Equal(t, uint64(1), head.Number) + return nil + } + seqMockBackend.UnsafeViewFn = func(ctx context.Context, chainID types.ChainID, unsafe types.ReferenceView) (types.ReferenceView, error) { + require.Equal(t, chainID, l2ChainID) + require.Equal(t, uint64(1), unsafe.Local.Number) + require.Equal(t, uint64(0), unsafe.Cross.Number) + return unsafe, nil + } // create an unsafe L2 block seq.ActL2StartBlock(t) seq.ActL2EndBlock(t) seq.ActL2PipelineFull(t) - seqMockBackend.AssertExpectations(t) status := seq.SyncStatus() require.Equal(t, uint64(1), status.UnsafeL2.Number) require.Equal(t, uint64(0), status.CrossUnsafeL2.Number) @@ -56,10 +68,16 @@ func TestInteropVerifier(gt *testing.T) { // promote it to cross-unsafe in the backend // and see if the node picks up on it - seqMockBackend.ExpectCheckBlock(l2ChainID, 1, types.CrossUnsafe, nil) + seqMockBackend.UnsafeViewFn = func(ctx context.Context, chainID types.ChainID, unsafe types.ReferenceView) (types.ReferenceView, error) { + require.Equal(t, chainID, l2ChainID) + require.Equal(t, uint64(1), unsafe.Local.Number) + require.Equal(t, uint64(0), unsafe.Cross.Number) + out := unsafe + out.Cross = unsafe.Local + return out, nil + } seq.ActInteropBackendCheck(t) seq.ActL2PipelineFull(t) - seqMockBackend.AssertExpectations(t) status = seq.SyncStatus() require.Equal(t, uint64(1), status.UnsafeL2.Number) require.Equal(t, uint64(1), status.CrossUnsafeL2.Number, "cross unsafe now") @@ -74,10 +92,20 @@ func TestInteropVerifier(gt *testing.T) { l1Miner.ActL1EndBlock(t) // Sync the L1 block, to verify the L2 block as local-safe. - seqMockBackend.ExpectCheckBlock(l2ChainID, 1, types.CrossUnsafe, nil) // not cross-safe yet + seqMockBackend.UpdateLocalUnsafeFn = nil + seqMockBackend.UpdateLocalSafeFn = func(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error { + require.Equal(t, uint64(1), lastDerived.Number) + return nil + } + seqMockBackend.SafeViewFn = func(ctx context.Context, chainID types.ChainID, safe types.ReferenceView) (types.ReferenceView, error) { + require.Equal(t, chainID, l2ChainID) + require.Equal(t, uint64(1), safe.Local.Number) + require.Equal(t, uint64(0), safe.Cross.Number) + return safe, nil + } seq.ActL1HeadSignal(t) + l1Head := seq.SyncStatus().HeadL1 seq.ActL2PipelineFull(t) - seqMockBackend.AssertExpectations(t) status = seq.SyncStatus() require.Equal(t, uint64(1), status.UnsafeL2.Number) @@ -86,10 +114,23 @@ func TestInteropVerifier(gt *testing.T) { require.Equal(t, uint64(0), status.SafeL2.Number) // Now mark it as cross-safe - seqMockBackend.ExpectCheckBlock(l2ChainID, 1, types.CrossSafe, nil) + seqMockBackend.SafeViewFn = func(ctx context.Context, chainID types.ChainID, request types.ReferenceView) (types.ReferenceView, error) { + require.Equal(t, chainID, l2ChainID) + require.Equal(t, uint64(1), request.Local.Number) + require.Equal(t, uint64(0), request.Cross.Number) + out := request + out.Cross = request.Local + return out, nil + } + seqMockBackend.DerivedFromFn = func(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (eth.L1BlockRef, error) { + require.Equal(t, uint64(1), blockNumber) + return l1Head, nil + } + seqMockBackend.FinalizedFn = func(ctx context.Context, chainID types.ChainID) (eth.BlockID, error) { + return seq.RollupCfg.Genesis.L1, nil + } seq.ActInteropBackendCheck(t) seq.ActL2PipelineFull(t) - seqMockBackend.AssertExpectations(t) status = seq.SyncStatus() require.Equal(t, uint64(1), status.UnsafeL2.Number) @@ -98,12 +139,30 @@ func TestInteropVerifier(gt *testing.T) { require.Equal(t, uint64(1), status.SafeL2.Number, "cross-safe reached") require.Equal(t, uint64(0), status.FinalizedL2.Number) + verMockBackend.UpdateLocalUnsafeFn = func(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error { + require.Equal(t, uint64(1), head.Number) + return nil + } + verMockBackend.UpdateLocalSafeFn = func(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error { + require.Equal(t, uint64(1), lastDerived.Number) + require.Equal(t, l1Head.ID(), derivedFrom.ID()) + return nil + } // The verifier might not see the L2 block that was just derived from L1 as cross-verified yet. - verMockBackend.ExpectCheckBlock(l2ChainID, 1, types.LocalUnsafe, nil) // for the local unsafe check - verMockBackend.ExpectCheckBlock(l2ChainID, 1, types.LocalUnsafe, nil) // for the local safe check + verMockBackend.UnsafeViewFn = func(ctx context.Context, chainID types.ChainID, request types.ReferenceView) (types.ReferenceView, error) { + require.Equal(t, uint64(1), request.Local.Number) + require.Equal(t, uint64(0), request.Cross.Number) + // Don't promote the Cross value yet + return request, nil + } + verMockBackend.SafeViewFn = func(ctx context.Context, chainID types.ChainID, request types.ReferenceView) (types.ReferenceView, error) { + require.Equal(t, uint64(1), request.Local.Number) + require.Equal(t, uint64(0), request.Cross.Number) + // Don't promote the Cross value yet + return request, nil + } ver.ActL1HeadSignal(t) ver.ActL2PipelineFull(t) - verMockBackend.AssertExpectations(t) status = ver.SyncStatus() require.Equal(t, uint64(1), status.UnsafeL2.Number, "synced the block") require.Equal(t, uint64(0), status.CrossUnsafeL2.Number, "not cross-verified yet") @@ -111,13 +170,16 @@ func TestInteropVerifier(gt *testing.T) { require.Equal(t, uint64(0), status.SafeL2.Number, "not yet cross-safe") require.Equal(t, uint64(0), status.FinalizedL2.Number) + seqMockBackend.UpdateFinalizedL1Fn = func(ctx context.Context, chainID types.ChainID, finalized eth.L1BlockRef) error { + require.Equal(t, l1Head, finalized) + return nil + } // signal that L1 finalized; the cross-safe block we have should get finalized too l1Miner.ActL1SafeNext(t) l1Miner.ActL1FinalizeNext(t) seq.ActL1SafeSignal(t) seq.ActL1FinalizedSignal(t) seq.ActL2PipelineFull(t) - seqMockBackend.AssertExpectations(t) status = seq.SyncStatus() require.Equal(t, uint64(1), status.FinalizedL2.Number, "finalized the block") diff --git a/op-node/chaincfg/chains.go b/op-node/chaincfg/chains.go index 2fc5c42335d8..b16e9b802ae7 100644 --- a/op-node/chaincfg/chains.go +++ b/op-node/chaincfg/chains.go @@ -9,18 +9,17 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup" ) -var Mainnet, Sepolia *rollup.Config +// OPSepolia loads the op-sepolia rollup config. This is intended for tests that need an arbitrary, valid rollup config. +func OPSepolia() *rollup.Config { + return mustLoadRollupConfig("op-sepolia") +} -func init() { - mustCfg := func(name string) *rollup.Config { - cfg, err := GetRollupConfig(name) - if err != nil { - panic(fmt.Errorf("failed to load rollup config %q: %w", name, err)) - } - return cfg +func mustLoadRollupConfig(name string) *rollup.Config { + cfg, err := GetRollupConfig(name) + if err != nil { + panic(fmt.Errorf("failed to load rollup config %q: %w", name, err)) } - Mainnet = mustCfg("op-mainnet") - Sepolia = mustCfg("op-sepolia") + return cfg } var L2ChainIDToNetworkDisplayName = func() map[string]string { diff --git a/op-node/p2p/peer_params_test.go b/op-node/p2p/peer_params_test.go index 66dc29b1604b..96e3401f5a9e 100644 --- a/op-node/p2p/peer_params_test.go +++ b/op-node/p2p/peer_params_test.go @@ -43,14 +43,14 @@ func (testSuite *PeerParamsTestSuite) TestNewPeerScoreThresholds() { // TestGetPeerScoreParams validates the peer score parameters. func (testSuite *PeerParamsTestSuite) TestGetPeerScoreParams_None() { - params, err := GetScoringParams("none", chaincfg.Sepolia) + params, err := GetScoringParams("none", chaincfg.OPSepolia()) testSuite.NoError(err) testSuite.Nil(params) } // TestLightPeerScoreParams validates the light peer score params. func (testSuite *PeerParamsTestSuite) TestGetPeerScoreParams_Light() { - cfg := chaincfg.Sepolia + cfg := chaincfg.OPSepolia() cfg.BlockTime = 1 slot := time.Duration(cfg.BlockTime) * time.Second epoch := 6 * slot @@ -98,7 +98,7 @@ func (testSuite *PeerParamsTestSuite) TestGetPeerScoreParams_Light() { // TestParamsZeroBlockTime validates peer score params use default slot for 0 block time. func (testSuite *PeerParamsTestSuite) TestParamsZeroBlockTime() { - cfg := chaincfg.Sepolia + cfg := chaincfg.OPSepolia() cfg.BlockTime = 0 slot := 2 * time.Second params, err := GetScoringParams("light", cfg) diff --git a/op-node/rollup/engine/events.go b/op-node/rollup/engine/events.go index b5e010280ebc..b05410a6dcef 100644 --- a/op-node/rollup/engine/events.go +++ b/op-node/rollup/engine/events.go @@ -229,6 +229,22 @@ func (ev PromoteFinalizedEvent) String() string { return "promote-finalized" } +// FinalizedUpdateEvent signals that a block has been marked as finalized. +type FinalizedUpdateEvent struct { + Ref eth.L2BlockRef +} + +func (ev FinalizedUpdateEvent) String() string { + return "finalized-update" +} + +// RequestFinalizedUpdateEvent signals that a FinalizedUpdateEvent is needed. +type RequestFinalizedUpdateEvent struct{} + +func (ev RequestFinalizedUpdateEvent) String() string { + return "request-finalized-update" +} + // CrossUpdateRequestEvent triggers update events to be emitted, repeating the current state. type CrossUpdateRequestEvent struct { CrossUnsafe bool @@ -419,8 +435,11 @@ func (d *EngDeriver) OnEvent(ev event.Event) bool { return true } d.ec.SetFinalizedHead(x.Ref) + d.emitter.Emit(FinalizedUpdateEvent(x)) // Try to apply the forkchoice changes d.emitter.Emit(TryUpdateEngineEvent{}) + case RequestFinalizedUpdateEvent: + d.emitter.Emit(FinalizedUpdateEvent{Ref: d.ec.Finalized()}) case CrossUpdateRequestEvent: if x.CrossUnsafe { d.emitter.Emit(CrossUnsafeUpdateEvent{ diff --git a/op-node/rollup/interop/interop.go b/op-node/rollup/interop/interop.go index 152020f09c70..904f93d94112 100644 --- a/op-node/rollup/interop/interop.go +++ b/op-node/rollup/interop/interop.go @@ -2,6 +2,7 @@ package interop import ( "context" + "fmt" "sync" "time" @@ -11,19 +12,28 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/engine" "github.com/ethereum-optimism/optimism/op-node/rollup/event" + "github.com/ethereum-optimism/optimism/op-node/rollup/finality" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) -const checkBlockTimeout = time.Second * 10 +const rpcTimeout = time.Second * 10 type InteropBackend interface { - CheckBlock(ctx context.Context, - chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (types.SafetyLevel, error) + UnsafeView(ctx context.Context, chainID types.ChainID, unsafe types.ReferenceView) (types.ReferenceView, error) + SafeView(ctx context.Context, chainID types.ChainID, safe types.ReferenceView) (types.ReferenceView, error) + Finalized(ctx context.Context, chainID types.ChainID) (eth.BlockID, error) + + DerivedFrom(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (eth.L1BlockRef, error) + + UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error + UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error + UpdateFinalizedL1(ctx context.Context, chainID types.ChainID, finalized eth.L1BlockRef) error } type L2Source interface { L2BlockRefByNumber(context.Context, uint64) (eth.L2BlockRef, error) + L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error) } // InteropDeriver watches for update events (either real changes to block safety, @@ -39,11 +49,6 @@ type InteropDeriver struct { driverCtx context.Context - // L2 blockhash -> derived from L1 block ref. - // Added to when a block is local-safe. - // Removed from when it is promoted to cross-safe. - derivedFrom map[common.Hash]eth.L1BlockRef - backend InteropBackend l2 L2Source @@ -58,13 +63,12 @@ var _ event.AttachEmitter = (*InteropDeriver)(nil) func NewInteropDeriver(log log.Logger, cfg *rollup.Config, driverCtx context.Context, backend InteropBackend, l2 L2Source) *InteropDeriver { return &InteropDeriver{ - log: log, - cfg: cfg, - chainID: types.ChainIDFromBig(cfg.L2ChainID), - driverCtx: driverCtx, - derivedFrom: make(map[common.Hash]eth.L1BlockRef), - backend: backend, - l2: l2, + log: log, + cfg: cfg, + chainID: types.ChainIDFromBig(cfg.L2ChainID), + driverCtx: driverCtx, + backend: backend, + l2: l2, } } @@ -78,87 +82,178 @@ func (d *InteropDeriver) OnEvent(ev event.Event) bool { switch x := ev.(type) { case engine.UnsafeUpdateEvent: - d.emitter.Emit(engine.RequestCrossUnsafeEvent{}) + d.onLocalUnsafeUpdate(x) + case engine.LocalSafeUpdateEvent: + d.onLocalSafeUpdate(x) + case finality.FinalizeL1Event: + d.onFinalizedL1(x) case engine.CrossUnsafeUpdateEvent: - if x.CrossUnsafe.Number >= x.LocalUnsafe.Number { - break // nothing left to promote - } - // Pre-interop the engine itself handles promotion to cross-unsafe. - // Check if the next block (still unsafe) can be promoted to cross-unsafe. - if !d.cfg.IsInterop(d.cfg.TimestampForBlock(x.CrossUnsafe.Number + 1)) { - return false - } - ctx, cancel := context.WithTimeout(d.driverCtx, checkBlockTimeout) - defer cancel() - candidate, err := d.l2.L2BlockRefByNumber(ctx, x.CrossUnsafe.Number+1) - if err != nil { - d.log.Warn("Failed to fetch next cross-unsafe candidate", "err", err) - break - } - blockSafety, err := d.backend.CheckBlock(ctx, d.chainID, candidate.Hash, candidate.Number) - if err != nil { - d.log.Warn("Failed to check interop safety of unsafe block", "err", err) - break + if err := d.onCrossUnsafe(x); err != nil { + d.log.Error("Failed to process cross-unsafe update", "err", err) } - switch blockSafety { - case types.CrossUnsafe, types.CrossSafe, types.Finalized: - // Hold off on promoting higher than cross-unsafe, - // this will happen once we verify it to be local-safe first. - d.emitter.Emit(engine.PromoteCrossUnsafeEvent{Ref: candidate}) - } - case engine.LocalSafeUpdateEvent: - d.log.Debug("Local safe update event", "block", x.Ref.Hash, "derivedFrom", x.DerivedFrom) - d.derivedFrom[x.Ref.Hash] = x.DerivedFrom - d.emitter.Emit(engine.RequestCrossSafeEvent{}) case engine.CrossSafeUpdateEvent: - if x.CrossSafe.Number >= x.LocalSafe.Number { - break // nothing left to promote - } - // Pre-interop the engine itself handles promotion to cross-safe. - // Check if the next block (not yet cross-safe) can be promoted to cross-safe. - if !d.cfg.IsInterop(d.cfg.TimestampForBlock(x.CrossSafe.Number + 1)) { - return false - } - ctx, cancel := context.WithTimeout(d.driverCtx, checkBlockTimeout) - defer cancel() - candidate, err := d.l2.L2BlockRefByNumber(ctx, x.CrossSafe.Number+1) - if err != nil { - d.log.Warn("Failed to fetch next cross-safe candidate", "err", err) - break - } - blockSafety, err := d.backend.CheckBlock(ctx, d.chainID, candidate.Hash, candidate.Number) - if err != nil { - d.log.Warn("Failed to check interop safety of local-safe block", "err", err) - break - } - derivedFrom, ok := d.derivedFrom[candidate.Hash] - if !ok { - d.log.Warn("Unknown block candidate source, cannot promote block safety", "block", candidate, "safety", blockSafety) - break + if err := d.onCrossSafeUpdateEvent(x); err != nil { + d.log.Error("Failed to process cross-safe update", "err", err) } - switch blockSafety { - case types.CrossSafe: - d.log.Info("Verified cross-safe block", "block", candidate, "derivedFrom", derivedFrom) - // TODO(#11673): once we have interop reorg support, we need to clean stale blocks also. - delete(d.derivedFrom, candidate.Hash) - d.emitter.Emit(engine.PromoteSafeEvent{ - Ref: candidate, - DerivedFrom: derivedFrom, - }) - case types.Finalized: - // TODO(#11673): once we have interop reorg support, we need to clean stale blocks also. - delete(d.derivedFrom, candidate.Hash) - d.emitter.Emit(engine.PromoteSafeEvent{ - Ref: candidate, - DerivedFrom: derivedFrom, - }) - d.emitter.Emit(engine.PromoteFinalizedEvent{ - Ref: candidate, - }) + case engine.FinalizedUpdateEvent: + if err := d.onFinalizedUpdate(x); err != nil { + d.log.Error("Failed to process finalized update", "err", err) } - // no reorg support yet; the safe L2 head will finalize eventually, no exceptions default: return false } return true } + +func (d *InteropDeriver) onLocalUnsafeUpdate(x engine.UnsafeUpdateEvent) { + d.log.Debug("Signaling unsafe L2 head update to interop backend", "head", x.Ref) + ctx, cancel := context.WithTimeout(d.driverCtx, rpcTimeout) + defer cancel() + if err := d.backend.UpdateLocalUnsafe(ctx, d.chainID, x.Ref); err != nil { + d.log.Warn("Failed to signal unsafe L2 head to interop backend", "head", x.Ref, "err", err) + // still continue to try and do a cross-unsafe update + } + // Now that the op-supervisor is aware of the new local-unsafe block, we want to check if cross-unsafe changed. + d.emitter.Emit(engine.RequestCrossUnsafeEvent{}) +} + +func (d *InteropDeriver) onLocalSafeUpdate(x engine.LocalSafeUpdateEvent) { + d.log.Debug("Signaling derived-from update to interop backend", "derivedFrom", x.DerivedFrom, "block", x.Ref) + ctx, cancel := context.WithTimeout(d.driverCtx, rpcTimeout) + defer cancel() + if err := d.backend.UpdateLocalSafe(ctx, d.chainID, x.DerivedFrom, x.Ref); err != nil { + d.log.Debug("Failed to signal derived-from update to interop backend", "derivedFrom", x.DerivedFrom, "block", x.Ref) + // still continue to try and do a cross-safe update + } + // Now that the op-supervisor is aware of the new local-safe block, we want to check if cross-safe changed. + d.emitter.Emit(engine.RequestCrossSafeEvent{}) +} + +func (d *InteropDeriver) onFinalizedL1(x finality.FinalizeL1Event) { + if !d.cfg.IsInterop(x.FinalizedL1.Time) { + return + } + d.log.Debug("Signaling finalized L1 update to interop backend", "finalized", x.FinalizedL1) + ctx, cancel := context.WithTimeout(d.driverCtx, rpcTimeout) + defer cancel() + if err := d.backend.UpdateFinalizedL1(ctx, d.chainID, x.FinalizedL1); err != nil { + d.log.Warn("Failed to signal finalized L1 block to interop backend", "finalized", x.FinalizedL1, "err", err) + } + // New L2 blocks may be ready to finalize now that the backend knows of new L1 finalized info. + d.emitter.Emit(engine.RequestFinalizedUpdateEvent{}) +} + +func (d *InteropDeriver) onCrossUnsafe(x engine.CrossUnsafeUpdateEvent) error { + if x.CrossUnsafe.Number >= x.LocalUnsafe.Number { + return nil // nothing left to promote + } + + // Pre-interop the engine itself handles promotion to cross-unsafe. + // Start checking cross-unsafe once the local-unsafe block is in the interop update. + if !d.cfg.IsInterop(x.LocalUnsafe.Time) { + return nil + } + ctx, cancel := context.WithTimeout(d.driverCtx, rpcTimeout) + defer cancel() + view := types.ReferenceView{ + Local: x.LocalUnsafe.ID(), + Cross: x.CrossUnsafe.ID(), + } + result, err := d.backend.UnsafeView(ctx, d.chainID, view) + if err != nil { + return fmt.Errorf("failed to check unsafe-level view: %w", err) + } + if result.Cross.Number == x.CrossUnsafe.Number { + // supervisor is in sync with op-node + return nil + } + if result.Cross.Number < x.CrossUnsafe.Number { + d.log.Warn("op-supervisor is behind known cross-unsafe block", "supervisor", result.Cross, "known", x.CrossUnsafe) + return nil + } + d.log.Info("New cross-unsafe block", "block", result.Cross.Number) + // Note: in the future we want to do reorg-checks, + // and initiate a reorg, if found to be on a conflicting chain. + ref, err := d.l2.L2BlockRefByHash(ctx, result.Cross.Hash) + if err != nil { + return fmt.Errorf("failed to get cross-unsafe block info of %s: %w", result.Cross, err) + } + d.emitter.Emit(engine.PromoteCrossUnsafeEvent{Ref: ref}) + + return nil +} + +func (d *InteropDeriver) onCrossSafeUpdateEvent(x engine.CrossSafeUpdateEvent) error { + if x.CrossSafe.Number >= x.LocalSafe.Number { + return nil // nothing left to promote + } + // Pre-interop the engine itself handles promotion to cross-safe. + // Start checking cross-safe once the local-safe block is in the interop update. + if !d.cfg.IsInterop(x.LocalSafe.Time) { + return nil + } + ctx, cancel := context.WithTimeout(d.driverCtx, rpcTimeout) + defer cancel() + view := types.ReferenceView{ + Local: x.LocalSafe.ID(), + Cross: x.CrossSafe.ID(), + } + result, err := d.backend.SafeView(ctx, d.chainID, view) + if err != nil { + return fmt.Errorf("failed to check safe-level view: %w", err) + } + if result.Cross.Number == x.CrossSafe.Number { + // supervisor is in sync with op-node + return nil + } + if result.Cross.Number < x.CrossSafe.Number { + d.log.Warn("op-supervisor is behind known cross-safe block", "supervisor", result.Cross, "known", x.CrossSafe) + // TODO: we may want to force set the cross-safe block in the engine, + // and then reset derivation, so this op-node can help get the supervisor back in sync. + return nil + } + derivedFrom, err := d.backend.DerivedFrom(ctx, d.chainID, result.Cross.Hash, result.Cross.Number) + if err != nil { + return fmt.Errorf("failed to get derived-from of %s: %w", result.Cross, err) + } + ref, err := d.l2.L2BlockRefByHash(ctx, result.Cross.Hash) + if err != nil { + return fmt.Errorf("failed to get block ref of %s: %w", result.Cross, err) + } + d.emitter.Emit(engine.PromoteSafeEvent{ + Ref: ref, + DerivedFrom: derivedFrom, + }) + d.emitter.Emit(engine.RequestFinalizedUpdateEvent{}) + return nil +} + +func (d *InteropDeriver) onFinalizedUpdate(x engine.FinalizedUpdateEvent) error { + // Note: we have to check interop fork, but finality may be pre-fork activation until we update. + // We may want to change this to only start checking finality once the local head is past the activation. + + ctx, cancel := context.WithTimeout(d.driverCtx, rpcTimeout) + defer cancel() + + finalized, err := d.backend.Finalized(ctx, d.chainID) + if err != nil { + return fmt.Errorf("failed to retrieve finalized L2 block from supervisor: %w", err) + } + // Check if we can finalize something new + if finalized.Number == x.Ref.Number { + // supervisor is in sync with op-node + return nil + } + if finalized.Number < x.Ref.Number { + d.log.Warn("op-supervisor is behind known finalized block", "supervisor", finalized, "known", x.Ref) + return nil + } + ref, err := d.l2.L2BlockRefByHash(ctx, finalized.Hash) + if err != nil { + return fmt.Errorf("failed to get block ref of %s: %w", finalized, err) + } + d.emitter.Emit(engine.PromoteFinalizedEvent{ + Ref: ref, + }) + return nil +} diff --git a/op-node/rollup/interop/interop_test.go b/op-node/rollup/interop/interop_test.go index a7aaedcae7a1..4078e4881a07 100644 --- a/op-node/rollup/interop/interop_test.go +++ b/op-node/rollup/interop/interop_test.go @@ -6,17 +6,18 @@ import ( "math/rand" // nosemgrep "testing" - "github.com/stretchr/testify/require" - "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/engine" + "github.com/ethereum-optimism/optimism/op-node/rollup/finality" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testutils" supervisortypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) +var _ InteropBackend = (*testutils.MockInteropBackend)(nil) + func TestInteropDeriver(t *testing.T) { logger := testlog.Logger(t, log.LevelInfo) l2Source := &testutils.MockL2Client{} @@ -31,25 +32,34 @@ func TestInteropDeriver(t *testing.T) { interopDeriver.AttachEmitter(emitter) rng := rand.New(rand.NewSource(123)) - t.Run("unsafe blocks trigger cross-unsafe check attempts", func(t *testing.T) { + t.Run("local-unsafe blocks push to supervisor and trigger cross-unsafe attempts", func(t *testing.T) { emitter.ExpectOnce(engine.RequestCrossUnsafeEvent{}) - interopDeriver.OnEvent(engine.UnsafeUpdateEvent{ - Ref: testutils.RandomL2BlockRef(rng), - }) + unsafeHead := testutils.RandomL2BlockRef(rng) + interopBackend.ExpectUpdateLocalUnsafe(chainID, unsafeHead, nil) + interopDeriver.OnEvent(engine.UnsafeUpdateEvent{Ref: unsafeHead}) emitter.AssertExpectations(t) + interopBackend.AssertExpectations(t) }) t.Run("establish cross-unsafe", func(t *testing.T) { - crossUnsafe := testutils.RandomL2BlockRef(rng) - firstLocalUnsafe := testutils.NextRandomL2Ref(rng, 2, crossUnsafe, crossUnsafe.L1Origin) - lastLocalUnsafe := testutils.NextRandomL2Ref(rng, 2, firstLocalUnsafe, firstLocalUnsafe.L1Origin) - interopBackend.ExpectCheckBlock( - chainID, firstLocalUnsafe.Number, supervisortypes.CrossUnsafe, nil) + oldCrossUnsafe := testutils.RandomL2BlockRef(rng) + nextCrossUnsafe := testutils.NextRandomL2Ref(rng, 2, oldCrossUnsafe, oldCrossUnsafe.L1Origin) + lastLocalUnsafe := testutils.NextRandomL2Ref(rng, 2, nextCrossUnsafe, nextCrossUnsafe.L1Origin) + localView := supervisortypes.ReferenceView{ + Local: lastLocalUnsafe.ID(), + Cross: oldCrossUnsafe.ID(), + } + supervisorView := supervisortypes.ReferenceView{ + Local: lastLocalUnsafe.ID(), + Cross: nextCrossUnsafe.ID(), + } + interopBackend.ExpectUnsafeView( + chainID, localView, supervisorView, nil) + l2Source.ExpectL2BlockRefByHash(nextCrossUnsafe.Hash, nextCrossUnsafe, nil) emitter.ExpectOnce(engine.PromoteCrossUnsafeEvent{ - Ref: firstLocalUnsafe, + Ref: nextCrossUnsafe, }) - l2Source.ExpectL2BlockRefByNumber(firstLocalUnsafe.Number, firstLocalUnsafe, nil) interopDeriver.OnEvent(engine.CrossUnsafeUpdateEvent{ - CrossUnsafe: crossUnsafe, + CrossUnsafe: oldCrossUnsafe, LocalUnsafe: lastLocalUnsafe, }) interopBackend.AssertExpectations(t) @@ -57,53 +67,62 @@ func TestInteropDeriver(t *testing.T) { l2Source.AssertExpectations(t) }) t.Run("deny cross-unsafe", func(t *testing.T) { - crossUnsafe := testutils.RandomL2BlockRef(rng) - firstLocalUnsafe := testutils.NextRandomL2Ref(rng, 2, crossUnsafe, crossUnsafe.L1Origin) - lastLocalUnsafe := testutils.NextRandomL2Ref(rng, 2, firstLocalUnsafe, firstLocalUnsafe.L1Origin) - interopBackend.ExpectCheckBlock( - chainID, firstLocalUnsafe.Number, supervisortypes.LocalUnsafe, nil) - l2Source.ExpectL2BlockRefByNumber(firstLocalUnsafe.Number, firstLocalUnsafe, nil) + oldCrossUnsafe := testutils.RandomL2BlockRef(rng) + nextCrossUnsafe := testutils.NextRandomL2Ref(rng, 2, oldCrossUnsafe, oldCrossUnsafe.L1Origin) + lastLocalUnsafe := testutils.NextRandomL2Ref(rng, 2, nextCrossUnsafe, nextCrossUnsafe.L1Origin) + localView := supervisortypes.ReferenceView{ + Local: lastLocalUnsafe.ID(), + Cross: oldCrossUnsafe.ID(), + } + supervisorView := supervisortypes.ReferenceView{ + Local: lastLocalUnsafe.ID(), + Cross: oldCrossUnsafe.ID(), // stuck on same cross-safe + } + interopBackend.ExpectUnsafeView( + chainID, localView, supervisorView, nil) interopDeriver.OnEvent(engine.CrossUnsafeUpdateEvent{ - CrossUnsafe: crossUnsafe, + CrossUnsafe: oldCrossUnsafe, LocalUnsafe: lastLocalUnsafe, }) interopBackend.AssertExpectations(t) - // no cross-unsafe promote event is expected - emitter.AssertExpectations(t) + emitter.AssertExpectations(t) // no promote-cross-unsafe event expected l2Source.AssertExpectations(t) }) - t.Run("register local-safe", func(t *testing.T) { + t.Run("local-safe blocks push to supervisor and trigger cross-safe attempts", func(t *testing.T) { + emitter.ExpectOnce(engine.RequestCrossSafeEvent{}) derivedFrom := testutils.RandomBlockRef(rng) localSafe := testutils.RandomL2BlockRef(rng) - emitter.ExpectOnce(engine.RequestCrossSafeEvent{}) + interopBackend.ExpectUpdateLocalSafe(chainID, derivedFrom, localSafe, nil) interopDeriver.OnEvent(engine.LocalSafeUpdateEvent{ Ref: localSafe, DerivedFrom: derivedFrom, }) - require.Contains(t, interopDeriver.derivedFrom, localSafe.Hash) - require.Equal(t, derivedFrom, interopDeriver.derivedFrom[localSafe.Hash]) emitter.AssertExpectations(t) + interopBackend.AssertExpectations(t) }) t.Run("establish cross-safe", func(t *testing.T) { derivedFrom := testutils.RandomBlockRef(rng) - crossSafe := testutils.RandomL2BlockRef(rng) - firstLocalSafe := testutils.NextRandomL2Ref(rng, 2, crossSafe, crossSafe.L1Origin) - lastLocalSafe := testutils.NextRandomL2Ref(rng, 2, firstLocalSafe, firstLocalSafe.L1Origin) - emitter.ExpectOnce(engine.RequestCrossSafeEvent{}) - // The local safe block must be known, for the derived-from mapping to work - interopDeriver.OnEvent(engine.LocalSafeUpdateEvent{ - Ref: firstLocalSafe, - DerivedFrom: derivedFrom, - }) - interopBackend.ExpectCheckBlock( - chainID, firstLocalSafe.Number, supervisortypes.CrossSafe, nil) + oldCrossSafe := testutils.RandomL2BlockRef(rng) + nextCrossSafe := testutils.NextRandomL2Ref(rng, 2, oldCrossSafe, oldCrossSafe.L1Origin) + lastLocalSafe := testutils.NextRandomL2Ref(rng, 2, nextCrossSafe, nextCrossSafe.L1Origin) + localView := supervisortypes.ReferenceView{ + Local: lastLocalSafe.ID(), + Cross: oldCrossSafe.ID(), + } + supervisorView := supervisortypes.ReferenceView{ + Local: lastLocalSafe.ID(), + Cross: nextCrossSafe.ID(), + } + interopBackend.ExpectSafeView(chainID, localView, supervisorView, nil) + interopBackend.ExpectDerivedFrom(chainID, nextCrossSafe.Hash, nextCrossSafe.Number, derivedFrom, nil) + l2Source.ExpectL2BlockRefByHash(nextCrossSafe.Hash, nextCrossSafe, nil) emitter.ExpectOnce(engine.PromoteSafeEvent{ - Ref: firstLocalSafe, + Ref: nextCrossSafe, DerivedFrom: derivedFrom, }) - l2Source.ExpectL2BlockRefByNumber(firstLocalSafe.Number, firstLocalSafe, nil) + emitter.ExpectOnce(engine.RequestFinalizedUpdateEvent{}) interopDeriver.OnEvent(engine.CrossSafeUpdateEvent{ - CrossSafe: crossSafe, + CrossSafe: oldCrossSafe, LocalSafe: lastLocalSafe, }) interopBackend.AssertExpectations(t) @@ -111,26 +130,54 @@ func TestInteropDeriver(t *testing.T) { l2Source.AssertExpectations(t) }) t.Run("deny cross-safe", func(t *testing.T) { - derivedFrom := testutils.RandomBlockRef(rng) - crossSafe := testutils.RandomL2BlockRef(rng) - firstLocalSafe := testutils.NextRandomL2Ref(rng, 2, crossSafe, crossSafe.L1Origin) - lastLocalSafe := testutils.NextRandomL2Ref(rng, 2, firstLocalSafe, firstLocalSafe.L1Origin) - emitter.ExpectOnce(engine.RequestCrossSafeEvent{}) - // The local safe block must be known, for the derived-from mapping to work - interopDeriver.OnEvent(engine.LocalSafeUpdateEvent{ - Ref: firstLocalSafe, - DerivedFrom: derivedFrom, - }) - interopBackend.ExpectCheckBlock( - chainID, firstLocalSafe.Number, supervisortypes.LocalSafe, nil) - l2Source.ExpectL2BlockRefByNumber(firstLocalSafe.Number, firstLocalSafe, nil) + oldCrossSafe := testutils.RandomL2BlockRef(rng) + nextCrossSafe := testutils.NextRandomL2Ref(rng, 2, oldCrossSafe, oldCrossSafe.L1Origin) + lastLocalSafe := testutils.NextRandomL2Ref(rng, 2, nextCrossSafe, nextCrossSafe.L1Origin) + localView := supervisortypes.ReferenceView{ + Local: lastLocalSafe.ID(), + Cross: oldCrossSafe.ID(), + } + supervisorView := supervisortypes.ReferenceView{ + Local: lastLocalSafe.ID(), + Cross: oldCrossSafe.ID(), // stay on old cross-safe + } + interopBackend.ExpectSafeView(chainID, localView, supervisorView, nil) interopDeriver.OnEvent(engine.CrossSafeUpdateEvent{ - CrossSafe: crossSafe, + CrossSafe: oldCrossSafe, LocalSafe: lastLocalSafe, }) interopBackend.AssertExpectations(t) - // no cross-safe promote event is expected - emitter.AssertExpectations(t) + emitter.AssertExpectations(t) // no promote-cross-safe event expected l2Source.AssertExpectations(t) }) + t.Run("finalized L1 trigger cross-L2 finality check", func(t *testing.T) { + emitter.ExpectOnce(engine.RequestFinalizedUpdateEvent{}) + finalizedL1 := testutils.RandomBlockRef(rng) + interopBackend.ExpectUpdateFinalizedL1(chainID, finalizedL1, nil) + interopDeriver.OnEvent(finality.FinalizeL1Event{ + FinalizedL1: finalizedL1, + }) + emitter.AssertExpectations(t) + interopBackend.AssertExpectations(t) + }) + t.Run("next L2 finalized block", func(t *testing.T) { + oldFinalizedL2 := testutils.RandomL2BlockRef(rng) + intermediateL2 := testutils.NextRandomL2Ref(rng, 2, oldFinalizedL2, oldFinalizedL2.L1Origin) + nextFinalizedL2 := testutils.NextRandomL2Ref(rng, 2, intermediateL2, intermediateL2.L1Origin) + emitter.ExpectOnce(engine.PromoteFinalizedEvent{ + Ref: nextFinalizedL2, + }) + interopBackend.ExpectFinalized(chainID, nextFinalizedL2.ID(), nil) + l2Source.ExpectL2BlockRefByHash(nextFinalizedL2.Hash, nextFinalizedL2, nil) + interopDeriver.OnEvent(engine.FinalizedUpdateEvent{Ref: oldFinalizedL2}) + emitter.AssertExpectations(t) + interopBackend.AssertExpectations(t) + }) + t.Run("keep L2 finalized block", func(t *testing.T) { + oldFinalizedL2 := testutils.RandomL2BlockRef(rng) + interopBackend.ExpectFinalized(chainID, oldFinalizedL2.ID(), nil) + interopDeriver.OnEvent(engine.FinalizedUpdateEvent{Ref: oldFinalizedL2}) + emitter.AssertExpectations(t) // no PromoteFinalizedEvent + interopBackend.AssertExpectations(t) + }) } diff --git a/op-program/chainconfig/chaincfg.go b/op-program/chainconfig/chaincfg.go index 484309cd6bca..c558b1bbad58 100644 --- a/op-program/chainconfig/chaincfg.go +++ b/op-program/chainconfig/chaincfg.go @@ -3,27 +3,14 @@ package chainconfig import ( "fmt" + "github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum/go-ethereum/params" ) -var OPSepoliaChainConfig, OPMainnetChainConfig *params.ChainConfig - -func init() { - mustLoadConfig := func(chainID uint64) *params.ChainConfig { - cfg, err := params.LoadOPStackChainConfig(chainID) - if err != nil { - panic(err) - } - return cfg - } - OPSepoliaChainConfig = mustLoadConfig(11155420) - OPMainnetChainConfig = mustLoadConfig(10) -} - -var L2ChainConfigsByChainID = map[uint64]*params.ChainConfig{ - 11155420: OPSepoliaChainConfig, - 10: OPMainnetChainConfig, +// OPSepoliaChainConfig loads the op-sepolia chain config. This is intended for tests that need an arbitrary, valid chain config. +func OPSepoliaChainConfig() *params.ChainConfig { + return mustLoadChainConfig("op-sepolia") } func RollupConfigByChainID(chainID uint64) (*rollup.Config, error) { @@ -37,3 +24,15 @@ func RollupConfigByChainID(chainID uint64) (*rollup.Config, error) { func ChainConfigByChainID(chainID uint64) (*params.ChainConfig, error) { return params.LoadOPStackChainConfig(chainID) } + +func mustLoadChainConfig(name string) *params.ChainConfig { + chainCfg := chaincfg.ChainByName(name) + if chainCfg == nil { + panic(fmt.Errorf("unknown chain config %q", name)) + } + cfg, err := ChainConfigByChainID(chainCfg.ChainID) + if err != nil { + panic(fmt.Errorf("failed to load rollup config: %q: %w", name, err)) + } + return cfg +} diff --git a/op-program/client/boot_test.go b/op-program/client/boot_test.go index e8e91e519b75..fa6aa6e664bf 100644 --- a/op-program/client/boot_test.go +++ b/op-program/client/boot_test.go @@ -14,14 +14,15 @@ import ( ) func TestBootstrapClient(t *testing.T) { + rollupCfg := chaincfg.OPSepolia() bootInfo := &BootInfo{ L1Head: common.HexToHash("0x1111"), L2OutputRoot: common.HexToHash("0x2222"), L2Claim: common.HexToHash("0x3333"), L2ClaimBlockNumber: 1, - L2ChainID: chaincfg.Sepolia.L2ChainID.Uint64(), - L2ChainConfig: chainconfig.OPSepoliaChainConfig, - RollupConfig: chaincfg.Sepolia, + L2ChainID: rollupCfg.L2ChainID.Uint64(), + L2ChainConfig: chainconfig.OPSepoliaChainConfig(), + RollupConfig: rollupCfg, } mockOracle := &mockBoostrapOracle{bootInfo, false} readBootInfo := NewBootstrapClient(mockOracle).BootInfo() @@ -35,8 +36,8 @@ func TestBootstrapClient_CustomChain(t *testing.T) { L2Claim: common.HexToHash("0x3333"), L2ClaimBlockNumber: 1, L2ChainID: CustomChainIDIndicator, - L2ChainConfig: chainconfig.OPSepoliaChainConfig, - RollupConfig: chaincfg.Sepolia, + L2ChainConfig: chainconfig.OPSepoliaChainConfig(), + RollupConfig: chaincfg.OPSepolia(), } mockOracle := &mockBoostrapOracle{bootInfo, true} readBootInfo := NewBootstrapClient(mockOracle).BootInfo() diff --git a/op-program/client/l2/engine_test.go b/op-program/client/l2/engine_test.go index 713c01c077fa..e81ae931b62d 100644 --- a/op-program/client/l2/engine_test.go +++ b/op-program/client/l2/engine_test.go @@ -165,13 +165,13 @@ func createOracleEngine(t *testing.T) (*OracleEngine, *stubEngineBackend) { } engine := OracleEngine{ backend: backend, - rollupCfg: chaincfg.Sepolia, + rollupCfg: chaincfg.OPSepolia(), } return &engine, backend } func createL2Block(t *testing.T, number int) *types.Block { - tx, err := derive.L1InfoDeposit(chaincfg.Sepolia, eth.SystemConfig{}, uint64(1), eth.HeaderBlockInfo(&types.Header{ + tx, err := derive.L1InfoDeposit(chaincfg.OPSepolia(), eth.SystemConfig{}, uint64(1), eth.HeaderBlockInfo(&types.Header{ Number: big.NewInt(32), BaseFee: big.NewInt(7), }), 0) diff --git a/op-program/host/cmd/main_test.go b/op-program/host/cmd/main_test.go index 6c91bf13365d..cee90a956646 100644 --- a/op-program/host/cmd/main_test.go +++ b/op-program/host/cmd/main_test.go @@ -73,7 +73,7 @@ func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) { require.NoError(t, err) defaultCfg := config.NewConfig( rollupCfg, - chainconfig.OPSepoliaChainConfig, + chainconfig.OPSepoliaChainConfig(), common.HexToHash(l1HeadValue), common.HexToHash(l2HeadValue), common.HexToHash(l2OutputRoot), @@ -100,7 +100,7 @@ func TestNetwork(t *testing.T) { genesisFile := writeValidGenesis(t) cfg := configForArgs(t, addRequiredArgsExcept("--network", "--rollup.config", configFile, "--l2.genesis", genesisFile)) - require.Equal(t, *chaincfg.Sepolia, *cfg.Rollup) + require.Equal(t, *chaincfg.OPSepolia(), *cfg.Rollup) }) for _, name := range chaincfg.AvailableNetworks() { @@ -154,9 +154,9 @@ func TestL2Genesis(t *testing.T) { require.Equal(t, l2GenesisConfig, cfg.L2ChainConfig) }) - t.Run("NotRequiredForGoerli", func(t *testing.T) { + t.Run("NotRequiredForSepolia", func(t *testing.T) { cfg := configForArgs(t, replaceRequiredArg("--network", "sepolia")) - require.Equal(t, chainconfig.OPSepoliaChainConfig, cfg.L2ChainConfig) + require.Equal(t, chainconfig.OPSepoliaChainConfig(), cfg.L2ChainConfig) }) } @@ -388,7 +388,7 @@ func writeValidGenesis(t *testing.T) string { func writeValidRollupConfig(t *testing.T) string { dir := t.TempDir() - j, err := json.Marshal(chaincfg.Sepolia) + j, err := json.Marshal(chaincfg.OPSepolia()) require.NoError(t, err) cfgFile := dir + "/rollup.json" require.NoError(t, os.WriteFile(cfgFile, j, 0666)) diff --git a/op-program/host/config/config_test.go b/op-program/host/config/config_test.go index e9cc54edd6a6..971807d8d6b9 100644 --- a/op-program/host/config/config_test.go +++ b/op-program/host/config/config_test.go @@ -15,8 +15,8 @@ import ( ) var ( - validRollupConfig = chaincfg.Sepolia - validL2Genesis = chainconfig.OPSepoliaChainConfig + validRollupConfig = chaincfg.OPSepolia() + validL2Genesis = chainconfig.OPSepoliaChainConfig() validL1Head = common.Hash{0xaa} validL2Head = common.Hash{0xbb} validL2Claim = common.Hash{0xcc} diff --git a/op-program/host/host_test.go b/op-program/host/host_test.go index c5d63e17ab34..8c59f42005ab 100644 --- a/op-program/host/host_test.go +++ b/op-program/host/host_test.go @@ -24,7 +24,7 @@ func TestServerMode(t *testing.T) { l1Head := common.Hash{0x11} l2OutputRoot := common.Hash{0x33} - cfg := config.NewConfig(chaincfg.Sepolia, chainconfig.OPSepoliaChainConfig, l1Head, common.Hash{0x22}, l2OutputRoot, common.Hash{0x44}, 1000) + cfg := config.NewConfig(chaincfg.OPSepolia(), chainconfig.OPSepoliaChainConfig(), l1Head, common.Hash{0x22}, l2OutputRoot, common.Hash{0x44}, 1000) cfg.DataDir = dir cfg.ServerMode = true diff --git a/op-program/host/kvstore/local_test.go b/op-program/host/kvstore/local_test.go index 4f61dc4a2784..f5e71f9d893b 100644 --- a/op-program/host/kvstore/local_test.go +++ b/op-program/host/kvstore/local_test.go @@ -15,7 +15,7 @@ import ( func TestLocalPreimageSource(t *testing.T) { cfg := &config.Config{ - Rollup: chaincfg.Sepolia, + Rollup: chaincfg.OPSepolia(), L1Head: common.HexToHash("0x1111"), L2OutputRoot: common.HexToHash("0x2222"), L2Claim: common.HexToHash("0x3333"), diff --git a/op-program/verify/mainnet/cmd/mainnet.go b/op-program/verify/mainnet/cmd/mainnet.go index bcd4d5df030d..03490dc542ba 100644 --- a/op-program/verify/mainnet/cmd/mainnet.go +++ b/op-program/verify/mainnet/cmd/mainnet.go @@ -6,11 +6,12 @@ import ( "fmt" "os" - "github.com/ethereum-optimism/optimism/op-program/chainconfig" "github.com/ethereum-optimism/optimism/op-program/verify" "github.com/ethereum/go-ethereum/common" ) +const opMainnetChainID = 10 + func main() { var l1RpcUrl string var l1RpcKind string @@ -44,7 +45,7 @@ func main() { os.Exit(2) } - runner, err := verify.NewRunner(l1RpcUrl, l1RpcKind, l1BeaconUrl, l2RpcUrl, dataDir, "op-mainnet", chainconfig.OPMainnetChainConfig) + runner, err := verify.NewRunner(l1RpcUrl, l1RpcKind, l1BeaconUrl, l2RpcUrl, dataDir, "op-mainnet", opMainnetChainID) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Failed to create runner: %v\n", err.Error()) os.Exit(1) diff --git a/op-program/verify/sepolia/cmd/sepolia.go b/op-program/verify/sepolia/cmd/sepolia.go index c89e67cea931..d07e4980866b 100644 --- a/op-program/verify/sepolia/cmd/sepolia.go +++ b/op-program/verify/sepolia/cmd/sepolia.go @@ -6,11 +6,12 @@ import ( "fmt" "os" - "github.com/ethereum-optimism/optimism/op-program/chainconfig" "github.com/ethereum-optimism/optimism/op-program/verify" "github.com/ethereum/go-ethereum/common" ) +const opSepoliaChainID = 11155420 + func main() { var l1RpcUrl string var l1RpcKind string @@ -44,7 +45,7 @@ func main() { os.Exit(2) } - runner, err := verify.NewRunner(l1RpcUrl, l1RpcKind, l1BeaconUrl, l2RpcUrl, dataDir, "op-sepolia", chainconfig.OPSepoliaChainConfig) + runner, err := verify.NewRunner(l1RpcUrl, l1RpcKind, l1BeaconUrl, l2RpcUrl, dataDir, "op-sepolia", opSepoliaChainID) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Failed to create runner: %v\n", err.Error()) os.Exit(1) diff --git a/op-program/verify/verify.go b/op-program/verify/verify.go index 124a4a2e1801..b5c5c078ddf9 100644 --- a/op-program/verify/verify.go +++ b/op-program/verify/verify.go @@ -12,6 +12,7 @@ import ( "time" "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-program/chainconfig" "github.com/ethereum-optimism/optimism/op-program/host" "github.com/ethereum-optimism/optimism/op-program/host/config" "github.com/ethereum-optimism/optimism/op-service/client" @@ -43,7 +44,7 @@ type Runner struct { rollupCfg *rollup.Config } -func NewRunner(l1RpcUrl string, l1RpcKind string, l1BeaconUrl string, l2RpcUrl string, dataDir string, network string, chainCfg *params.ChainConfig) (*Runner, error) { +func NewRunner(l1RpcUrl string, l1RpcKind string, l1BeaconUrl string, l2RpcUrl string, dataDir string, network string, chainID uint64) (*Runner, error) { ctx := context.Background() logCfg := oplog.DefaultCLIConfig() logCfg.Level = log.LevelDebug @@ -55,11 +56,16 @@ func NewRunner(l1RpcUrl string, l1RpcKind string, l1BeaconUrl string, l2RpcUrl s return nil, fmt.Errorf("dial L2 client: %w", err) } - rollupCfg, err := rollup.LoadOPStackRollupConfig(chainCfg.ChainID.Uint64()) + rollupCfg, err := rollup.LoadOPStackRollupConfig(chainID) if err != nil { return nil, fmt.Errorf("failed to load rollup config: %w", err) } + chainCfg, err := chainconfig.ChainConfigByChainID(chainID) + if err != nil { + return nil, fmt.Errorf("failed to load chain config: %w", err) + } + l2ClientCfg := sources.L2ClientDefaultConfig(rollupCfg, false) l2RPC := client.NewBaseRPCClient(l2RawRpc) l2Client, err := sources.NewL2Client(l2RPC, setupLog, nil, l2ClientCfg) diff --git a/op-service/sources/supervisor_client.go b/op-service/sources/supervisor_client.go index ff702010daff..d9cb71fb45b2 100644 --- a/op-service/sources/supervisor_client.go +++ b/op-service/sources/supervisor_client.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum-optimism/optimism/op-service/client" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) @@ -65,20 +66,48 @@ func (cl *SupervisorClient) AddL2RPC( return result } -func (cl *SupervisorClient) CheckBlock(ctx context.Context, - chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (types.SafetyLevel, error) { - var result types.SafetyLevel - err := cl.client.CallContext( - ctx, - &result, - "supervisor_checkBlock", - (*hexutil.U256)(&chainID), blockHash, hexutil.Uint64(blockNumber)) +func (cl *SupervisorClient) UnsafeView(ctx context.Context, chainID types.ChainID, unsafe types.ReferenceView) (types.ReferenceView, error) { + var result types.ReferenceView + err := cl.client.CallContext(ctx, &result, "supervisor_unsafeView", (*hexutil.U256)(&chainID), unsafe) if err != nil { - return types.LocalUnsafe, fmt.Errorf("failed to check Block %s:%d (chain %s): %w", blockHash, blockNumber, chainID, err) + return types.ReferenceView{}, fmt.Errorf("failed to share unsafe block view %s (chain %s): %w", unsafe, chainID, err) } return result, nil } +func (cl *SupervisorClient) SafeView(ctx context.Context, chainID types.ChainID, safe types.ReferenceView) (types.ReferenceView, error) { + var result types.ReferenceView + err := cl.client.CallContext(ctx, &result, "supervisor_safeView", (*hexutil.U256)(&chainID), safe) + if err != nil { + return types.ReferenceView{}, fmt.Errorf("failed to share safe block view %s (chain %s): %w", safe, chainID, err) + } + return result, nil +} + +func (cl *SupervisorClient) Finalized(ctx context.Context, chainID types.ChainID) (eth.BlockID, error) { + var result eth.BlockID + err := cl.client.CallContext(ctx, &result, "supervisor_finalized", chainID) + return result, err +} + +func (cl *SupervisorClient) DerivedFrom(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (eth.L1BlockRef, error) { + var result eth.L1BlockRef + err := cl.client.CallContext(ctx, &result, "supervisor_derivedFrom", chainID, blockHash, blockNumber) + return result, err +} + +func (cl *SupervisorClient) UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error { + return cl.client.CallContext(ctx, nil, "supervisor_updateLocalUnsafe", chainID, head) +} + +func (cl *SupervisorClient) UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error { + return cl.client.CallContext(ctx, nil, "supervisor_updateLocalSafe", chainID, derivedFrom, lastDerived) +} + +func (cl *SupervisorClient) UpdateFinalizedL1(ctx context.Context, chainID types.ChainID, finalizedL1 eth.L1BlockRef) error { + return cl.client.CallContext(ctx, nil, "supervisor_updateFinalizedL1", chainID, finalizedL1) +} + func (cl *SupervisorClient) Close() { cl.client.Close() } diff --git a/op-service/testutils/fake_interop_backend.go b/op-service/testutils/fake_interop_backend.go new file mode 100644 index 000000000000..7c6287031229 --- /dev/null +++ b/op-service/testutils/fake_interop_backend.go @@ -0,0 +1,48 @@ +package testutils + +import ( + "context" + + "github.com/ethereum/go-ethereum/common" + + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" +) + +type FakeInteropBackend struct { + UnsafeViewFn func(ctx context.Context, chainID types.ChainID, unsafe types.ReferenceView) (types.ReferenceView, error) + SafeViewFn func(ctx context.Context, chainID types.ChainID, safe types.ReferenceView) (types.ReferenceView, error) + FinalizedFn func(ctx context.Context, chainID types.ChainID) (eth.BlockID, error) + DerivedFromFn func(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (eth.L1BlockRef, error) + UpdateLocalUnsafeFn func(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error + UpdateLocalSafeFn func(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error + UpdateFinalizedL1Fn func(ctx context.Context, chainID types.ChainID, finalized eth.L1BlockRef) error +} + +func (m *FakeInteropBackend) UnsafeView(ctx context.Context, chainID types.ChainID, unsafe types.ReferenceView) (types.ReferenceView, error) { + return m.UnsafeViewFn(ctx, chainID, unsafe) +} + +func (m *FakeInteropBackend) SafeView(ctx context.Context, chainID types.ChainID, safe types.ReferenceView) (types.ReferenceView, error) { + return m.SafeViewFn(ctx, chainID, safe) +} + +func (m *FakeInteropBackend) Finalized(ctx context.Context, chainID types.ChainID) (eth.BlockID, error) { + return m.FinalizedFn(ctx, chainID) +} + +func (m *FakeInteropBackend) DerivedFrom(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (eth.L1BlockRef, error) { + return m.DerivedFromFn(ctx, chainID, blockHash, blockNumber) +} + +func (m *FakeInteropBackend) UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error { + return m.UpdateLocalUnsafeFn(ctx, chainID, head) +} + +func (m *FakeInteropBackend) UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error { + return m.UpdateLocalSafeFn(ctx, chainID, derivedFrom, lastDerived) +} + +func (m *FakeInteropBackend) UpdateFinalizedL1(ctx context.Context, chainID types.ChainID, finalized eth.L1BlockRef) error { + return m.UpdateFinalizedL1Fn(ctx, chainID, finalized) +} diff --git a/op-service/testutils/mock_interop_backend.go b/op-service/testutils/mock_interop_backend.go index 970627ff750f..4bb300a95ff2 100644 --- a/op-service/testutils/mock_interop_backend.go +++ b/op-service/testutils/mock_interop_backend.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) @@ -14,13 +15,89 @@ type MockInteropBackend struct { Mock mock.Mock } -func (m *MockInteropBackend) ExpectCheckBlock(chainID types.ChainID, blockNumber uint64, safety types.SafetyLevel, err error) { - m.Mock.On("CheckBlock", chainID, blockNumber).Once().Return(safety, &err) +func (m *MockInteropBackend) UnsafeView(ctx context.Context, chainID types.ChainID, unsafe types.ReferenceView) (types.ReferenceView, error) { + result := m.Mock.MethodCalled("UnsafeView", chainID, unsafe) + return result.Get(0).(types.ReferenceView), *result.Get(1).(*error) } -func (m *MockInteropBackend) CheckBlock(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (types.SafetyLevel, error) { - result := m.Mock.MethodCalled("CheckBlock", chainID, blockNumber) - return result.Get(0).(types.SafetyLevel), *result.Get(1).(*error) +func (m *MockInteropBackend) ExpectUnsafeView(chainID types.ChainID, unsafe types.ReferenceView, result types.ReferenceView, err error) { + m.Mock.On("UnsafeView", chainID, unsafe).Once().Return(result, &err) +} + +func (m *MockInteropBackend) OnUnsafeView(chainID types.ChainID, fn func(request types.ReferenceView) (result types.ReferenceView, err error)) { + var result types.ReferenceView + var err error + m.Mock.On("UnsafeView", chainID, mock.Anything).Run(func(args mock.Arguments) { + v := args[0].(types.ReferenceView) + result, err = fn(v) + }).Return(result, &err) +} + +func (m *MockInteropBackend) SafeView(ctx context.Context, chainID types.ChainID, safe types.ReferenceView) (types.ReferenceView, error) { + result := m.Mock.MethodCalled("SafeView", chainID, safe) + return result.Get(0).(types.ReferenceView), *result.Get(1).(*error) +} + +func (m *MockInteropBackend) ExpectSafeView(chainID types.ChainID, safe types.ReferenceView, result types.ReferenceView, err error) { + m.Mock.On("SafeView", chainID, safe).Once().Return(result, &err) +} + +func (m *MockInteropBackend) OnSafeView(chainID types.ChainID, fn func(request types.ReferenceView) (result types.ReferenceView, err error)) { + var result types.ReferenceView + var err error + m.Mock.On("SafeView", chainID, mock.Anything).Run(func(args mock.Arguments) { + v := args[0].(types.ReferenceView) + result, err = fn(v) + }).Return(result, &err) +} + +func (m *MockInteropBackend) Finalized(ctx context.Context, chainID types.ChainID) (eth.BlockID, error) { + result := m.Mock.MethodCalled("Finalized", chainID) + return result.Get(0).(eth.BlockID), *result.Get(1).(*error) +} + +func (m *MockInteropBackend) ExpectFinalized(chainID types.ChainID, result eth.BlockID, err error) { + m.Mock.On("Finalized", chainID).Once().Return(result, &err) +} + +func (m *MockInteropBackend) DerivedFrom(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (eth.L1BlockRef, error) { + result := m.Mock.MethodCalled("DerivedFrom", chainID, blockHash, blockNumber) + return result.Get(0).(eth.L1BlockRef), *result.Get(1).(*error) +} + +func (m *MockInteropBackend) ExpectDerivedFrom(chainID types.ChainID, blockHash common.Hash, blockNumber uint64, result eth.L1BlockRef, err error) { + m.Mock.On("DerivedFrom", chainID, blockHash, blockNumber).Once().Return(result, &err) +} + +func (m *MockInteropBackend) UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error { + result := m.Mock.MethodCalled("UpdateLocalUnsafe", chainID, head) + return *result.Get(0).(*error) +} + +func (m *MockInteropBackend) ExpectUpdateLocalUnsafe(chainID types.ChainID, head eth.L2BlockRef, err error) { + m.Mock.On("UpdateLocalUnsafe", chainID, head).Once().Return(&err) +} + +func (m *MockInteropBackend) ExpectAnyUpdateLocalUnsafe(chainID types.ChainID, err error) { + m.Mock.On("UpdateLocalUnsafe", chainID, mock.Anything).Once().Return(&err) +} + +func (m *MockInteropBackend) UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error { + result := m.Mock.MethodCalled("UpdateLocalSafe", chainID, derivedFrom, lastDerived) + return *result.Get(0).(*error) +} + +func (m *MockInteropBackend) ExpectUpdateLocalSafe(chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef, err error) { + m.Mock.On("UpdateLocalSafe", chainID, derivedFrom, lastDerived).Once().Return(&err) +} + +func (m *MockInteropBackend) UpdateFinalizedL1(ctx context.Context, chainID types.ChainID, finalized eth.L1BlockRef) error { + result := m.Mock.MethodCalled("UpdateFinalizedL1", chainID, finalized) + return *result.Get(0).(*error) +} + +func (m *MockInteropBackend) ExpectUpdateFinalizedL1(chainID types.ChainID, finalized eth.L1BlockRef, err error) { + m.Mock.On("UpdateFinalizedL1", chainID, finalized).Once().Return(&err) } func (m *MockInteropBackend) AssertExpectations(t mock.TestingT) { diff --git a/op-service/txmgr/txmgr.go b/op-service/txmgr/txmgr.go index 643337a147e7..e633a74c2881 100644 --- a/op-service/txmgr/txmgr.go +++ b/op-service/txmgr/txmgr.go @@ -891,6 +891,10 @@ func (m *SimpleTxManager) SuggestGasPriceCaps(ctx context.Context) (*big.Int, *b return nil, nil, nil, fmt.Errorf("failed to get gas price estimates: %w", err) } + m.metr.RecordTipCap(tip) + m.metr.RecordBaseFee(baseFee) + m.metr.RecordBlobBaseFee(blobFee) + // Enforce minimum base fee and tip cap minTipCap := m.cfg.MinTipCap.Load() minBaseFee := m.cfg.MinBaseFee.Load() diff --git a/op-supervisor/supervisor/backend/backend.go b/op-supervisor/supervisor/backend/backend.go index 8216eaa9c0b5..563268ae3f3f 100644 --- a/op-supervisor/supervisor/backend/backend.go +++ b/op-supervisor/supervisor/backend/backend.go @@ -226,3 +226,12 @@ func (su *SupervisorBackend) CheckBlock(chainID *hexutil.U256, blockHash common. safest := su.db.Safest(types.ChainID(*chainID), uint64(blockNumber), 0) return safest, nil } + +func (su *SupervisorBackend) DerivedFrom( + ctx context.Context, + chainID types.ChainID, + blockHash common.Hash, + blockNumber uint64) (eth.BlockRef, error) { + // TODO(#12358): attach to backend + return eth.BlockRef{}, nil +} diff --git a/op-supervisor/supervisor/backend/mock.go b/op-supervisor/supervisor/backend/mock.go index e62c7b950b7c..99ec630ddc36 100644 --- a/op-supervisor/supervisor/backend/mock.go +++ b/op-supervisor/supervisor/backend/mock.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/frontend" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) @@ -55,6 +56,10 @@ func (m *MockBackend) CheckBlock(chainID *hexutil.U256, blockHash common.Hash, b return types.CrossUnsafe, nil } +func (m *MockBackend) DerivedFrom(ctx context.Context, t types.ChainID, parentHash common.Hash, n uint64) (eth.BlockRef, error) { + return eth.BlockRef{}, nil +} + func (m *MockBackend) Close() error { return nil } diff --git a/op-supervisor/supervisor/frontend/frontend.go b/op-supervisor/supervisor/frontend/frontend.go index 41fb84e511cd..b77b6b3edeeb 100644 --- a/op-supervisor/supervisor/frontend/frontend.go +++ b/op-supervisor/supervisor/frontend/frontend.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) @@ -19,6 +20,13 @@ type QueryBackend interface { CheckMessage(identifier types.Identifier, payloadHash common.Hash) (types.SafetyLevel, error) CheckMessages(messages []types.Message, minSafety types.SafetyLevel) error CheckBlock(chainID *hexutil.U256, blockHash common.Hash, blockNumber hexutil.Uint64) (types.SafetyLevel, error) + DerivedFrom(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (eth.BlockRef, error) +} + +type UpdatesBackend interface { + UpdateLocalUnsafe(chainID types.ChainID, head eth.BlockRef) + UpdateLocalSafe(chainID types.ChainID, derivedFrom eth.BlockRef, lastDerived eth.BlockRef) + UpdateFinalizedL1(chainID types.ChainID, finalized eth.BlockRef) } type Backend interface { @@ -44,9 +52,24 @@ func (q *QueryFrontend) CheckMessages( return q.Supervisor.CheckMessages(messages, minSafety) } -// CheckBlock checks the safety-level of an L2 block as a whole. -func (q *QueryFrontend) CheckBlock(chainID *hexutil.U256, blockHash common.Hash, blockNumber hexutil.Uint64) (types.SafetyLevel, error) { - return q.Supervisor.CheckBlock(chainID, blockHash, blockNumber) +func (q *QueryFrontend) UnsafeView(ctx context.Context, chainID types.ChainID, unsafe types.ReferenceView) (types.ReferenceView, error) { + // TODO(#12358): attach to backend + return types.ReferenceView{}, nil +} + +func (q *QueryFrontend) SafeView(ctx context.Context, chainID types.ChainID, safe types.ReferenceView) (types.ReferenceView, error) { + // TODO(#12358): attach to backend + return types.ReferenceView{}, nil +} + +func (q *QueryFrontend) Finalized(ctx context.Context, chainID types.ChainID) (eth.BlockID, error) { + // TODO(#12358): attach to backend + return eth.BlockID{}, nil +} + +func (q *QueryFrontend) DerivedFrom(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (eth.BlockRef, error) { + // TODO(#12358): attach to backend + return eth.BlockRef{}, nil } type AdminFrontend struct { @@ -67,3 +90,19 @@ func (a *AdminFrontend) Stop(ctx context.Context) error { func (a *AdminFrontend) AddL2RPC(ctx context.Context, rpc string) error { return a.Supervisor.AddL2RPC(ctx, rpc) } + +type UpdatesFrontend struct { + Supervisor UpdatesBackend +} + +func (u *UpdatesFrontend) UpdateLocalUnsafe(chainID types.ChainID, head eth.BlockRef) { + u.Supervisor.UpdateLocalUnsafe(chainID, head) +} + +func (u *UpdatesFrontend) UpdateLocalSafe(chainID types.ChainID, derivedFrom eth.BlockRef, lastDerived eth.BlockRef) { + u.Supervisor.UpdateLocalSafe(chainID, derivedFrom, lastDerived) +} + +func (u *UpdatesFrontend) UpdateFinalizedL1(chainID types.ChainID, finalized eth.BlockRef) { + u.Supervisor.UpdateFinalizedL1(chainID, finalized) +} diff --git a/op-supervisor/supervisor/service_test.go b/op-supervisor/supervisor/service_test.go index 8cc4dcfa6678..a61b96937f6e 100644 --- a/op-supervisor/supervisor/service_test.go +++ b/op-supervisor/supervisor/service_test.go @@ -5,12 +5,9 @@ import ( "testing" "time" - "github.com/ethereum-optimism/optimism/op-supervisor/config" - "github.com/holiman/uint256" "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/op-service/dial" @@ -19,6 +16,7 @@ import ( "github.com/ethereum-optimism/optimism/op-service/oppprof" oprpc "github.com/ethereum-optimism/optimism/op-service/rpc" "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-supervisor/config" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) @@ -62,8 +60,14 @@ func TestSupervisorService(t *testing.T) { require.NoError(t, err) ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) var dest types.SafetyLevel - err = cl.CallContext(ctx, &dest, "supervisor_checkBlock", - (*hexutil.U256)(uint256.NewInt(1)), common.Hash{0xab}, hexutil.Uint64(123)) + err = cl.CallContext(ctx, &dest, "supervisor_checkMessage", + types.Identifier{ + Origin: common.Address{0xaa}, + BlockNumber: 123, + LogIndex: 42, + Timestamp: 1234567, + ChainID: types.ChainID{0xbb}, + }, common.Hash{0xcc}) cancel() require.NoError(t, err) require.Equal(t, types.CrossUnsafe, dest, "expecting mock to return cross-unsafe") diff --git a/op-supervisor/supervisor/types/types.go b/op-supervisor/supervisor/types/types.go index ea480afa8b3c..0224b9c29e93 100644 --- a/op-supervisor/supervisor/types/types.go +++ b/op-supervisor/supervisor/types/types.go @@ -11,6 +11,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + + "github.com/ethereum-optimism/optimism/op-service/eth" ) type ExecutingMessage struct { @@ -160,3 +162,12 @@ func (id ChainID) ToUInt32() (uint32, error) { } return uint32(v64), nil } + +type ReferenceView struct { + Local eth.BlockID `json:"local"` + Cross eth.BlockID `json:"cross"` +} + +func (v ReferenceView) String() string { + return fmt.Sprintf("View(local: %s, cross: %s)", v.Local, v.Cross) +} diff --git a/ops-bedrock/docker-compose.yml b/ops-bedrock/docker-compose.yml index adcaea8f4d1b..c4ec137fb7cb 100644 --- a/ops-bedrock/docker-compose.yml +++ b/ops-bedrock/docker-compose.yml @@ -12,9 +12,7 @@ volumes: da_data: op_log: - services: - l1: build: context: . @@ -34,8 +32,8 @@ services: depends_on: - l1 build: - context: . - dockerfile: l1-lighthouse.Dockerfile + context: . + dockerfile: l1-lighthouse.Dockerfile ports: - "9000:9000" - "5052:5052" @@ -56,8 +54,8 @@ services: - l1 - l1-bn build: - context: . - dockerfile: l1-lighthouse.Dockerfile + context: . + dockerfile: l1-lighthouse.Dockerfile volumes: - "l1_vc_data:/db" - "${PWD}/beacon-data/data/keys:/validator_setup/validators" @@ -82,7 +80,7 @@ services: - "l2_data:/db" - "${PWD}/../.devnet/genesis-l2.json:/genesis.json" - "${PWD}/test-jwt-secret.txt:/config/jwt-secret.txt" - entrypoint: # pass the L2 specific flags by overriding the entry-point and adding extra arguments + entrypoint: # pass the L2 specific flags by overriding the entry-point and adding extra arguments - "/bin/sh" - "/entrypoint.sh" environment: @@ -190,20 +188,23 @@ services: OP_BATCHER_L1_ETH_RPC: http://l1:8545 OP_BATCHER_L2_ETH_RPC: http://l2:8545 OP_BATCHER_ROLLUP_RPC: http://op-node:8545 - OP_BATCHER_MAX_CHANNEL_DURATION: 2 + OP_BATCHER_MAX_CHANNEL_DURATION: 10 # 10 L1 blocks = 60 seconds OP_BATCHER_SUB_SAFETY_MARGIN: 4 # SWS is 15, ChannelTimeout is 40 - OP_BATCHER_POLL_INTERVAL: 1s + OP_BATCHER_POLL_INTERVAL: 2s OP_BATCHER_NUM_CONFIRMATIONS: 1 + OP_BATCHER_MAX_PENDING_TX: 0 # no limit OP_BATCHER_MNEMONIC: test test test test test test test test test test test junk OP_BATCHER_SEQUENCER_HD_PATH: "m/44'/60'/0'/0/2" OP_BATCHER_PPROF_ENABLED: "true" OP_BATCHER_METRICS_ENABLED: "true" OP_BATCHER_RPC_ENABLE_ADMIN: "true" - OP_BATCHER_BATCH_TYPE: 1 + OP_BATCHER_BATCH_TYPE: 0 OP_BATCHER_ALTDA_ENABLED: "${ALTDA_ENABLED}" OP_BATCHER_ALTDA_DA_SERVICE: "${ALTDA_SERVICE}" OP_BATCHER_ALTDA_DA_SERVER: "http://da-server:3100" OP_BATCHER_DATA_AVAILABILITY_TYPE: "${DA_TYPE}" + OP_BATCHER_ALTDA_MAX_CONCURRENT_DA_REQUESTS: 200 + OP_BATCHER_TARGET_NUM_FRAMES: 16 op-challenger: depends_on: @@ -240,22 +241,104 @@ services: OP_CHALLENGER_NUM_CONFIRMATIONS: 1 da-server: - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/da-server:devnet - build: - context: ../ - dockerfile: ops/docker/op-stack-go/Dockerfile - target: da-server-target - command: > - da-server - --file.path=/data - --addr=0.0.0.0 - --port=3100 - --log.level=debug - --generic-commitment="${ALTDA_GENERIC_DA}" + # platform: linux/amd64 + image: ghcr.io/layr-labs/eigenda-proxy:dev + depends_on: + - redis-cache + environment: + EIGENDA_PROXY_ADDR: 0.0.0.0 + EIGENDA_PROXY_PORT: 3100 + EIGENDA_PROXY_METRICS_ENABLED: true + EIGENDA_PROXY_METRICS_PORT: 7300 + # MEMSTORE_ENABLED=true means data id only stored in a memcache inside the proxy, + # and is not forwarded to eigenda. + MEMSTORE_ENABLED: ${MEMSTORE_ENABLED-true} + MEMSTORE_EXPIRATION: 45m + MEMSTORE_PUT_LATENCY: 1m + MEMSTORE_GET_LATENCY: 1s + # if MEMSTORE_ENABLED=false, then these variables need to be set properly to connect to eigenda + EIGENDA_PROXY_EIGENDA_DISPERSER_RPC: disperser-preprod-holesky.eigenda.xyz:443 + EIGENDA_PROXY_EIGENDA_SERVICE_MANAGER_ADDR: ${EIGENDA_PROXY_EIGENDA_SERVICE_MANAGER_ADDR} + EIGENDA_PROXY_EIGENDA_SIGNER_PRIVATE_KEY_HEX: ${EIGENDA_PROXY_EIGENDA_SIGNER_PRIVATE_KEY_HEX} + EIGENDA_PROXY_EIGENDA_ETH_RPC: ${EIGENDA_PROXY_EIGENDA_ETH_RPC} + EIGENDA_PROXY_REDIS_ENDPOINT: redis-cache:6379 + EIGENDA_PROXY_REDIS_EVICTION: 1h + EIGENDA_PROXY_CACHE_TARGETS: "redis" + EIGENDA_PROXY_ETH_CONFIRMATION_DEPTH: 0 # don't wait for finality (-1) ports: - - "3100:3100" + - 3100:3100 + - 6969:7300 + + evm-tx-load-gen: + image: ghcr.io/layr-labs/evm-tx-load-gen:latest + depends_on: + - l2 + environment: + TRAFFIC_GENERATOR_HOSTNAME: http://l2:8545 + TRAFFIC_GENERATOR_TIMEOUT: 30s + TRAFFIC_GENERATOR_NUM_INSTANCES: 1 + TRAFFIC_GENERATOR_SIGNER_ADDRESSES: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 + TRAFFIC_GENERATOR_SIGNER_PRIVATE_KEYS_HEX: ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + # to send 1 MB/s, set interval to 125ms and pad_size to 130958 + # with the tx overhead (signature, nonce, etc) the actual txs send will have size exactly 128KB = 131072 bytes + # this will send 8 txs/s, each of size 128KB, such that 8 * 128 KB = 1 MB + # max block size with 30M gas is ~1.7MB. To make sure blocks are almost full but txpool doesn't just keep increasing unboundedly, + # we send 1.5MB of data (100KB every 133ms) + TRAFFIC_GENERATOR_REQUEST_INTERVAL: 133ms + TRAFFIC_GENERATOR_PAD_SIZE: 100000 + + # for eigenda-proxy da-server + redis-cache: + image: redis:7.0.11 + ports: + - "6379:6379" + + grafana: + image: grafana/grafana:11.1.0 + restart: unless-stopped + env_file: + - monitoring/grafana/grafana.env volumes: - - "da_data:/data" + - ./monitoring/grafana/provisioning/:/etc/grafana/provisioning/:ro + - ./monitoring/grafana/dashboards:/var/lib/grafana/dashboards + # - grafana_data:/var/lib/grafana + ports: + - 3000:3000 + + prometheus: + image: prom/prometheus:latest + restart: unless-stopped + # env_file: + # - .env + volumes: + - ./monitoring/prometheus:/etc/prometheus + # - prometheus_data:/prometheus + ports: + - 9090:9090 + command: --config.file=/etc/prometheus/prometheus.yml --log.level=debug + + loki: + image: grafana/loki:3.1.1 + restart: unless-stopped + volumes: + - ./monitoring/loki:/etc/loki + ports: + - 3200:3200 + command: -config.file=/etc/loki/config.yaml + + promtail: + image: grafana/promtail:3.1.1 + restart: unless-stopped + volumes: + # uncomment to scrape system logs + # - /var/log:/var/log + - ./monitoring/promtail:/etc/promtail + - /var/run/docker.sock:/var/run/docker.sock # Mount Docker socket to read container logs + command: -config.file=/etc/promtail/config.yaml + + ethereum-metrics-exporter-l2: + image: ethpandaops/ethereum-metrics-exporter:latest + command: --consensus-url http://op-node:8545 --execution-url http://l2:8545 sentinel: image: quarry/sentinel # TODO(10141): We need a public image for this (sentinel is out of repo) diff --git a/ops-bedrock/monitoring/grafana/dashboards/ethereum-metrics-exporter.json b/ops-bedrock/monitoring/grafana/dashboards/ethereum-metrics-exporter.json new file mode 100644 index 000000000000..f0ad6a15d340 --- /dev/null +++ b/ops-bedrock/monitoring/grafana/dashboards/ethereum-metrics-exporter.json @@ -0,0 +1,3678 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "Companion dashboard for https://github.com/samcm/ethereum-metrics-exporter", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 16277, + "graphTooltip": 0, + "id": 1, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "ndvLBM54z" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 5, + "title": "Overview", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 9, + "x": 0, + "y": 1 + }, + "id": 10, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "name", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "max by (version)(eth_exe_web3_client_version{instance=~\"$instance\"})", + "interval": "", + "legendFormat": "{{ version }}", + "refId": "A" + } + ], + "title": "Execution Client", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 9, + "x": 9, + "y": 1 + }, + "id": 29, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "name", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_con_spec_config_name{instance=~\"$instance\"}", + "interval": "", + "legendFormat": "{{ name }}", + "refId": "A" + } + ], + "title": "Consensus Config", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 18, + "y": 1 + }, + "id": 40, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "name", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_con_fork_current{instance=~\"$instance\"}", + "interval": "", + "legendFormat": "{{ fork }}", + "refId": "A" + } + ], + "title": "Consensus Fork", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 9, + "x": 0, + "y": 5 + }, + "id": 31, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "name", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "max by (version)(eth_con_node_version{instance=~\"$instance\"})", + "interval": "", + "legendFormat": "{{ version }}", + "refId": "A" + } + ], + "title": "Consensus Client", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 3, + "x": 18, + "y": 5 + }, + "id": 2, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_exe_chain_id{instance=~\"$instance\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Execution Chain ID", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 3, + "x": 21, + "y": 5 + }, + "id": 3, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_exe_network_id{instance=~\"$instance\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Execution Network ID", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 9, + "x": 9, + "y": 6 + }, + "id": 30, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "name", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_con_spec_preset_base{instance=~\"$instance\"}", + "interval": "", + "legendFormat": "{{ preset }}", + "refId": "A" + } + ], + "title": "Consensus Preset", + "type": "stat" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 7, + "panels": [], + "title": "Consensus Layer", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "0": { + "index": 1, + "text": "Synced" + }, + "1": { + "index": 0, + "text": "Syncing" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "green", + "value": 0 + }, + { + "color": "#EAB839", + "value": 1 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 0, + "y": 11 + }, + "id": 19, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_con_sync_is_syncing{instance=~\"$instance\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Sync Status", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 5, + "y": 11 + }, + "id": 22, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_con_sync_percentage{instance=~\"$instance\"}", + "interval": "", + "legendFormat": "{{ instance }}", + "refId": "A" + } + ], + "title": "Sync Percent", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 10, + "y": 11 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "\n eth_con_beacon_slot{instance=~\"$instance\", slot!=\"genesis\"}\n", + "interval": "", + "legendFormat": "{{ block_id }}", + "range": true, + "refId": "A" + } + ], + "title": "Slots", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 16, + "y": 11 + }, + "id": 48, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_con_beacon_finality_checkpoint_epochs{instance=~\"$instance\", state_id=\"head\", checkpoint!=\"previous_justified\"}", + "interval": "", + "legendFormat": "{{ checkpoint }}", + "refId": "A" + } + ], + "title": "Epochs", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Epochs" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 20, + "y": 11 + }, + "id": 17, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "sum by (instance)(\n eth_con_beacon_finality_checkpoint_epochs{instance=~\"$instance\", checkpoint=\"justified\", state_id=\"head\"}\n)\n-\nsum by (instance)(\n eth_con_beacon_finality_checkpoint_epochs{instance=~\"$instance\", checkpoint=\"finalized\", state_id=\"head\"}\n)", + "hide": false, + "interval": "", + "legendFormat": "Justified -> Finalized", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "sum by (instance)(\n eth_con_beacon_finality_checkpoint_epochs{instance=~\"$instance\", checkpoint=\"justified\", state_id=\"head\"}\n)\n-\nsum by (instance)(\n eth_con_beacon_finality_checkpoint_epochs{instance=~\"$instance\", checkpoint=\"previous_justified\", state_id=\"head\"}\n)", + "hide": false, + "interval": "", + "legendFormat": "Justified -> Previous Justified", + "refId": "B" + } + ], + "title": "Epoch distances", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "slots" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 0, + "y": 17 + }, + "id": 21, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_con_sync_distance{instance=~\"$instance\"}", + "interval": "", + "legendFormat": "{{ instance }}", + "refId": "A" + } + ], + "title": "Sync Distance", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 3, + "y": 17 + }, + "id": 23, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(eth_con_sync_percentage{instance=~\"$instance\"}[1m])) by (instance)", + "instant": false, + "interval": "", + "legendFormat": "{{ instance }}", + "range": true, + "refId": "A" + } + ], + "title": "Sync rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 6, + "y": 17 + }, + "id": 68, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by (instance)(increase(eth_con_beacon_reorg_count{instance=~\"$instance\"}[1m]))", + "interval": "", + "legendFormat": "{{ instance }}", + "range": true, + "refId": "A" + } + ], + "title": "Reorgs", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Slots" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 10, + "y": 17 + }, + "id": 15, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by (instance)(\n eth_con_beacon_slot{instance=~\"$instance\", block_id=\"head\"}\n)\n-\nsum by (instance) (\n eth_con_beacon_slot{instance=~\"$instance\", block_id=\"finalized\"}\n) ", + "interval": "1m", + "legendFormat": "Head -> Finalized", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by (instance)(\n eth_con_beacon_slot{instance=~\"$instance\", block_id=\"head\"}\n)\n-\nsum by (instance) (\n eth_con_beacon_slot{instance=~\"$instance\", block_id=\"justified\"}\n) != 0", + "hide": false, + "interval": "1m", + "legendFormat": "Head -> Justified", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by (instance)(\n eth_con_beacon_slot{instance=~\"$instance\", block_id=\"justified\"}\n)\n-\nsum by (instance) (\n eth_con_beacon_slot{instance=~\"$instance\", block_id=\"finalized\"}\n) != 0", + "hide": false, + "interval": "1m", + "legendFormat": "Justified -> Finalized", + "range": true, + "refId": "C" + } + ], + "title": "Slot distances", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 16, + "y": 17 + }, + "id": 67, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_con_beacon_transactions{instance=~\"$instance\", block_id=\"head\"}", + "interval": "", + "legendFormat": "Transactions", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_con_beacon_slashings{instance=~\"$instance\", block_id=\"head\", type=\"proposer\"}", + "hide": false, + "interval": "", + "legendFormat": "Proposer Slashings", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_con_beacon_slashings{instance=~\"$instance\", block_id=\"head\", type=\"attester\"}", + "hide": false, + "interval": "", + "legendFormat": "Attester Slashings", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_con_beacon_attestations{instance=~\"$instance\",block_id=\"head\"}", + "hide": false, + "interval": "", + "legendFormat": "Attestations", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_con_beacon_deposits{instance=~\"$instance\",block_id=\"head\"}", + "hide": false, + "interval": "", + "legendFormat": "Deposits", + "refId": "E" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_con_beacon_voluntary_exits{instance=~\"$instance\",block_id=\"head\"}", + "hide": false, + "interval": "", + "legendFormat": "Voluntary Exits", + "refId": "F" + } + ], + "title": "Counts Per Block (at head)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "log": 10, + "type": "log" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 20, + "y": 17 + }, + "id": 60, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by (event)(increase(eth_con_event_count{instance=~\"$instance\"}[1m]))", + "hide": false, + "interval": "1m", + "legendFormat": "{{ event }}", + "range": true, + "refId": "A" + } + ], + "title": "Events (per min)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 23 + }, + "id": 69, + "options": { + "calculate": true, + "calculation": { + "xBuckets": { + "mode": "size" + }, + "yBuckets": { + "mode": "count", + "value": "30" + } + }, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Oranges", + "steps": 128 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": false, + "expr": "avg(increase(eth_con_beacon_proposer_delay_bucket{instance=~\"$instance\"}[1m])) by (le)", + "interval": "1m", + "legendFormat": "{{ instance }}", + "range": true, + "refId": "A" + } + ], + "title": "Proposer delay", + "type": "heatmap" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": ".*Per Block" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "right" + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 5, + "x": 6, + "y": 23 + }, + "id": 72, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(eth_con_beacon_withdrawals_index_max{instance=~\"$instance\", block_id=\"head\"}) by (instance)", + "interval": "", + "legendFormat": "Index Max", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(eth_con_beacon_withdrawals_index_min{instance=~\"$instance\", block_id=\"head\"}) by (instance)", + "hide": false, + "interval": "", + "legendFormat": "Index Min", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(eth_con_beacon_withdrawals{instance=~\"$instance\", block_id=\"head\"}) by (instance)", + "hide": false, + "interval": "", + "legendFormat": "Per Block", + "range": true, + "refId": "C" + } + ], + "title": "Withdrawals", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "gwei" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 5, + "x": 11, + "y": 23 + }, + "id": 71, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(increase(eth_con_beacon_withdrawals_amount_gwei{instance=~\"$instance\", block_id=\"head\"}[1m])) by (instance)", + "interval": "", + "legendFormat": "{{ instance }}", + "range": true, + "refId": "A" + } + ], + "title": "Withdrawal Amounts", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 16, + "y": 23 + }, + "id": 70, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by (direction)(eth_con_peers{instance=~\"$instance\", state=\"connected\"})", + "hide": false, + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Peers (stacked)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 20, + "y": 23 + }, + "id": 28, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_con_fork_epoch{instance=~\"$instance\", fork!=\"SHARDING\"}", + "hide": false, + "interval": "", + "legendFormat": "{{ fork }}", + "refId": "A" + } + ], + "title": "Fork Epochs", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 30 + }, + "id": 9, + "panels": [], + "title": "Execution Layer", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "0": { + "index": 1, + "text": "Synced" + }, + "1": { + "index": 0, + "text": "Syncing" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "green", + "value": 0 + }, + { + "color": "#EAB839", + "value": 1 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 0, + "y": 31 + }, + "id": 24, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_exe_sync_is_syncing{instance=~\"$instance\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Sync Status", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 5, + "y": 31 + }, + "id": 34, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_exe_sync_percentage{instance=~\"$instance\"}", + "interval": "", + "legendFormat": "{{ instance }}", + "refId": "A" + } + ], + "title": "Sync Percent", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 10, + "y": 31 + }, + "id": 39, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_exe_block_most_recent_number{instance=~\"$instance\"}", + "interval": "", + "legendFormat": "{{ instance }}", + "refId": "A" + } + ], + "title": "Block Height", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 15, + "y": 31 + }, + "id": 45, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_exe_net_peer_count{instance=~\"$instance\"}", + "interval": "", + "legendFormat": "{{ instance }}", + "refId": "A" + } + ], + "title": "Peers", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 20, + "y": 31 + }, + "id": 47, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "sum by (instance)(\n eth_exe_block_head_total_difficulty_trillions{instance=~\"$instance\"}\n)", + "interval": "", + "legendFormat": "{{ instance }}", + "refId": "A" + } + ], + "title": "Total Difficulty (trillions)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "blocks" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 0, + "y": 37 + }, + "id": 35, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_exe_sync_highest_block{instance=~\"$instance\"} - eth_exe_sync_current_block{instance=~\"$instance\"}", + "interval": "", + "legendFormat": "{{ instance }}", + "refId": "A" + } + ], + "title": "Sync Distance", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 5, + "y": 37 + }, + "id": 36, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "sum by (instance)(rate(eth_exe_sync_percentage{instance=~\"$instance\"}[1m]))", + "interval": "1m", + "legendFormat": "{{ instance }}", + "refId": "A" + } + ], + "title": "Sync rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Gwei" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 10, + "y": 37 + }, + "id": 38, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_exe_gas_price_gwei{instance=~\"$instance\"}", + "interval": "", + "legendFormat": "{{ instance }}", + "refId": "A" + } + ], + "title": "Suggested Gas Price", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 9, + "x": 15, + "y": 37 + }, + "id": 54, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by (instance)(\n eth_exe_block_head_gas_used{instance=~\"$instance\"}\n)\n/\nsum by (instance)( \n eth_exe_block_head_gas_limit{instance=~\"$instance\"} \n)", + "interval": "20s", + "legendFormat": "{{ instance }}", + "range": true, + "refId": "A" + } + ], + "title": "Gas Used ", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 0, + "y": 43 + }, + "id": 49, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by (instance)(\n increase(\n eth_exe_block_head_transactions_in_block{instance=~\"$instance\"}[1m]\n )\n)", + "interval": "1m", + "legendFormat": "{{ instance }}", + "range": true, + "refId": "A" + } + ], + "title": "Transactions per block", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 5, + "y": 43 + }, + "id": 56, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "eth_exe_block_head_block_size_bytes{instance=~\"$instance\"}", + "interval": "1m", + "legendFormat": "{{ instance }}", + "range": true, + "refId": "A" + } + ], + "title": "Block size", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 10, + "y": 43 + }, + "id": 55, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "eth_exe_txpool_transactions{instance=~\"$instance\"}", + "interval": "", + "legendFormat": "{{ status }}", + "range": true, + "refId": "A" + } + ], + "title": "Transaction Pool", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 15, + "y": 43 + }, + "id": 53, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_exe_block_head_gas_used{instance=~\"$instance\"}", + "interval": "", + "legendFormat": "{{ instance }}", + "refId": "A" + } + ], + "title": "Gas used", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 20, + "y": 43 + }, + "id": 52, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_exe_block_head_gas_limit{instance=~\"$instance\"}", + "interval": "", + "legendFormat": "{{ instance }}", + "refId": "A" + } + ], + "title": "Gas limit", + "type": "timeseries" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 49 + }, + "id": 42, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 13, + "w": 24, + "x": 0, + "y": 50 + }, + "id": 44, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": false + }, + "pluginVersion": "9.3.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": false, + "expr": "sum by (spec)(\n label_replace(\n {__name__=~\"eth_con_spec.*\", instance=~\"$instance\"},\n \"spec\",\n \"$1\",\n \"__name__\",\n \"eth_con_spec_(.*)\"\n )\n)", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "{{ spec }}", + "refId": "A" + } + ], + "title": "Consensus Spec", + "type": "table" + } + ], + "title": "Consensus Spec", + "type": "row" + } + ], + "refresh": "5s", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "ethereum-metrics-exporter-l2:9090", + "value": "ethereum-metrics-exporter-l2:9090" + }, + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "definition": "label_values(eth_con_beacon_empty_slots_count,instance)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "instance", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(eth_con_beacon_empty_slots_count,instance)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Ethereum Metrics Exporter (Single)", + "uid": "M2TT9Su7z", + "version": 1, + "weekStart": "" +} diff --git a/ops-bedrock/monitoring/grafana/dashboards/geth-1727304694012.json b/ops-bedrock/monitoring/grafana/dashboards/geth-1727304694012.json new file mode 100644 index 000000000000..e5f8ae8b36b0 --- /dev/null +++ b/ops-bedrock/monitoring/grafana/dashboards/geth-1727304694012.json @@ -0,0 +1,5896 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "A Prometheus metric dashboard for go-ethereum, supports all blockchains compatible with go-ethereum", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 18463, + "graphTooltip": 0, + "id": 5, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 4, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "refId": "A" + } + ], + "title": "Blockchain", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 1 + }, + "id": 108, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": {}, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "chain_head_header{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Latest header", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 7, + "x": 3, + "y": 1 + }, + "id": 110, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "chain_head_header{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "header", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "chain_head_receipt{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "receipt", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "chain_head_block{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "block", + "refId": "C" + } + ], + "title": "Chain head", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 10, + "y": 1 + }, + "id": 152, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": {}, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "chain_reorg_add{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 1, + "range": true, + "refId": "A" + } + ], + "title": "Chain Reorg Add", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 1 + }, + "id": 113, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": {}, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "txpool_pending{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Executable transactions", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 9, + "x": 15, + "y": 1 + }, + "id": 116, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "txpool_pending{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "executable", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "txpool_queued{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "gapped", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "txpool_local{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "local", + "refId": "C" + } + ], + "title": "Transaction pool", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 3 + }, + "id": 111, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": {}, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "chain_head_receipt{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Latest receipt", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 3 + }, + "id": 115, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": {}, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "txpool_local{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Local transactions", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 10, + "y": 4 + }, + "id": 153, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": {}, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "chain_reorg_drop{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 1, + "range": true, + "refId": "A" + } + ], + "title": "Chain Reorg Drop", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 0, + "y": 5 + }, + "id": 109, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": {}, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "chain_head_block{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Latest block", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 3, + "x": 12, + "y": 5 + }, + "id": 114, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": {}, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "txpool_queued{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Gapped transactions", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ns" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 7 + }, + "id": 112, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "chain_execution{chain=\"$chain\", instance=~\"$instance\", quantile=\"$quantile\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "execution (q=$quantile)", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "chain_validation{chain=\"$chain\", instance=~\"$instance\", quantile=\"$quantile\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "validation (q=$quantile)", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "chain_write{chain=\"$chain\", instance=~\"$instance\", quantile=\"$quantile\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "commit (q=$quantile)", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "chain_account_reads{chain=\"$chain\", instance=~\"$instance\", quantile=\"$quantile\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "account read (q=$quantile)", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "chain_account_updates{chain=\"$chain\", instance=~\"$instance\", quantile=\"$quantile\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "account update (q=$quantile)", + "refId": "E" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "chain_account_hashes{chain=\"$chain\", instance=~\"$instance\", quantile=\"$quantile\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "account hashe (q=$quantile)", + "refId": "F" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "chain_account_commits{chain=\"$chain\", instance=~\"$instance\", quantile=\"$quantile\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "account commit (q=$quantile)", + "refId": "G" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "chain_storage_reads{chain=\"$chain\", instance=~\"$instance\", quantile=\"$quantile\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "storage read (q=$quantile)", + "refId": "H" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "chain_storage_updates{chain=\"$chain\", instance=~\"$instance\", quantile=\"$quantile\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "storage update (q=$quantile)", + "refId": "I" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "chain_storage_hashes{chain=\"$chain\", instance=~\"$instance\", quantile=\"$quantile\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "storage hashe (q=$quantile)", + "refId": "J" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "chain_storage_commits{chain=\"$chain\", instance=~\"$instance\", quantile=\"$quantile\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "storage commit (q=$quantile)", + "refId": "K" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "chain_snapshot_commits{chain=\"$chain\", instance=~\"$instance\", quantile=\"$quantile\"}", + "hide": false, + "interval": "", + "legendFormat": "snapshot commit (q=$quantile)", + "refId": "L" + } + ], + "title": "Block processing", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 7 + }, + "id": 117, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "rate(txpool_valid{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "valid", + "refId": "K" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "rate(txpool_invalid{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "invalid", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "rate(txpool_underpriced{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "underpriced", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "rate(txpool_pending_discard{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "executable discard", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "rate(txpool_pending_replace{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "executable replace", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "rate(txpool_pending_ratelimit{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "executable ratelimit", + "refId": "E" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "rate(txpool_pending_nofunds{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "executable nofunds", + "refId": "F" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "rate(txpool_queued_discard{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "gapped discard", + "refId": "G" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "rate(txpool_queued_replace{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "gapped replace", + "refId": "H" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "rate(txpool_queued_ratelimit{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "gapped ratelimit", + "refId": "I" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "rate(txpool_queued_nofunds{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "gapped nofunds", + "refId": "J" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "rate(txpool_known{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "legendFormat": "known", + "range": true, + "refId": "L" + } + ], + "title": "Transaction propagation", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 15 + }, + "id": 149, + "panels": [], + "title": "RPC", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": ".*(timeout|drop)" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "custom.axisSoftMax", + "value": 100 + }, + { + "id": "unit", + "value": "short" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 150, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(geth_rpc_requests_success_count{instance=\"$instance\"}[5m])) by (chain, instance, method)", + "hide": false, + "interval": "", + "legendFormat": "{{method}}", + "range": true, + "refId": "A" + } + ], + "title": "Success RPC QPS", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": ".*(timeout|drop)" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "custom.axisSoftMax", + "value": 100 + }, + { + "id": "unit", + "value": "short" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 147, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(geth_rpc_requests_failure_count{instance=\"$instance\"}[5m])) by (chain, instance, method)", + "hide": false, + "interval": "", + "legendFormat": "{{method}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "hide": false, + "refId": "B" + } + ], + "title": "Failure RPC QPS", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "dtdurations" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "debug_traceBlockByNumber" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "right" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 146, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "asc" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(geth_rpc_requests_success{quantile='$quantile', instance=\"$instance\"}[5m])) by (chain, instance, method) \n/ \nsum(rate(geth_rpc_requests_success_count{instance=\"$instance\"}[5m])) by (chain, instance, method) /1e6 \n< 1e200", + "hide": false, + "interval": "", + "legendFormat": "{{method}}", + "range": true, + "refId": "A" + } + ], + "title": "Success RPC Latency", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "dtdurations" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": ".*(timeout|drop)" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "custom.axisSoftMax", + "value": 100 + }, + { + "id": "unit", + "value": "short" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 151, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(geth_rpc_requests_failure{quantile='$quantile', instance=\"$instance\"}[5m])) by (chain, instance, method) / sum(rate(geth_rpc_requests_failure_count{instance=\"$instance\"}[5m])) by (chain, instance, method) /1e6", + "hide": false, + "interval": "", + "legendFormat": "{{method}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "hide": false, + "refId": "B" + } + ], + "title": "Failure RPC Latency", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 32 + }, + "id": 82, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "refId": "A" + } + ], + "title": "System", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "goroutines" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "unit", + "value": "short" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "threads" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "unit", + "value": "short" + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 0, + "y": 33 + }, + "id": 106, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "avg(system_cpu_sysload{chain=\"$chain\", instance=~\"$instance\"}) by (instance)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "system", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "avg(system_cpu_syswait{chain=\"$chain\", instance=~\"$instance\"}) by (instance)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "iowait", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "avg(system_cpu_procload{chain=\"$chain\", instance=~\"$instance\"}) by (instance)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "geth", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "avg(system_cpu_goroutines{chain=\"$chain\", instance=~\"$instance\"}) by (instance)", + "hide": false, + "interval": "", + "legendFormat": "goroutines", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "avg(system_cpu_threads{chain=\"$chain\", instance=~\"$instance\"}) by (instance)", + "hide": false, + "interval": "", + "legendFormat": "threads", + "refId": "E" + } + ], + "title": "CPU", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "used" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 8, + "y": 33 + }, + "id": 86, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(system_memory_allocs{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "alloc", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "system_memory_used{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "used", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "system_memory_held{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "held", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(system_memory_frees{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "instant": false, + "interval": "", + "legendFormat": "free", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "system_memory_pauses{chain=\"$chain\", instance=~\"$instance\"}", + "hide": true, + "interval": "", + "legendFormat": "pause", + "refId": "E" + } + ], + "title": "Memory", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Bps" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 33 + }, + "id": 85, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(system_disk_readbytes{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "read", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(system_disk_writebytes{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "write", + "refId": "B" + } + ], + "title": "Disk", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 39 + }, + "id": 75, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "refId": "A" + } + ], + "title": "Network", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Bps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": ".*-flow$" + }, + "properties": [ + { + "id": "unit", + "value": "decbytes" + }, + { + "id": "custom.axisPlacement", + "value": "right" + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 96, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "rate(p2p_ingress{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "ingress-rate", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "rate(p2p_egress{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "egress-rate", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "p2p_ingress{chain=\"$chain\", instance=~\"$instance\"}", + "hide": false, + "legendFormat": "igress-flow", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "p2p_egress{chain=\"$chain\", instance=~\"$instance\"}", + "hide": false, + "legendFormat": "egress-flow", + "range": true, + "refId": "D" + } + ], + "title": "Traffic", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 40 + }, + "id": 77, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "p2p_peers{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "peers", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(p2p_dials{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "dials", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(p2p_serves{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "serves", + "refId": "C" + } + ], + "title": "Peers", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 46 + }, + "id": 136, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "refId": "A" + } + ], + "title": "Downloader", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "Measured in #peers per second", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "#EAB839", + "value": 30 + }, + { + "color": "#6ED0E0", + "value": 50 + } + ] + }, + "unit": "cps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": ".*(timeout|drop)" + }, + "properties": [ + { + "id": "unit", + "value": "short" + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 0, + "y": 47 + }, + "id": 129, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_downloader_throttle{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + } + ], + "title": "Throttle", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "Measured in blocks per second", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": ".*(timeout|drop)" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "custom.axisSoftMax", + "value": 100 + }, + { + "id": "unit", + "value": "short" + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 47 + }, + "id": 144, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_downloader_throttle{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "hide": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "throttle peers", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_downloader_bodies_in{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "bodies in", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_downloader_headers_in{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "headers in", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_downloader_receipts_in{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "receipts in", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_downloader_bodies_drop{chain=\"$chain\", instance=~\"$instance\"}", + "hide": true, + "interval": "", + "legendFormat": "bodies drop", + "refId": "E" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_downloader_headers_drop{chain=\"$chain\", instance=~\"$instance\"}", + "hide": true, + "interval": "", + "legendFormat": "headers drop", + "refId": "F" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_downloader_receipts_drop{chain=\"$chain\", instance=~\"$instance\"}", + "hide": true, + "interval": "", + "legendFormat": "receipts drop", + "refId": "G" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_downloader_bodies_timeout{chain=\"$chain\", instance=~\"$instance\"}", + "hide": true, + "interval": "", + "legendFormat": "bodies timeout", + "refId": "H" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_downloader_headers_timeout{chain=\"$chain\", instance=~\"$instance\"}", + "hide": true, + "interval": "", + "legendFormat": "headers timeout", + "refId": "I" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_downloader_receipts_timeout{chain=\"$chain\", instance=~\"$instance\"}", + "hide": true, + "interval": "", + "legendFormat": "receipts timeout", + "refId": "J" + } + ], + "title": "QPS", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "Measured in blocks per second", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 53 + }, + "id": 145, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_downloader_throttle{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "hide": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "throttle peers", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_downloader_bodies_in{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": true, + "interval": "", + "legendFormat": "bodies in", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_downloader_headers_in{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": true, + "interval": "", + "legendFormat": "headers in", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_downloader_receipts_in{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": true, + "interval": "", + "legendFormat": "receipts in", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_downloader_bodies_drop{chain=\"$chain\", instance=~\"$instance\"}", + "hide": false, + "interval": "", + "legendFormat": "bodies drop", + "refId": "E" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_downloader_headers_drop{chain=\"$chain\", instance=~\"$instance\"}", + "hide": false, + "interval": "", + "legendFormat": "headers drop", + "refId": "F" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_downloader_receipts_drop{chain=\"$chain\", instance=~\"$instance\"}", + "hide": false, + "interval": "", + "legendFormat": "receipts drop", + "refId": "G" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_downloader_bodies_timeout{chain=\"$chain\", instance=~\"$instance\"}", + "hide": false, + "interval": "", + "legendFormat": "bodies timeout", + "refId": "H" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_downloader_headers_timeout{chain=\"$chain\", instance=~\"$instance\"}", + "hide": false, + "interval": "", + "legendFormat": "headers timeout", + "refId": "I" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_downloader_receipts_timeout{chain=\"$chain\", instance=~\"$instance\"}", + "hide": false, + "interval": "", + "legendFormat": "receipts timeout", + "refId": "J" + } + ], + "title": "Abnormal QPS", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ns" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 53 + }, + "id": 130, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_downloader_bodies_req{chain=\"$chain\", instance=~\"$instance\", quantile=\"$quantile\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "bodies(q={{quantile}})", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_downloader_headers_req{chain=\"$chain\", instance=~\"$instance\", quantile=\"$quantile\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "headers(q={{quantile}})", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_downloader_receipts_req{chain=\"$chain\", instance=~\"$instance\", quantile=\"$quantile\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "receipts(q={{quantile}})", + "refId": "D" + } + ], + "title": "Latency", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 59 + }, + "id": 134, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "refId": "A" + } + ], + "title": "Fetcher", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 2, + "x": 0, + "y": 60 + }, + "id": 138, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_fetcher_transaction_waiting_peers{chain=\"$chain\", instance=~\"$instance\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Waiting Peers", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 2, + "x": 2, + "y": 60 + }, + "id": 141, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_fetcher_transaction_waiting_hashes{chain=\"$chain\", instance=~\"$instance\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Waiting Hashes", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 2, + "x": 4, + "y": 60 + }, + "id": 140, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_fetcher_transaction_queueing_peers{chain=\"$chain\", instance=~\"$instance\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Queueing Peers", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 2, + "x": 6, + "y": 60 + }, + "id": 139, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_fetcher_transaction_queueing_hashes{chain=\"$chain\", instance=~\"$instance\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Queueing Hashes", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 2, + "x": 8, + "y": 60 + }, + "id": 142, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_fetcher_transaction_fetching_peers{chain=\"$chain\", instance=~\"$instance\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Fetching Peers", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 2, + "x": 10, + "y": 60 + }, + "id": 143, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_fetcher_transaction_fetching_hashes{chain=\"$chain\", instance=~\"$instance\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Fetching Hashes", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "Measured in blocks per second", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 60 + }, + "id": 132, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_fetcher_transaction_request_out{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "request out", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_fetcher_transaction_request_fail{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "request fail", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_fetcher_transaction_request_done{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "request done", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_fetcher_transaction_request_timeout{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "request timeout", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_fetcher_transaction_replies_in{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "replies in", + "refId": "E" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_fetcher_transaction_replies_known{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "replies known", + "refId": "F" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_fetcher_transaction_replies_underpriced{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "replies underpriced", + "refId": "G" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_fetcher_transaction_replies_otherreject{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "replies otherreject", + "refId": "H" + } + ], + "title": "QPS of Transaction", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "Measured in blocks per second", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": ".*(timeout|drop)" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "custom.axisSoftMax", + "value": 100 + }, + { + "id": "unit", + "value": "short" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 64 + }, + "id": 131, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_fetcher_block_bodies{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "bodies", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_fetcher_block_headers{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "headers", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_fetcher_block_filter_headers_in{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "filter headers in", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_fetcher_block_filter_headers_out{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "filter headers out", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_fetcher_block_filter_bodies_in{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "filter bodies in", + "refId": "E" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_fetcher_block_filter_bodies_out{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "filter bodies out", + "refId": "F" + } + ], + "title": "QPS of Block", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 72 + }, + "id": 17, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "refId": "A" + } + ], + "title": "Database", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Bps" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 73 + }, + "id": 35, + "options": { + "legend": { + "calcs": [ + "mean", + "min", + "max" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "rate(eth_db_chaindata_disk_read{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "ethdb read", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "rate(eth_db_chaindata_disk_write{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "ethdb write", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "rate(eth_db_chaindata_ancient_read{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "ancient read", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "rate(eth_db_chaindata_ancient_write{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "ancient write", + "range": true, + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_db_chaindata_compact_input{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "compact read", + "refId": "E" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_db_chaindata_compact_output{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "compact write", + "refId": "F" + } + ], + "title": "Data rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 73 + }, + "id": 118, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "eth_db_chaindata_disk_read{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "leveldb read", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "eth_db_chaindata_disk_write{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "leveldb write", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "eth_db_chaindata_ancient_read{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "ancient read", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "eth_db_chaindata_ancient_write{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "ancient write", + "refId": "D" + } + ], + "title": "Session totals", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 73 + }, + "id": 119, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "eth_db_chaindata_disk_size{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "leveldb", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "eth_db_chaindata_ancient_size{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "ancient", + "refId": "A" + } + ], + "title": "Storage size", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "delay time" + }, + "properties": [ + { + "id": "unit", + "value": "ns" + } + ] + } + ] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 0, + "y": 80 + }, + "id": 127, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_db_chaindata_compact_writedelay_counter{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + } + ], + "title": "Compact Writedelay Count", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "time" + }, + "properties": [ + { + "id": "custom.lineWidth", + "value": 3 + }, + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "unit", + "value": "ns" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "delay time" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "unit", + "value": "ns" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 21, + "x": 3, + "y": 80 + }, + "id": 121, + "options": { + "legend": { + "calcs": [ + "mean", + "min", + "max" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_db_chaindata_compact_time{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "time", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_db_chaindata_compact_nonlevel0{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "level0", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_db_chaindata_compact_level0{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "~level0", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_db_chaindata_compact_memory{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "mem", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_db_chaindata_compact_seek{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "seek", + "refId": "E" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_db_chaindata_compact_writedelay_duration{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "delay time", + "refId": "F" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(eth_db_chaindata_compact_writedelay_counter{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "delay count", + "refId": "G" + } + ], + "title": "Compact", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ns" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "time" + }, + "properties": [ + { + "id": "unit", + "value": "ns" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "delay time" + }, + "properties": [ + { + "id": "unit", + "value": "ns" + } + ] + } + ] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 0, + "y": 84 + }, + "id": 128, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "eth_db_chaindata_compact_writedelay_duration{chain=\"$chain\", instance=~\"$instance\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + } + ], + "title": "Compact Writedelay Duration", + "type": "stat" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 88 + }, + "id": 37, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "refId": "A" + } + ], + "title": "Trie Stats", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Bps" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 89 + }, + "id": 120, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "min", + "max" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": false, + "expr": "rate(trie_memcache_clean_read{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "instant": false, + "intervalFactor": 1, + "legendFormat": "read", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "rate(trie_memcache_clean_write{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "write", + "range": true, + "refId": "B" + } + ], + "title": "Clean cache-BPS", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Bps" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 89 + }, + "id": 56, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "rate(trie_memcache_gc_size{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "gc", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "rate(trie_memcache_flush_size{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "overflow", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "expr": "rate(trie_memcache_commit_size{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "commit", + "refId": "A" + } + ], + "title": "Dirty cache-BPS", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "rps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": ".*rate" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "custom.lineWidth", + "value": 2 + }, + { + "id": "color", + "value": { + "mode": "continuous-RdYlGr" + } + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 95 + }, + "id": 122, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(trie_memcache_clean_hit{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "hit", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(trie_memcache_clean_miss{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "miss", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(trie_memcache_clean_hit{chain=\"$chain\", instance=~\"$instance\"}[1m])/(rate(trie_memcache_clean_miss{chain=\"$chain\", instance=~\"$instance\"}[1m])+rate(trie_memcache_clean_hit{chain=\"$chain\", instance=~\"$instance\"}[1m]))", + "hide": false, + "interval": "", + "legendFormat": "hit rate", + "refId": "A" + } + ], + "title": "Clean cache-Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "rps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": ".*rate" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "custom.lineWidth", + "value": 2 + }, + { + "id": "color", + "value": { + "mode": "continuous-RdYlGr" + } + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 95 + }, + "id": 124, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(trie_memcache_dirty_hit{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "hit", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(trie_memcache_dirty_miss{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "miss", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(trie_memcache_dirty_hit{chain=\"$chain\", instance=~\"$instance\"}[1m])/(rate(trie_memcache_dirty_miss{chain=\"$chain\", instance=~\"$instance\"}[1m])+rate(trie_memcache_dirty_hit{chain=\"$chain\", instance=~\"$instance\"}[1m]))", + "hide": false, + "interval": "", + "legendFormat": "hit rate", + "refId": "A" + } + ], + "title": "Dirty cache-Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "wps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 101 + }, + "id": 125, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "mean", + "min", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(trie_memcache_gc_nodes{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "gc", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(trie_memcache_commit_nodes{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "commit", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(trie_memcache_flush_nodes{chain=\"$chain\", instance=~\"$instance\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "overflow", + "refId": "A" + } + ], + "title": "MPT-Nodes", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ns" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 101 + }, + "id": 126, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "mean", + "min", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(trie_memcache_gc_time{chain=\"$chain\", instance=~\"$instance\", quantile=~\"$quantile\"}[1m])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "gc", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(trie_memcache_commit_time{chain=\"$chain\", instance=~\"$instance\", quantile=~\"$quantile\"}[1m])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "commit", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "exemplar": true, + "expr": "rate(trie_memcache_flush_time{chain=\"$chain\", instance=~\"$instance\", quantile=~\"$quantile\"}[1m])", + "hide": false, + "interval": "", + "legendFormat": "overflow", + "refId": "A" + } + ], + "title": "MPT-Time", + "type": "timeseries" + } + ], + "refresh": "10s", + "revision": 1, + "schemaVersion": 39, + "tags": [ + "go-ethereum", + "blockchain", + "ethereum", + "prometheus" + ], + "templating": { + "list": [ + { + "current": { + "isNone": true, + "selected": false, + "text": "None", + "value": "" + }, + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "definition": "label_values(chain_head_block{}, chain)", + "description": "go-ethereum compatible chains", + "hide": 0, + "includeAll": false, + "label": "chain", + "multi": false, + "name": "chain", + "options": [], + "query": { + "query": "label_values(chain_head_block{}, chain)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "l1:6060", + "value": "l1:6060" + }, + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "definition": "label_values(chain_head_block{chain=~\"$chain\"}, instance)", + "hide": 0, + "includeAll": false, + "label": "instance", + "multi": false, + "name": "instance", + "options": [], + "query": { + "query": "label_values(chain_head_block{chain=~\"$chain\"}, instance)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "0.95", + "value": "0.95" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "quantile", + "options": [ + { + "selected": false, + "text": "0.5", + "value": "0.5" + }, + { + "selected": false, + "text": "0.75", + "value": "0.75" + }, + { + "selected": true, + "text": "0.95", + "value": "0.95" + }, + { + "selected": false, + "text": "0.99", + "value": "0.99" + }, + { + "selected": false, + "text": "0.999", + "value": "0.999" + }, + { + "selected": false, + "text": "0.9999", + "value": "0.9999" + } + ], + "query": "0.5, 0.75, 0.95, 0.99, 0.999, 0.9999", + "queryValue": "", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "geth (l1 and l2)", + "uid": "MHrP4vo7i", + "version": 1, + "weekStart": "" +} diff --git a/ops-bedrock/monitoring/grafana/dashboards/op_stack_compose_dashboard.json b/ops-bedrock/monitoring/grafana/dashboards/op_stack_compose_dashboard.json new file mode 100644 index 000000000000..c62628c2c493 --- /dev/null +++ b/ops-bedrock/monitoring/grafana/dashboards/op_stack_compose_dashboard.json @@ -0,0 +1,4865 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 45, + "panels": [], + "title": "Overview", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 48, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": { + "valueSize": 54 + }, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "op_node_default_refs_number{layer=\"l2\", type=\"l2_unsafe\"}", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{type}}", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_node_default_refs_number{layer=\"l2\", type=\"l2_safe\"}", + "hide": false, + "instant": false, + "legendFormat": "{{type}}", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_node_default_refs_number{layer=\"l2\", type=\"l2_finalized\"}", + "hide": false, + "instant": false, + "legendFormat": "{{type}}", + "range": true, + "refId": "C" + } + ], + "title": "L2 Blocks", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 12, + "y": 1 + }, + "id": 51, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "rate(op_node_default_transactions_sequenced_total[$__rate_interval])", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Sequencer TPS", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 0, + "y": 5 + }, + "id": 63, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "txpool_pending{instance=\"l2:6060\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "executable", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "txpool_queued{instance=\"l2:6060\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "gapped", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "txpool_local{instance=\"l2:6060\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "local", + "range": true, + "refId": "C" + } + ], + "title": "Transaction pool", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 6, + "y": 5 + }, + "id": 64, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "eth_exe_block_head_transactions_in_block", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "executable", + "range": true, + "refId": "A" + } + ], + "title": "Txs per block", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 12, + "y": 5 + }, + "id": 61, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "eth_exe_block_head_block_size_bytes{instance=\"ethereum-metrics-exporter-l2:9090\"}", + "interval": "1m", + "legendFormat": "{{ instance }}", + "range": true, + "refId": "A" + } + ], + "title": "Block size", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 18, + "y": 5 + }, + "id": 62, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "exemplar": true, + "expr": "eth_exe_block_head_gas_used{instance=\"ethereum-metrics-exporter-l2:9090\"}", + "interval": "", + "legendFormat": "{{ instance }}", + "range": true, + "refId": "A" + } + ], + "title": "Block Gas used", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 0, + "y": 10 + }, + "id": 56, + "interval": "2s", + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "op_batcher_default_blocks_added_count", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "num_blocks", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_batcher_default_channel_num_frames", + "hide": false, + "instant": false, + "legendFormat": "num_frames", + "range": true, + "refId": "B" + } + ], + "title": "op-batcher curr channel", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 5, + "y": 10 + }, + "id": 57, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_batcher_default_output_bytes", + "hide": false, + "instant": false, + "legendFormat": "bytes output (compressed)", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_batcher_default_input_bytes{stage=\"closed\"}", + "hide": false, + "instant": false, + "legendFormat": "bytes input", + "range": true, + "refId": "B" + } + ], + "title": "op-batcher bytes/channel", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Bps" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 7, + "x": 11, + "y": 10 + }, + "id": 59, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "rate(op_batcher_default_input_bytes_total[$__rate_interval])", + "hide": false, + "instant": false, + "legendFormat": "input", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "rate(op_batcher_default_output_bytes_total[$__rate_interval])", + "hide": false, + "instant": false, + "legendFormat": "output (compressed)", + "range": true, + "refId": "B" + } + ], + "title": "op-batcher throughput", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "Bps" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 18, + "y": 10 + }, + "id": 60, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false, + "sizing": "auto" + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "rate(op_batcher_default_input_bytes_total[$__rate_interval])", + "hide": false, + "instant": false, + "legendFormat": "input", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "rate(op_batcher_default_output_bytes_total[$__rate_interval])", + "hide": false, + "instant": false, + "legendFormat": "output (compressed)", + "range": true, + "refId": "B" + } + ], + "title": "op-batcher throughput", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "fixed" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "success" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "green", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "in-flight" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "yellow", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 4, + "w": 7, + "x": 0, + "y": 16 + }, + "id": 52, + "interval": "2s", + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "op_batcher_default_altda_request_total", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{stage}}", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_batcher_default_altda_in_flight_requests", + "hide": false, + "instant": false, + "legendFormat": "in-flight", + "range": true, + "refId": "B" + } + ], + "title": "Batcher AltDA Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 7, + "x": 7, + "y": 16 + }, + "id": 49, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "eigenda_proxy_http_server_requests_total", + "instant": false, + "legendFormat": "{{method}} - {{commitment_mode}} - {{DA_cert_version}}", + "range": true, + "refId": "A" + } + ], + "title": "Eigenda-Proxy Completed Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "", + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 14, + "y": 16 + }, + "id": 55, + "interval": "2s", + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_batcher_default_txmgr_pending_txs", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{__name__}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Batcher Pending Txs", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 19, + "y": 16 + }, + "id": 53, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_node_default_frame_added_total", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Deriv Pipeline Frames Seen", + "type": "stat" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 20 + }, + "id": 27, + "panels": [], + "title": "EigenDA Proxy", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 16, + "w": 7, + "x": 0, + "y": 21 + }, + "id": 28, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "eigenda_proxy_http_server_requests_total", + "instant": false, + "legendFormat": "{{method}} - {{commitment_mode}} - {{DA_cert_version}}", + "range": true, + "refId": "A" + } + ], + "title": "Requests Total", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 16, + "w": 8, + "x": 7, + "y": 21 + }, + "id": 47, + "options": { + "displayMode": "gradient", + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "eigenda_proxy_http_server_request_duration_seconds_bucket{method=\"GET\"}", + "format": "heatmap", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "/get requests duration", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 16, + "w": 9, + "x": 15, + "y": 21 + }, + "id": 29, + "options": { + "displayMode": "gradient", + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "eigenda_proxy_http_server_request_duration_seconds_bucket{method=\"POST\"}", + "format": "heatmap", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "/put requests duration", + "type": "bargauge" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 37 + }, + "id": 14, + "panels": [], + "title": "Batcher", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 38 + }, + "id": 20, + "interval": "2s", + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_batcher_default_pending_blocks_count", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "pending_blocks_count {{stage}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Number of pending blocks, not added to a channel yet.", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 38 + }, + "id": 19, + "interval": "2s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_batcher_default_input_bytes", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "input {{stage}}", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_batcher_default_output_bytes", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "output", + "range": true, + "refId": "B", + "useBackend": false + } + ], + "title": "Total number of input/output bytes per channel.", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 46 + }, + "id": 17, + "interval": "2s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "rate(op_batcher_default_pending_blocks_bytes_total[$__rate_interval])", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{__name__}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Total size of transactions in pending blocks as they are fetched from L2", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 46 + }, + "id": 16, + "interval": "2s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_batcher_default_blocks_added_count", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{__name__}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Total number of blocks added to current channel.", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 54 + }, + "id": 18, + "interval": "2s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_batcher_default_channel_num_frames", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{__name__}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Total number of frames of closed channel.", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 54 + }, + "id": 25, + "interval": "2s", + "options": { + "displayMode": "basic", + "maxVizHeight": 300, + "minVizHeight": 16, + "minVizWidth": 8, + "namePlacement": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_batcher_default_blob_used_bytes_bucket", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "B", + "useBackend": false + } + ], + "title": "Blob sizes", + "type": "bargauge" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 66 + }, + "id": 41, + "panels": [], + "title": "Batcher altda", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "", + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 67 + }, + "id": 40, + "interval": "2s", + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "op_batcher_default_altda_in_flight_requests", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{__name__}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Batcher InFlight AltDA Requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "", + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 67 + }, + "id": 42, + "interval": "2s", + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "op_batcher_default_altda_request_total", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{stage}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Batcher AltDA Requests", + "type": "stat" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 75 + }, + "id": 26, + "panels": [], + "title": "Batcher txmgr", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 76 + }, + "id": 21, + "interval": "2s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_batcher_default_txmgr_last_confirm_unix", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{__name__}}", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_batcher_default_txmgr_last_publish_unix", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{__name__}}", + "range": true, + "refId": "B", + "useBackend": false + } + ], + "title": "Batcher Tx Publish/Confirm Times", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "TODO: batcher_tx_total is 2x txs sent b/c of bug. See https://github.com/ethereum-optimism/optimism/pull/11438", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 76 + }, + "id": 15, + "interval": "2s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_batcher_default_batcher_tx_total", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{__name__}}", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_batcher_default_txmgr_confirm_total", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{__name__}}", + "range": true, + "refId": "B", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_batcher_default_txmgr_current_nonce", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{__name__}}", + "range": true, + "refId": "C", + "useBackend": false + } + ], + "title": "Batcher Txs", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 84 + }, + "id": 23, + "interval": "2s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_batcher_default_txmgr_pending_txs", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{__name__}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Batcher Pending Txs", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 84 + }, + "id": 22, + "interval": "2s", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_batcher_default_txmgr_tx_confirmed_latency_ms", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{__name__}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Tx confirmation latency", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 92 + }, + "id": 33, + "panels": [], + "title": "Node", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 93 + }, + "id": 34, + "options": { + "legend": { + "calcs": [], + "displayMode": "hidden", + "placement": "right", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_node_default_events_emitted", + "instant": false, + "legendFormat": "{{event_type}} (from {{emitter}})", + "range": true, + "refId": "A" + } + ], + "title": "Events Emitted (by emitters)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 93 + }, + "id": 35, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_node_default_events_processed", + "instant": false, + "legendFormat": "{{event_type}} (from {{deriver}})", + "range": true, + "refId": "A" + } + ], + "title": "Events Processed (by derivers)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 102 + }, + "id": 36, + "options": { + "legend": { + "calcs": [], + "displayMode": "hidden", + "placement": "right", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_node_default_events_process_time", + "instant": false, + "legendFormat": "{{event_type}} (from {{deriver}})", + "range": true, + "refId": "A" + } + ], + "title": "Events Processing Time (by derivers)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 102 + }, + "id": 38, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_node_default_frame_added_total", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Frames Added Total", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 70 + }, + { + "color": "red", + "value": 85 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 111 + }, + "id": 39, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sizing": "auto" + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_node_default_derivation_errors_total", + "instant": false, + "legendFormat": "derivation errors", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_node_default_sequencing_errors_total", + "hide": false, + "instant": false, + "legendFormat": "sequencing errors", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_node_default_storage_errors_total", + "hide": false, + "instant": false, + "legendFormat": "storage errors", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_node_default_publishing_errors_total", + "hide": false, + "instant": false, + "legendFormat": "p2p errors", + "range": true, + "refId": "D" + } + ], + "title": "op_node errors", + "type": "gauge" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 117 + }, + "id": 6, + "panels": [], + "title": "Sequencer", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 0, + "y": 118 + }, + "id": 7, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": { + "valueSize": 54 + }, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_node_default_refs_number{type=\"l2_unsafe\", layer=\"l2\"}", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "L2 Unsafe Block", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 5, + "y": 118 + }, + "id": 10, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": { + "valueSize": 54 + }, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_node_default_refs_number{type=\"l2_safe\", layer=\"l2\"}", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "L2 Safe Block", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 10, + "y": 118 + }, + "id": 9, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": { + "valueSize": 54 + }, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_node_default_refs_number{type=\"l2_finalized\", layer=\"l2\"}", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "L2 Finalized Block", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byFrameRefID", + "options": "A" + }, + "properties": [ + { + "id": "displayName", + "value": "Balance" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 9, + "x": 15, + "y": 118 + }, + "id": 13, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hoverProximity": -46, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(op_node_default_l1_reorg_depth_count[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "L1 Reorg Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 0, + "y": 122 + }, + "id": 8, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": { + "valueSize": 54 + }, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_node_default_refs_number{type=\"l1_head\"}", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "L1 Head", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 5, + "y": 122 + }, + "id": 11, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": { + "valueSize": 54 + }, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_node_default_refs_number{type=\"l1_safe\"}", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "L1 Safe Block", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 10, + "y": 122 + }, + "id": 12, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": { + "valueSize": 54 + }, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_node_default_refs_number{type=\"l1_finalized\"}", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "L1 Finalized Block", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 126 + }, + "id": 43, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "rate(op_node_default_transactions_sequenced_total[2m])", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "TPS", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 126 + }, + "id": 44, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "rate(op_batcher_default_output_bytes_total[1m])", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Bytes/sec output by channel", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 135 + }, + "id": 66, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_node_default_refs_number{layer=\"l2\", type=\"l2_finalized\"}", + "hide": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_node_default_refs_number{layer=\"l2\", type=\"l2_safe\"}", + "hide": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "B" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "$B - $A", + "hide": false, + "refId": "C", + "type": "math" + } + ], + "title": "delta(safe - finalized)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 135 + }, + "id": 67, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_node_default_refs_number{layer=\"l2\", type=\"l2_safe\"}", + "hide": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "editorMode": "code", + "expr": "op_node_default_refs_number{layer=\"l2\", type=\"l2_unsafe\"}", + "hide": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "B" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "$B - $A", + "hide": false, + "refId": "C", + "type": "math" + } + ], + "title": "delta(unsafe - safe)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 4, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "yellow", + "value": 1 + }, + { + "color": "green", + "value": 1 + } + ] + }, + "unit": "sci" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 144 + }, + "id": 4, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": { + "valueSize": 54 + }, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_proposer_default_balance", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Proposer Balance", + "type": "stat" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 148 + }, + "id": 5, + "panels": [], + "title": "Balances", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 4, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "yellow", + "value": 0.5 + }, + { + "color": "green", + "value": 1 + } + ] + }, + "unit": "sci" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 149 + }, + "id": 3, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": { + "valueSize": 54 + }, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_batcher_default_balance", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Batcher Balance", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byFrameRefID", + "options": "A" + }, + "properties": [ + { + "id": "displayName", + "value": "Balance" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 149 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hoverProximity": -46, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_batcher_default_balance", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Batcher Balance", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byFrameRefID", + "options": "A" + }, + "properties": [ + { + "id": "displayName", + "value": "Balance" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 149 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "DS_PROMETHEUS" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "op_proposer_default_balance", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Proposer Balance", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 157 + }, + "id": 31, + "panels": [], + "title": "Logs", + "type": "row" + }, + { + "datasource": { + "type": "loki", + "uid": "loki-datasource" + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 158 + }, + "id": 65, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": false, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "loki-datasource" + }, + "editorMode": "builder", + "expr": "{service_name=\"ops-bedrock-l2-1\"} |= ``", + "queryType": "range", + "refId": "A" + } + ], + "title": "op-geth logs", + "type": "logs" + }, + { + "datasource": { + "type": "loki", + "uid": "loki-datasource" + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 167 + }, + "id": 32, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": false, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "loki-datasource" + }, + "editorMode": "builder", + "expr": "{service_name=\"ops-bedrock-op-node-1\"} |= ``", + "queryType": "range", + "refId": "A" + } + ], + "title": "op-node logs", + "type": "logs" + }, + { + "datasource": { + "type": "loki", + "uid": "loki-datasource" + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 176 + }, + "id": 30, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": false, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "loki-datasource" + }, + "editorMode": "builder", + "expr": "{container=\"ops-bedrock-da-server-1\"} |= ``", + "queryType": "range", + "refId": "A" + } + ], + "title": "eigenda-proxy logs", + "type": "logs" + }, + { + "datasource": { + "type": "loki", + "uid": "loki-datasource" + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 184 + }, + "id": 24, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": false, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "pluginVersion": "11.1.0", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "loki-datasource" + }, + "editorMode": "code", + "expr": "{container=\"ops-bedrock-op-batcher-1\"}", + "queryType": "range", + "refId": "A" + } + ], + "title": "op-batcher logs", + "type": "logs" + } + ], + "refresh": "10s", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "OP Stack Compose", + "uid": "ddshn0bgt86ioc", + "version": 1, + "weekStart": "" +} diff --git a/ops-bedrock/monitoring/grafana/grafana-dashboard-overview-high-throughput.png b/ops-bedrock/monitoring/grafana/grafana-dashboard-overview-high-throughput.png new file mode 100644 index 000000000000..a50ab728ed86 Binary files /dev/null and b/ops-bedrock/monitoring/grafana/grafana-dashboard-overview-high-throughput.png differ diff --git a/ops-bedrock/monitoring/grafana/grafana.env b/ops-bedrock/monitoring/grafana/grafana.env new file mode 100644 index 000000000000..3a7446dfccfa --- /dev/null +++ b/ops-bedrock/monitoring/grafana/grafana.env @@ -0,0 +1 @@ +GF_SECURITY_ADMIN_PASSWORD=admin diff --git a/ops-bedrock/monitoring/grafana/provisioning/dashboards/all.yml b/ops-bedrock/monitoring/grafana/provisioning/dashboards/all.yml new file mode 100644 index 000000000000..e281a1e592c8 --- /dev/null +++ b/ops-bedrock/monitoring/grafana/provisioning/dashboards/all.yml @@ -0,0 +1,11 @@ +apiVersion: 1 + +providers: + - name: 'default' + orgId: 1 + folder: '' + type: file + disableDeletion: true + editable: true + options: + path: /var/lib/grafana/dashboards diff --git a/ops-bedrock/monitoring/grafana/provisioning/datasources/all.yml b/ops-bedrock/monitoring/grafana/provisioning/datasources/all.yml new file mode 100644 index 000000000000..73f7ac78a2a5 --- /dev/null +++ b/ops-bedrock/monitoring/grafana/provisioning/datasources/all.yml @@ -0,0 +1,24 @@ +apiVersion: 1 + +deleteDatasources: + - name: "Prometheus" + +datasources: + - access: "proxy" + editable: true + is_default: true + name: "Prometheus" + uid: "DS_PROMETHEUS" + org_id: 1 + type: "prometheus" + url: "http://prometheus:9090" + version: 1 + + - access: "proxy" + editable: true + name: "Loki" + uid: "loki-datasource" + org_id: 1 + type: "loki" + url: "http://loki:3200" + version: 1 diff --git a/ops-bedrock/monitoring/loki/config.yaml b/ops-bedrock/monitoring/loki/config.yaml new file mode 100644 index 000000000000..d61882a45a7c --- /dev/null +++ b/ops-bedrock/monitoring/loki/config.yaml @@ -0,0 +1,39 @@ +auth_enabled: false + +server: + http_listen_port: 3200 + +common: + instance_addr: 127.0.0.1 + path_prefix: /loki + storage: + filesystem: + chunks_directory: /loki/chunks + rules_directory: /loki/rules + replication_factor: 1 + ring: + kvstore: + store: inmemory + +schema_config: + configs: + - from: 2020-10-24 + store: tsdb + object_store: filesystem + schema: v13 + index: + prefix: index_ + period: 24h + +# By default, Loki will send anonymous, but uniquely-identifiable usage and configuration +# analytics to Grafana Labs. These statistics are sent to https://stats.grafana.org/ +# +# Statistics help us better understand how Loki is used, and they show us performance +# levels for most users. This helps us prioritize features and documentation. +# For more information on what's sent, look at +# https://github.com/grafana/loki/blob/main/pkg/usagestats/stats.go +# Refer to the buildReport method to see what goes into a report. +# +# If you would like to disable reporting, uncomment the following lines: +#analytics: +# reporting_enabled: false diff --git a/ops-bedrock/monitoring/prometheus/prometheus.yml b/ops-bedrock/monitoring/prometheus/prometheus.yml new file mode 100644 index 000000000000..09d5feb16c1e --- /dev/null +++ b/ops-bedrock/monitoring/prometheus/prometheus.yml @@ -0,0 +1,36 @@ +global: + scrape_interval: 15s + evaluation_interval: 15s + +scrape_configs: + - job_name: "l1-geth" + static_configs: + - targets: ["l1:6060"] + metrics_path: /debug/metrics/prometheus + - job_name: "l2-geth" + static_configs: + - targets: ["l2:6060"] + metrics_path: /debug/metrics/prometheus + - job_name: "op-node" + static_configs: + - targets: ["op-node:7300"] + + - job_name: "op-batcher" + # override 15s default to get fine grained info about frames and channels + # l2 blocks are built every 2s so 2s scrape should be sufficient + scrape_interval: 2s + static_configs: + - targets: ["op-batcher:7300"] + + - job_name: "op-proposer" + static_configs: + - targets: ["op-proposer:7300"] + + - job_name: "eigenda-proxy" + static_configs: + - targets: ["da-server:7300"] + + - job_name: "ethereum-metrics-exporter-l2" + scrape_interval: 2s # info about every l2 block + static_configs: + - targets: ["ethereum-metrics-exporter-l2:9090"] diff --git a/ops-bedrock/monitoring/promtail/config.yaml b/ops-bedrock/monitoring/promtail/config.yaml new file mode 100644 index 000000000000..24a1bda01050 --- /dev/null +++ b/ops-bedrock/monitoring/promtail/config.yaml @@ -0,0 +1,32 @@ +server: + http_listen_port: 9080 + grpc_listen_port: 0 + +positions: + filename: /tmp/positions.yaml + +clients: + - url: http://loki:3200/loki/api/v1/push + +scrape_configs: + # Uncomment to scrape system logs + # - job_name: system + # static_configs: + # - targets: + # - localhost + # labels: + # job: varlogs + # __path__: /var/log/*log + # This scrapes docker container logs + # copied from https://stackoverflow.com/questions/74776432/with-promtail-how-do-i-only-keep-log-messages-for-specified-docker-containers + - job_name: docker + docker_sd_configs: + - host: unix:///var/run/docker.sock + filters: + - name: name + # Filter logging to just our containers + values: ["op-batcher-*", "da-server-*", "op-node-*", "l2-*"] + relabel_configs: + - source_labels: ["__meta_docker_container_name"] + regex: "/(.*)" + target_label: "container" diff --git a/ops/docker/Dockerfile.packages b/ops/docker/Dockerfile.packages index dbd496afc8af..fd2939cb45ff 100644 --- a/ops/docker/Dockerfile.packages +++ b/ops/docker/Dockerfile.packages @@ -31,7 +31,7 @@ COPY .gitmodules ./.gitmodules RUN git submodule update --init --recursive \ && cd packages/contracts-bedrock \ - && just build \ + && just forge-build \ && echo $(git rev-parse HEAD) > .gitcommit FROM --platform=linux/amd64 debian:bookworm-20240812-slim as contracts-bedrock diff --git a/packages/contracts-bedrock/.gas-snapshot b/packages/contracts-bedrock/.gas-snapshot index 8e43cb748941..da67af9f81fc 100644 --- a/packages/contracts-bedrock/.gas-snapshot +++ b/packages/contracts-bedrock/.gas-snapshot @@ -4,10 +4,10 @@ GasBenchMark_L1BlockInterop_SetValuesInterop:test_setL1BlockValuesInterop_benchm GasBenchMark_L1BlockInterop_SetValuesInterop_Warm:test_setL1BlockValuesInterop_benchmark() (gas: 5099) GasBenchMark_L1Block_SetValuesEcotone:test_setL1BlockValuesEcotone_benchmark() (gas: 158531) GasBenchMark_L1Block_SetValuesEcotone_Warm:test_setL1BlockValuesEcotone_benchmark() (gas: 7597) -GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 369242) -GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2967382) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 564356) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4076571) +GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 369245) +GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2967385) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 564368) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4076583) GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 467019) GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3512723) GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 72618) diff --git a/packages/contracts-bedrock/deploy-config/devnetL1-template.json b/packages/contracts-bedrock/deploy-config/devnetL1-template.json index d241c3186a08..99960fda185f 100644 --- a/packages/contracts-bedrock/deploy-config/devnetL1-template.json +++ b/packages/contracts-bedrock/deploy-config/devnetL1-template.json @@ -14,7 +14,7 @@ "l2OutputOracleStartingBlockNumber": 0, "l2OutputOracleProposer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", "l2OutputOracleChallenger": "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65", - "l2GenesisBlockGasLimit": "0x1c9c380", + "l2GenesisBlockGasLimit": "0x3938700", "l1BlockTime": 6, "baseFeeVaultRecipient": "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955", "l1FeeVaultRecipient": "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f", @@ -41,7 +41,7 @@ "governanceTokenOwner": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720", "eip1559Denominator": 50, "eip1559DenominatorCanyon": 250, - "eip1559Elasticity": 6, + "eip1559Elasticity": 2, "l1GenesisBlockTimestamp": "0x123", "l2GenesisRegolithTimeOffset": "0x0", "l2GenesisCanyonTimeOffset": "0x0", diff --git a/packages/contracts-bedrock/justfile b/packages/contracts-bedrock/justfile index a9c621cf240c..06228b3630d8 100644 --- a/packages/contracts-bedrock/justfile +++ b/packages/contracts-bedrock/justfile @@ -19,13 +19,16 @@ dep-status: prebuild: ./scripts/checks/check-foundry-install.sh -# Builds the contracts. -build: prebuild +# Core forge build command +forge-build: forge build +# Builds the contracts. +build: prebuild lint-fix-no-fail forge-build interfaces-check-no-build + # Builds the go-ffi tool for contract tests. build-go-ffi: - cd scripts/go-ffi && go build + cd ./scripts/go-ffi && go build # Cleans build artifacts and deployments. clean: @@ -84,10 +87,6 @@ gas-snapshot-no-build: # Generates a gas snapshot. gas-snapshot: build-go-ffi gas-snapshot-no-build -# Checks that the state diff is up to date. -statediff: - ./scripts/utils/statediff.sh && git diff --exit-code - # Generates default Kontrol summary. kontrol-summary: ./test/kontrol/scripts/make-summary-deployment.sh @@ -141,7 +140,7 @@ snapshots-check: # Checks interface correctness without building. interfaces-check-no-build: - ./scripts/checks/check-interfaces.sh + go run ./scripts/checks/interfaces # Checks that all interfaces are appropriately named and accurately reflect the corresponding # contract that they're meant to represent. We run "clean" before building because leftover @@ -176,6 +175,13 @@ lint-forge-tests-check: lint-check: forge fmt --check +# Checks for unused imports in Solidity contracts. Does not build contracts. +unused-imports-check-no-build: + go run ./scripts/checks/unused-imports + +# Checks for unused imports in Solidity contracts. +unused-imports-check: build unused-imports-check-no-build + # Checks that the deploy configs are valid. validate-deploy-configs: ./scripts/checks/check-deploy-configs.sh @@ -189,8 +195,17 @@ validate-spacers: build validate-spacers-no-build # TODO: Also run lint-forge-tests-check but we need to fix the test names first. # Runs all checks. -check: gas-snapshot-check-no-build kontrol-deployment-check snapshots-check-no-build lint-check semver-diff-check-no-build semver-natspec-check-no-build validate-deploy-configs validate-spacers-no-build interfaces-check-no-build - +check: + @just gas-snapshot-check-no-build \ + unused-imports-check-no-build \ + kontrol-deployment-check \ + snapshots-check-no-build \ + lint-check \ + semver-diff-check-no-build \ + semver-natspec-check-no-build \ + validate-deploy-configs \ + validate-spacers-no-build \ + interfaces-check-no-build ######################################################## # DEV TOOLS # @@ -207,5 +222,11 @@ pre-pr-no-build: build-go-ffi build lint gas-snapshot-no-build snapshots-no-buil lint-fix: forge fmt +# Fixes linting errors but doesn't fail if there are syntax errors. Useful for build command +# because the output of forge fmt can sometimes be difficult to understand but if there's a syntax +# error the build will fail anyway and provide more context about what's wrong. +lint-fix-no-fail: + forge fmt || true + # Fixes linting errors and checks that the code is correctly formatted. lint: lint-fix lint-check diff --git a/packages/contracts-bedrock/scripts/Artifacts.s.sol b/packages/contracts-bedrock/scripts/Artifacts.s.sol index bfac0c367bfc..0069bfa30f94 100644 --- a/packages/contracts-bedrock/scripts/Artifacts.s.sol +++ b/packages/contracts-bedrock/scripts/Artifacts.s.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.0; import { console2 as console } from "forge-std/console2.sol"; import { stdJson } from "forge-std/StdJson.sol"; import { Vm } from "forge-std/Vm.sol"; -import { Executables } from "scripts/libraries/Executables.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { Config } from "scripts/libraries/Config.sol"; import { StorageSlot } from "scripts/libraries/ForgeArtifacts.sol"; diff --git a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol index c8476b8a2e50..3179ea3d6426 100644 --- a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol +++ b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol @@ -49,6 +49,7 @@ contract DeployImplementationsInput is BaseDeployIO { uint256 internal _challengePeriodSeconds; uint256 internal _proofMaturityDelaySeconds; uint256 internal _disputeGameFinalityDelaySeconds; + uint256 internal _mipsVersion; // The release version to set OPCM implementations for, of the format `op-contracts/vX.Y.Z`. string internal _release; @@ -75,6 +76,8 @@ contract DeployImplementationsInput is BaseDeployIO { _proofMaturityDelaySeconds = _value; } else if (_sel == this.disputeGameFinalityDelaySeconds.selector) { _disputeGameFinalityDelaySeconds = _value; + } else if (_sel == this.mipsVersion.selector) { + _mipsVersion = _value; } else { revert("DeployImplementationsInput: unknown selector"); } @@ -133,6 +136,11 @@ contract DeployImplementationsInput is BaseDeployIO { return _disputeGameFinalityDelaySeconds; } + function mipsVersion() public view returns (uint256) { + require(_mipsVersion != 0, "DeployImplementationsInput: not set"); + return _mipsVersion; + } + function release() public view returns (string memory) { require(!LibString.eq(_release, ""), "DeployImplementationsInput: not set"); return _release; @@ -221,7 +229,7 @@ contract DeployImplementationsOutput is BaseDeployIO { function opcmProxy() public returns (OPContractsManager) { DeployUtils.assertValidContractAddress(address(_opcmProxy)); - DeployUtils.assertImplementationSet(address(_opcmProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_opcmProxy)); return _opcmProxy; } @@ -959,11 +967,12 @@ contract DeployImplementations is Script { if (existingImplementation != address(0)) { singleton = IMIPS(payable(existingImplementation)); } else if (isDevelopRelease(release)) { + uint256 mipsVersion = _dii.mipsVersion(); IPreimageOracle preimageOracle = IPreimageOracle(address(_dio.preimageOracleSingleton())); vm.broadcast(msg.sender); singleton = IMIPS( DeployUtils.create1({ - _name: "MIPS", + _name: mipsVersion == 1 ? "MIPS" : "MIPS2", _args: DeployUtils.encodeConstructor(abi.encodeCall(IMIPS.__constructor__, (preimageOracle))) }) ); diff --git a/packages/contracts-bedrock/scripts/DeployOPChain.s.sol b/packages/contracts-bedrock/scripts/DeployOPChain.s.sol index 140c2bba6b65..f88469b7ead5 100644 --- a/packages/contracts-bedrock/scripts/DeployOPChain.s.sol +++ b/packages/contracts-bedrock/scripts/DeployOPChain.s.sol @@ -25,7 +25,7 @@ import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory. import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; import { IPermissionedDisputeGame } from "src/dispute/interfaces/IPermissionedDisputeGame.sol"; -import { Claim, Duration, GameType, GameTypes, Hash, OutputRoot } from "src/dispute/lib/Types.sol"; +import { Claim, Duration, GameType, GameTypes, Hash } from "src/dispute/lib/Types.sol"; import { OPContractsManager } from "src/L1/OPContractsManager.sol"; import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol"; @@ -171,7 +171,7 @@ contract DeployOPChainInput is BaseDeployIO { function opcmProxy() public returns (OPContractsManager) { require(address(_opcmProxy) != address(0), "DeployOPChainInput: not set"); DeployUtils.assertValidContractAddress(address(_opcmProxy)); - DeployUtils.assertImplementationSet(address(_opcmProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_opcmProxy)); return _opcmProxy; } @@ -286,43 +286,51 @@ contract DeployOPChainOutput is BaseDeployIO { return _addressManager; } - function l1ERC721BridgeProxy() public view returns (IL1ERC721Bridge) { + function l1ERC721BridgeProxy() public returns (IL1ERC721Bridge) { DeployUtils.assertValidContractAddress(address(_l1ERC721BridgeProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_l1ERC721BridgeProxy)); return _l1ERC721BridgeProxy; } - function systemConfigProxy() public view returns (ISystemConfig) { + function systemConfigProxy() public returns (ISystemConfig) { DeployUtils.assertValidContractAddress(address(_systemConfigProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_systemConfigProxy)); return _systemConfigProxy; } - function optimismMintableERC20FactoryProxy() public view returns (IOptimismMintableERC20Factory) { + function optimismMintableERC20FactoryProxy() public returns (IOptimismMintableERC20Factory) { DeployUtils.assertValidContractAddress(address(_optimismMintableERC20FactoryProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_optimismMintableERC20FactoryProxy)); return _optimismMintableERC20FactoryProxy; } - function l1StandardBridgeProxy() public view returns (IL1StandardBridge) { + function l1StandardBridgeProxy() public returns (IL1StandardBridge) { DeployUtils.assertValidContractAddress(address(_l1StandardBridgeProxy)); + DeployUtils.assertL1ChugSplashImplementationSet(address(_l1StandardBridgeProxy)); return _l1StandardBridgeProxy; } function l1CrossDomainMessengerProxy() public view returns (IL1CrossDomainMessenger) { DeployUtils.assertValidContractAddress(address(_l1CrossDomainMessengerProxy)); + DeployUtils.assertResolvedDelegateProxyImplementationSet("OVM_L1CrossDomainMessenger", addressManager()); return _l1CrossDomainMessengerProxy; } - function optimismPortalProxy() public view returns (IOptimismPortal2) { + function optimismPortalProxy() public returns (IOptimismPortal2) { DeployUtils.assertValidContractAddress(address(_optimismPortalProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_optimismPortalProxy)); return _optimismPortalProxy; } - function disputeGameFactoryProxy() public view returns (IDisputeGameFactory) { + function disputeGameFactoryProxy() public returns (IDisputeGameFactory) { DeployUtils.assertValidContractAddress(address(_disputeGameFactoryProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_disputeGameFactoryProxy)); return _disputeGameFactoryProxy; } - function anchorStateRegistryProxy() public view returns (IAnchorStateRegistry) { + function anchorStateRegistryProxy() public returns (IAnchorStateRegistry) { DeployUtils.assertValidContractAddress(address(_anchorStateRegistryProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_anchorStateRegistryProxy)); return _anchorStateRegistryProxy; } @@ -341,8 +349,9 @@ contract DeployOPChainOutput is BaseDeployIO { return _permissionedDisputeGame; } - function delayedWETHPermissionedGameProxy() public view returns (IDelayedWETH) { + function delayedWETHPermissionedGameProxy() public returns (IDelayedWETH) { DeployUtils.assertValidContractAddress(address(_delayedWETHPermissionedGameProxy)); + DeployUtils.assertERC1967ImplementationSet(address(_delayedWETHPermissionedGameProxy)); return _delayedWETHPermissionedGameProxy; } @@ -366,6 +375,8 @@ contract DeployOPChainOutput is BaseDeployIO { assertValidOptimismPortal(_doi); assertValidPermissionedDisputeGame(_doi); assertValidSystemConfig(_doi); + assertValidAddressManager(_doi); + assertValidOPChainProxyAdmin(_doi); } function assertValidPermissionedDisputeGame(DeployOPChainInput _doi) internal { @@ -387,6 +398,11 @@ contract DeployOPChainOutput is BaseDeployIO { require(address(game.weth()) == address(delayedWETHPermissionedGameProxy()), "DPG-40"); require(address(game.anchorStateRegistry()) == address(anchorStateRegistryProxy()), "DPG-50"); require(game.l2ChainId() == _doi.l2ChainId(), "DPG-60"); + require(game.l2BlockNumber() == 0, "DPG-70"); + require(Duration.unwrap(game.clockExtension()) == 10800, "DPG-80"); + require(Duration.unwrap(game.maxClockDuration()) == 302400, "DPG-110"); + require(game.splitDepth() == 30, "DPG-90"); + require(game.maxGameDepth() == 73, "DPG-100"); } function assertValidAnchorStateRegistryProxy(DeployOPChainInput) internal { @@ -405,9 +421,13 @@ contract DeployOPChainOutput is BaseDeployIO { require( address(anchorStateRegistryProxy().disputeGameFactory()) == address(disputeGameFactoryProxy()), "ANCHORP-30" ); + + (Hash actualRoot,) = anchorStateRegistryProxy().anchors(GameTypes.PERMISSIONED_CANNON); + bytes32 expectedRoot = 0xdead000000000000000000000000000000000000000000000000000000000000; + require(Hash.unwrap(actualRoot) == expectedRoot, "ANCHORP-40"); } - function assertValidAnchorStateRegistryImpl(DeployOPChainInput) internal view { + function assertValidAnchorStateRegistryImpl(DeployOPChainInput) internal { IAnchorStateRegistry registry = anchorStateRegistryImpl(); DeployUtils.assertInitialized({ _contractAddress: address(registry), _slot: 0, _offset: 0 }); @@ -483,7 +503,7 @@ contract DeployOPChainOutput is BaseDeployIO { require(address(bridge.superchainConfig()) == address(_doi.opcmProxy().superchainConfig()), "L1SB-50"); } - function assertValidOptimismMintableERC20Factory(DeployOPChainInput) internal view { + function assertValidOptimismMintableERC20Factory(DeployOPChainInput) internal { IOptimismMintableERC20Factory factory = optimismMintableERC20FactoryProxy(); DeployUtils.assertInitialized({ _contractAddress: address(factory), _slot: 0, _offset: 0 }); @@ -521,7 +541,7 @@ contract DeployOPChainOutput is BaseDeployIO { require(vm.load(address(portal), bytes32(uint256(61))) == bytes32(0)); } - function assertValidDisputeGameFactory(DeployOPChainInput _doi) internal view { + function assertValidDisputeGameFactory(DeployOPChainInput _doi) internal { IDisputeGameFactory factory = disputeGameFactoryProxy(); DeployUtils.assertInitialized({ _contractAddress: address(factory), _slot: 0, _offset: 0 }); @@ -542,6 +562,61 @@ contract DeployOPChainOutput is BaseDeployIO { address admin = proxy.admin(); require(admin == address(opChainProxyAdmin()), "DWETH-20"); } + + function assertValidAddressManager(DeployOPChainInput) internal view { + require(addressManager().owner() == address(opChainProxyAdmin()), "AM-10"); + } + + function assertValidOPChainProxyAdmin(DeployOPChainInput _doi) internal { + IProxyAdmin admin = opChainProxyAdmin(); + require(admin.owner() == _doi.opChainProxyAdminOwner(), "OPCPA-10"); + require( + admin.getProxyImplementation(address(l1CrossDomainMessengerProxy())) + == DeployUtils.assertResolvedDelegateProxyImplementationSet("OVM_L1CrossDomainMessenger", addressManager()), + "OPCPA-20" + ); + require(address(admin.addressManager()) == address(addressManager()), "OPCPA-30"); + require( + admin.getProxyImplementation(address(l1StandardBridgeProxy())) + == DeployUtils.assertL1ChugSplashImplementationSet(address(l1StandardBridgeProxy())), + "OPCPA-40" + ); + require( + admin.getProxyImplementation(address(l1ERC721BridgeProxy())) + == DeployUtils.assertERC1967ImplementationSet(address(l1ERC721BridgeProxy())), + "OPCPA-50" + ); + require( + admin.getProxyImplementation(address(optimismPortalProxy())) + == DeployUtils.assertERC1967ImplementationSet(address(optimismPortalProxy())), + "OPCPA-60" + ); + require( + admin.getProxyImplementation(address(systemConfigProxy())) + == DeployUtils.assertERC1967ImplementationSet(address(systemConfigProxy())), + "OPCPA-70" + ); + require( + admin.getProxyImplementation(address(optimismMintableERC20FactoryProxy())) + == DeployUtils.assertERC1967ImplementationSet(address(optimismMintableERC20FactoryProxy())), + "OPCPA-80" + ); + require( + admin.getProxyImplementation(address(disputeGameFactoryProxy())) + == DeployUtils.assertERC1967ImplementationSet(address(disputeGameFactoryProxy())), + "OPCPA-90" + ); + require( + admin.getProxyImplementation(address(delayedWETHPermissionedGameProxy())) + == DeployUtils.assertERC1967ImplementationSet(address(delayedWETHPermissionedGameProxy())), + "OPCPA-100" + ); + require( + admin.getProxyImplementation(address(anchorStateRegistryProxy())) + == DeployUtils.assertERC1967ImplementationSet(address(anchorStateRegistryProxy())), + "OPCPA-110" + ); + } } contract DeployOPChain is Script { diff --git a/packages/contracts-bedrock/scripts/DeploySuperchain.s.sol b/packages/contracts-bedrock/scripts/DeploySuperchain.s.sol index 913bc510d5bb..38c87f623443 100644 --- a/packages/contracts-bedrock/scripts/DeploySuperchain.s.sol +++ b/packages/contracts-bedrock/scripts/DeploySuperchain.s.sol @@ -192,8 +192,10 @@ contract DeploySuperchainOutput is BaseDeployIO { address actualProtocolVersionsImpl = IProxy(payable(address(_protocolVersionsProxy))).implementation(); vm.stopPrank(); - require(actualSuperchainConfigImpl == address(_superchainConfigImpl), "100"); - require(actualProtocolVersionsImpl == address(_protocolVersionsImpl), "200"); + require(actualSuperchainConfigImpl == address(_superchainConfigImpl), "100"); // nosemgrep: + // sol-style-malformed-require + require(actualProtocolVersionsImpl == address(_protocolVersionsImpl), "200"); // nosemgrep: + // sol-style-malformed-require assertValidDeploy(_dsi); } diff --git a/packages/contracts-bedrock/scripts/L2Genesis.s.sol b/packages/contracts-bedrock/scripts/L2Genesis.s.sol index ae4773a2eebd..245a46a2d2af 100644 --- a/packages/contracts-bedrock/scripts/L2Genesis.s.sol +++ b/packages/contracts-bedrock/scripts/L2Genesis.s.sol @@ -2,15 +2,12 @@ pragma solidity 0.8.15; // Testing -import { Script } from "forge-std/Script.sol"; import { console2 as console } from "forge-std/console2.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; // Scripts import { Deployer } from "scripts/deploy/Deployer.sol"; import { Config, OutputMode, OutputModeUtils, Fork, ForkUtils, LATEST_FORK } from "scripts/libraries/Config.sol"; -import { Artifacts } from "scripts/Artifacts.s.sol"; -import { DeployConfig } from "scripts/deploy/DeployConfig.s.sol"; import { Process } from "scripts/libraries/Process.sol"; import { SetPreinstalls } from "scripts/SetPreinstalls.s.sol"; @@ -20,12 +17,12 @@ import { BaseFeeVault } from "src/L2/BaseFeeVault.sol"; import { L1FeeVault } from "src/L2/L1FeeVault.sol"; import { OptimismSuperchainERC20Beacon } from "src/L2/OptimismSuperchainERC20Beacon.sol"; import { OptimismMintableERC721Factory } from "src/universal/OptimismMintableERC721Factory.sol"; -import { FeeVault } from "src/universal/FeeVault.sol"; import { GovernanceToken } from "src/governance/GovernanceToken.sol"; // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; import { Preinstalls } from "src/libraries/Preinstalls.sol"; +import { Types } from "src/libraries/Types.sol"; // Interfaces import { IOptimismMintableERC20Factory } from "src/universal/interfaces/IOptimismMintableERC20Factory.sol"; @@ -344,7 +341,7 @@ contract L2Genesis is Deployer { SequencerFeeVault vault = new SequencerFeeVault({ _recipient: cfg.sequencerFeeVaultRecipient(), _minWithdrawalAmount: cfg.sequencerFeeVaultMinimumWithdrawalAmount(), - _withdrawalNetwork: FeeVault.WithdrawalNetwork(cfg.sequencerFeeVaultWithdrawalNetwork()) + _withdrawalNetwork: Types.WithdrawalNetwork(cfg.sequencerFeeVaultWithdrawalNetwork()) }); address impl = Predeploys.predeployToCodeNamespace(Predeploys.SEQUENCER_FEE_WALLET); @@ -428,7 +425,7 @@ contract L2Genesis is Deployer { BaseFeeVault vault = new BaseFeeVault({ _recipient: cfg.baseFeeVaultRecipient(), _minWithdrawalAmount: cfg.baseFeeVaultMinimumWithdrawalAmount(), - _withdrawalNetwork: FeeVault.WithdrawalNetwork(cfg.baseFeeVaultWithdrawalNetwork()) + _withdrawalNetwork: Types.WithdrawalNetwork(cfg.baseFeeVaultWithdrawalNetwork()) }); address impl = Predeploys.predeployToCodeNamespace(Predeploys.BASE_FEE_VAULT); @@ -445,7 +442,7 @@ contract L2Genesis is Deployer { L1FeeVault vault = new L1FeeVault({ _recipient: cfg.l1FeeVaultRecipient(), _minWithdrawalAmount: cfg.l1FeeVaultMinimumWithdrawalAmount(), - _withdrawalNetwork: FeeVault.WithdrawalNetwork(cfg.l1FeeVaultWithdrawalNetwork()) + _withdrawalNetwork: Types.WithdrawalNetwork(cfg.l1FeeVaultWithdrawalNetwork()) }); address impl = Predeploys.predeployToCodeNamespace(Predeploys.L1_FEE_VAULT); diff --git a/packages/contracts-bedrock/scripts/autogen/SemverLock.s.sol b/packages/contracts-bedrock/scripts/autogen/SemverLock.s.sol index bd2b5534b7fc..1d5aeb963e3d 100644 --- a/packages/contracts-bedrock/scripts/autogen/SemverLock.s.sol +++ b/packages/contracts-bedrock/scripts/autogen/SemverLock.s.sol @@ -48,7 +48,7 @@ contract SemverLock is Script { string memory artifactFiles = string(Process.run(commands)); string[] memory files = stdJson.readStringArray(artifactFiles, ""); - require(files.length > 0, string.concat("No artifacts found for ", contractName)); + require(files.length > 0, string.concat("SemverLock: no artifacts found for ", contractName)); string memory fileName = files[0]; // Parse the artifact to get the contract's initcode hash. diff --git a/packages/contracts-bedrock/scripts/checks/check-interfaces.sh b/packages/contracts-bedrock/scripts/checks/check-interfaces.sh index 174c26969058..c37783a08b90 100755 --- a/packages/contracts-bedrock/scripts/checks/check-interfaces.sh +++ b/packages/contracts-bedrock/scripts/checks/check-interfaces.sh @@ -75,6 +75,12 @@ EXCLUDE_CONTRACTS=( "ICrossL2Inbox" "ISystemConfigInterop" + # Enums need to be normalized + "ISequencerFeeVault" + "IBaseFeeVault" + "IL1FeeVault" + "IFeeVault" + # Solidity complains about receive but contract doens't have it. "IResolvedDelegateProxy" ) diff --git a/packages/contracts-bedrock/scripts/checks/interfaces/main.go b/packages/contracts-bedrock/scripts/checks/interfaces/main.go new file mode 100644 index 000000000000..004f1d5c03cd --- /dev/null +++ b/packages/contracts-bedrock/scripts/checks/interfaces/main.go @@ -0,0 +1,354 @@ +package main + +import ( + "encoding/json" + "errors" + "fmt" + "os" + "path/filepath" + "runtime" + "sort" + "strings" + "sync" + "sync/atomic" + + "github.com/google/go-cmp/cmp" +) + +var excludeContracts = []string{ + // External dependencies + "IERC20", "IERC721", "IERC721Enumerable", "IERC721Upgradeable", "IERC721Metadata", + "IERC165", "IERC165Upgradeable", "ERC721TokenReceiver", "ERC1155TokenReceiver", + "ERC777TokensRecipient", "Guard", "IProxy", "Vm", "VmSafe", "IMulticall3", + "IERC721TokenReceiver", "IProxyCreationCallback", "IBeacon", + + // EAS + "IEAS", "ISchemaResolver", "ISchemaRegistry", + + // TODO: Interfaces that need to be fixed + "IInitializable", "IPreimageOracle", "ILegacyMintableERC20", "IOptimismMintableERC20", + "IOptimismMintableERC721", "IOptimismSuperchainERC20", "MintableAndBurnable", + "KontrolCheatsBase", "IWETH", "IDelayedWETH", "IL2ToL2CrossDomainMessenger", + "ICrossL2Inbox", "ISystemConfigInterop", "IResolvedDelegateProxy", +} + +type ContractDefinition struct { + ContractKind string `json:"contractKind"` + Name string `json:"name"` +} + +type ASTNode struct { + NodeType string `json:"nodeType"` + Literals []string `json:"literals,omitempty"` + ContractDefinition +} + +type ArtifactAST struct { + Nodes []ASTNode `json:"nodes"` +} + +type Artifact struct { + AST ArtifactAST `json:"ast"` + ABI json.RawMessage `json:"abi"` +} + +func main() { + if err := run(); err != nil { + writeStderr("an error occurred: %v", err) + os.Exit(1) + } +} + +func writeStderr(msg string, args ...any) { + _, _ = fmt.Fprintf(os.Stderr, msg+"\n", args...) +} + +func run() error { + cwd, err := os.Getwd() + if err != nil { + return fmt.Errorf("failed to get current working directory: %w", err) + } + + artifactsDir := filepath.Join(cwd, "forge-artifacts") + + artifactFiles, err := glob(artifactsDir, ".json") + if err != nil { + return fmt.Errorf("failed to get artifact files: %w", err) + } + + // Remove duplicates from artifactFiles + uniqueArtifacts := make(map[string]string) + for contractName, artifactPath := range artifactFiles { + baseName := strings.Split(contractName, ".")[0] + uniqueArtifacts[baseName] = artifactPath + } + + var hasErr int32 + var outMtx sync.Mutex + fail := func(msg string, args ...any) { + outMtx.Lock() + writeStderr("❌ "+msg, args...) + outMtx.Unlock() + atomic.StoreInt32(&hasErr, 1) + } + + sem := make(chan struct{}, runtime.NumCPU()) + for contractName, artifactPath := range uniqueArtifacts { + contractName := contractName + artifactPath := artifactPath + + sem <- struct{}{} + + go func() { + defer func() { + <-sem + }() + + if err := processArtifact(contractName, artifactPath, artifactsDir, fail); err != nil { + fail("%s: %v", contractName, err) + } + }() + } + + for i := 0; i < cap(sem); i++ { + sem <- struct{}{} + } + + if atomic.LoadInt32(&hasErr) == 1 { + return errors.New("interface check failed, see logs above") + } + + return nil +} + +func processArtifact(contractName, artifactPath, artifactsDir string, fail func(string, ...any)) error { + if isExcluded(contractName) { + return nil + } + + artifact, err := readArtifact(artifactPath) + if err != nil { + return fmt.Errorf("failed to read artifact: %w", err) + } + + contractDef := getContractDefinition(artifact, contractName) + if contractDef == nil { + return nil // Skip processing if contract definition is not found + } + + if contractDef.ContractKind != "interface" { + return nil + } + + if !strings.HasPrefix(contractName, "I") { + fail("%s: Interface does not start with 'I'", contractName) + } + + semver, err := getContractSemver(artifact) + if err != nil { + return err + } + + if semver != "solidity^0.8.0" { + fail("%s: Interface does not have correct compiler version (MUST be exactly solidity ^0.8.0)", contractName) + } + + contractBasename := contractName[1:] + correspondingContractFile := filepath.Join(artifactsDir, contractBasename+".sol", contractBasename+".json") + + if _, err := os.Stat(correspondingContractFile); errors.Is(err, os.ErrNotExist) { + return nil + } + + contractArtifact, err := readArtifact(correspondingContractFile) + if err != nil { + return fmt.Errorf("failed to read corresponding contract artifact: %w", err) + } + + interfaceABI := artifact.ABI + contractABI := contractArtifact.ABI + + normalizedInterfaceABI, err := normalizeABI(interfaceABI) + if err != nil { + return fmt.Errorf("failed to normalize interface ABI: %w", err) + } + + normalizedContractABI, err := normalizeABI(contractABI) + if err != nil { + return fmt.Errorf("failed to normalize contract ABI: %w", err) + } + + match, err := compareABIs(normalizedInterfaceABI, normalizedContractABI) + if err != nil { + return fmt.Errorf("failed to compare ABIs: %w", err) + } + if !match { + fail("%s: Differences found in ABI between interface and actual contract", contractName) + } + + return nil +} + +func readArtifact(path string) (*Artifact, error) { + file, err := os.Open(path) + if err != nil { + return nil, fmt.Errorf("failed to open artifact file: %w", err) + } + defer file.Close() + + var artifact Artifact + if err := json.NewDecoder(file).Decode(&artifact); err != nil { + return nil, fmt.Errorf("failed to parse artifact file: %w", err) + } + + return &artifact, nil +} + +func getContractDefinition(artifact *Artifact, contractName string) *ContractDefinition { + for _, node := range artifact.AST.Nodes { + if node.NodeType == "ContractDefinition" && node.Name == contractName { + return &node.ContractDefinition + } + } + return nil +} + +func getContractSemver(artifact *Artifact) (string, error) { + for _, node := range artifact.AST.Nodes { + if node.NodeType == "PragmaDirective" { + return strings.Join(node.Literals, ""), nil + } + } + return "", errors.New("semver not found") +} + +func normalizeABI(abi json.RawMessage) (json.RawMessage, error) { + var abiData []map[string]interface{} + if err := json.Unmarshal(abi, &abiData); err != nil { + return nil, err + } + + hasConstructor := false + for i := range abiData { + normalizeABIItem(abiData[i]) + if abiData[i]["type"] == "constructor" { + hasConstructor = true + } + } + + // Add an empty constructor if it doesn't exist + if !hasConstructor { + emptyConstructor := map[string]interface{}{ + "type": "constructor", + "stateMutability": "nonpayable", + "inputs": []interface{}{}, + } + abiData = append(abiData, emptyConstructor) + } + + return json.Marshal(abiData) +} + +func normalizeABIItem(item map[string]interface{}) { + for key, value := range item { + switch v := value.(type) { + case string: + if key == "internalType" { + item[key] = normalizeInternalType(v) + } + case map[string]interface{}: + normalizeABIItem(v) + case []interface{}: + for _, elem := range v { + if elemMap, ok := elem.(map[string]interface{}); ok { + normalizeABIItem(elemMap) + } + } + } + } + + if item["type"] == "function" && item["name"] == "__constructor__" { + item["type"] = "constructor" + delete(item, "name") + delete(item, "outputs") + } +} + +func normalizeInternalType(internalType string) string { + internalType = strings.ReplaceAll(internalType, "contract I", "contract ") + internalType = strings.ReplaceAll(internalType, "enum I", "enum ") + internalType = strings.ReplaceAll(internalType, "struct I", "struct ") + return internalType +} + +func compareABIs(abi1, abi2 json.RawMessage) (bool, error) { + var data1, data2 []map[string]interface{} + + if err := json.Unmarshal(abi1, &data1); err != nil { + return false, fmt.Errorf("error unmarshalling first ABI: %w", err) + } + + if err := json.Unmarshal(abi2, &data2); err != nil { + return false, fmt.Errorf("error unmarshalling second ABI: %w", err) + } + + // Sort the ABI data + sort.Slice(data1, func(i, j int) bool { + return abiItemLess(data1[i], data1[j]) + }) + sort.Slice(data2, func(i, j int) bool { + return abiItemLess(data2[i], data2[j]) + }) + + // Compare using go-cmp + diff := cmp.Diff(data1, data2) + if diff != "" { + return false, nil + } + return true, nil +} + +func abiItemLess(a, b map[string]interface{}) bool { + aType := getString(a, "type") + bType := getString(b, "type") + + if aType != bType { + return aType < bType + } + + aName := getString(a, "name") + bName := getString(b, "name") + return aName < bName +} + +func getString(m map[string]interface{}, key string) string { + if v, ok := m[key]; ok { + if s, ok := v.(string); ok { + return s + } + } + return "" +} + +func isExcluded(contractName string) bool { + for _, exclude := range excludeContracts { + if exclude == contractName { + return true + } + } + return false +} + +func glob(dir string, ext string) (map[string]string, error) { + out := make(map[string]string) + err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if !info.IsDir() && filepath.Ext(path) == ext { + out[strings.TrimSuffix(filepath.Base(path), ext)] = path + } + return nil + }) + if err != nil { + return nil, fmt.Errorf("failed to walk directory: %w", err) + } + return out, nil +} diff --git a/packages/contracts-bedrock/scripts/checks/interfaces/main_test.go b/packages/contracts-bedrock/scripts/checks/interfaces/main_test.go new file mode 100644 index 000000000000..d1c9237e4722 --- /dev/null +++ b/packages/contracts-bedrock/scripts/checks/interfaces/main_test.go @@ -0,0 +1,295 @@ +package main + +import ( + "encoding/json" + "reflect" + "testing" +) + +func TestGetContractDefinition(t *testing.T) { + artifact := &Artifact{ + AST: ArtifactAST{ + Nodes: []ASTNode{ + {NodeType: "ContractDefinition", ContractDefinition: ContractDefinition{ContractKind: "interface", Name: "ITest"}}, + {NodeType: "ContractDefinition", ContractDefinition: ContractDefinition{ContractKind: "contract", Name: "Test"}}, + {NodeType: "ContractDefinition", ContractDefinition: ContractDefinition{ContractKind: "library", Name: "TestLib"}}, + }, + }, + } + + tests := []struct { + name string + contractName string + want *ContractDefinition + }{ + {"Find interface", "ITest", &ContractDefinition{ContractKind: "interface", Name: "ITest"}}, + {"Find contract", "Test", &ContractDefinition{ContractKind: "contract", Name: "Test"}}, + {"Find library", "TestLib", &ContractDefinition{ContractKind: "library", Name: "TestLib"}}, + {"Not found", "NonExistent", nil}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := getContractDefinition(artifact, tt.contractName) + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("getContractDefinition() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetContractSemver(t *testing.T) { + tests := []struct { + name string + artifact *Artifact + want string + wantErr bool + }{ + { + name: "Valid semver", + artifact: &Artifact{ + AST: ArtifactAST{ + Nodes: []ASTNode{ + {NodeType: "PragmaDirective", Literals: []string{"solidity", "^", "0.8.0"}}, + }, + }, + }, + want: "solidity^0.8.0", + wantErr: false, + }, + { + name: "Multiple pragmas", + artifact: &Artifact{ + AST: ArtifactAST{ + Nodes: []ASTNode{ + {NodeType: "PragmaDirective", Literals: []string{"solidity", "^", "0.8.0"}}, + {NodeType: "PragmaDirective", Literals: []string{"abicoder", "v2"}}, + }, + }, + }, + want: "solidity^0.8.0", + wantErr: false, + }, + { + name: "No semver", + artifact: &Artifact{ + AST: ArtifactAST{ + Nodes: []ASTNode{ + {NodeType: "ContractDefinition"}, + }, + }, + }, + want: "", + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := getContractSemver(tt.artifact) + if (err != nil) != tt.wantErr { + t.Errorf("getContractSemver() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("getContractSemver() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestNormalizeABI(t *testing.T) { + tests := []struct { + name string + abi string + want string + }{ + { + name: "Replace interface types and add constructor", + abi: `[{"inputs":[{"internalType":"contract ITest","name":"test","type":"address"}],"type":"function"}]`, + want: `[{"inputs":[{"internalType":"contract Test","name":"test","type":"address"}],"type":"function"},{"inputs":[],"stateMutability":"nonpayable","type":"constructor"}]`, + }, + { + name: "Convert __constructor__", + abi: `[{"type":"function","name":"__constructor__","inputs":[],"stateMutability":"nonpayable","outputs":[]}]`, + want: `[{"type":"constructor","inputs":[],"stateMutability":"nonpayable"}]`, + }, + { + name: "Keep existing constructor", + abi: `[{"type":"constructor","inputs":[{"name":"param","type":"uint256"}]},{"type":"function","name":"test"}]`, + want: `[{"type":"constructor","inputs":[{"name":"param","type":"uint256"}]},{"type":"function","name":"test"}]`, + }, + { + name: "Replace multiple interface types", + abi: `[{"inputs":[{"internalType":"contract ITest1","name":"test1","type":"address"},{"internalType":"contract ITest2","name":"test2","type":"address"}],"type":"function"}]`, + want: `[{"inputs":[{"internalType":"contract Test1","name":"test1","type":"address"},{"internalType":"contract Test2","name":"test2","type":"address"}],"type":"function"},{"inputs":[],"stateMutability":"nonpayable","type":"constructor"}]`, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := normalizeABI(json.RawMessage(tt.abi)) + if err != nil { + t.Errorf("normalizeABI() error = %v", err) + return + } + var gotJSON, wantJSON interface{} + if err := json.Unmarshal(got, &gotJSON); err != nil { + t.Errorf("Error unmarshalling got JSON: %v", err) + return + } + if err := json.Unmarshal([]byte(tt.want), &wantJSON); err != nil { + t.Errorf("Error unmarshalling want JSON: %v", err) + return + } + if !reflect.DeepEqual(gotJSON, wantJSON) { + t.Errorf("normalizeABI() = %v, want %v", string(got), tt.want) + } + }) + } +} + +func TestCompareABIs(t *testing.T) { + tests := []struct { + name string + abi1 string + abi2 string + want bool + }{ + { + name: "Identical ABIs", + abi1: `[{"type":"function","name":"test","inputs":[],"outputs":[]}]`, + abi2: `[{"type":"function","name":"test","inputs":[],"outputs":[]}]`, + want: true, + }, + { + name: "Different ABIs", + abi1: `[{"type":"function","name":"test1","inputs":[],"outputs":[]}]`, + abi2: `[{"type":"function","name":"test2","inputs":[],"outputs":[]}]`, + want: false, + }, + { + name: "Different order, same content", + abi1: `[{"type":"function","name":"test1","inputs":[],"outputs":[]},{"type":"function","name":"test2","inputs":[],"outputs":[]}]`, + abi2: `[{"type":"function","name":"test2","inputs":[],"outputs":[]},{"type":"function","name":"test1","inputs":[],"outputs":[]}]`, + want: true, + }, + { + name: "Different input types", + abi1: `[{"type":"function","name":"test","inputs":[{"type":"uint256"}],"outputs":[]}]`, + abi2: `[{"type":"function","name":"test","inputs":[{"type":"uint128"}],"outputs":[]}]`, + want: false, + }, + { + name: "Different output types", + abi1: `[{"type":"function","name":"test","inputs":[],"outputs":[{"type":"uint256"}]}]`, + abi2: `[{"type":"function","name":"test","inputs":[],"outputs":[{"type":"uint128"}]}]`, + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := compareABIs(json.RawMessage(tt.abi1), json.RawMessage(tt.abi2)) + if err != nil { + t.Errorf("compareABIs() error = %v", err) + return + } + if got != tt.want { + t.Errorf("compareABIs() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestIsExcluded(t *testing.T) { + tests := []struct { + name string + contractName string + want bool + }{ + {"Excluded contract", "IERC20", true}, + {"Non-excluded contract", "IMyContract", false}, + {"Another excluded contract", "IEAS", true}, + {"Excluded contract (case-sensitive)", "ierc20", false}, + {"Excluded contract with prefix", "IERC20Extension", false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := isExcluded(tt.contractName); got != tt.want { + t.Errorf("isExcluded() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestNormalizeInternalType(t *testing.T) { + tests := []struct { + name string + internalType string + want string + }{ + {"Replace contract I", "contract ITest", "contract Test"}, + {"Replace enum I", "enum IMyEnum", "enum MyEnum"}, + {"Replace struct I", "struct IMyStruct", "struct MyStruct"}, + {"No replacement needed", "uint256", "uint256"}, + {"Don't replace non-prefix I", "contract TestI", "contract TestI"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := normalizeInternalType(tt.internalType); got != tt.want { + t.Errorf("normalizeInternalType() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestABIItemLess(t *testing.T) { + tests := []struct { + name string + a map[string]interface{} + b map[string]interface{} + want bool + }{ + { + name: "Different types", + a: map[string]interface{}{"type": "constructor"}, + b: map[string]interface{}{"type": "function"}, + want: true, + }, + { + name: "Same type, different names", + a: map[string]interface{}{"type": "function", "name": "a"}, + b: map[string]interface{}{"type": "function", "name": "b"}, + want: true, + }, + { + name: "Same type and name", + a: map[string]interface{}{"type": "function", "name": "test"}, + b: map[string]interface{}{"type": "function", "name": "test"}, + want: false, + }, + { + name: "Constructor vs function", + a: map[string]interface{}{"type": "constructor"}, + b: map[string]interface{}{"type": "function", "name": "test"}, + want: true, + }, + { + name: "Event vs function", + a: map[string]interface{}{"type": "event", "name": "TestEvent"}, + b: map[string]interface{}{"type": "function", "name": "test"}, + want: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := abiItemLess(tt.a, tt.b); got != tt.want { + t.Errorf("abiItemLess() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/packages/contracts-bedrock/scripts/checks/unused-imports/main.go b/packages/contracts-bedrock/scripts/checks/unused-imports/main.go new file mode 100644 index 000000000000..9fc901b4326e --- /dev/null +++ b/packages/contracts-bedrock/scripts/checks/unused-imports/main.go @@ -0,0 +1,149 @@ +package main + +import ( + "bufio" + "errors" + "fmt" + "os" + "path/filepath" + "regexp" + "runtime" + "strings" + "sync" + "sync/atomic" +) + +var importPattern = regexp.MustCompile(`import\s*{([^}]+)}`) +var asPattern = regexp.MustCompile(`(\S+)\s+as\s+(\S+)`) + +func main() { + if err := run(); err != nil { + writeStderr("an error occurred: %v", err) + os.Exit(1) + } +} + +func writeStderr(msg string, args ...any) { + _, _ = fmt.Fprintf(os.Stderr, msg+"\n", args...) +} + +func run() error { + cwd, err := os.Getwd() + if err != nil { + return fmt.Errorf("failed to get current working directory: %w", err) + } + + var hasErr int32 + var outMtx sync.Mutex + fail := func(msg string, args ...any) { + outMtx.Lock() + writeStderr("❌ "+msg, args...) + outMtx.Unlock() + atomic.StoreInt32(&hasErr, 1) + } + + dirs := []string{"src", "scripts", "test"} + sem := make(chan struct{}, runtime.NumCPU()) + + for _, dir := range dirs { + dirPath := filepath.Join(cwd, dir) + if _, err := os.Stat(dirPath); errors.Is(err, os.ErrNotExist) { + continue + } + + err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() && strings.HasSuffix(info.Name(), ".sol") { + sem <- struct{}{} + go func() { + defer func() { <-sem }() + processFile(path, fail) + }() + } + return nil + }) + + if err != nil { + return fmt.Errorf("failed to walk directory %s: %w", dir, err) + } + } + + for i := 0; i < cap(sem); i++ { + sem <- struct{}{} + } + + if atomic.LoadInt32(&hasErr) == 1 { + return errors.New("unused imports check failed, see logs above") + } + + return nil +} + +func processFile(filePath string, fail func(string, ...any)) { + content, err := os.ReadFile(filePath) + if err != nil { + fail("%s: failed to read file: %v", filePath, err) + return + } + + imports := findImports(string(content)) + unusedImports := checkUnusedImports(imports, string(content)) + + if len(unusedImports) > 0 { + fail("File: %s\nUnused imports:", filePath) + for _, unused := range unusedImports { + fail(" - %s", unused) + } + } +} + +func findImports(content string) []string { + var imports []string + matches := importPattern.FindAllStringSubmatch(content, -1) + for _, match := range matches { + if len(match) > 1 { + importList := strings.Split(match[1], ",") + for _, imp := range importList { + imports = append(imports, strings.TrimSpace(imp)) + } + } + } + return imports +} + +func checkUnusedImports(imports []string, content string) []string { + var unusedImports []string + for _, imp := range imports { + searchTerm := imp + displayName := imp + + if match := asPattern.FindStringSubmatch(imp); len(match) > 2 { + searchTerm = match[2] + displayName = fmt.Sprintf("%s as %s", match[1], match[2]) + } + + if !isImportUsed(searchTerm, content) { + unusedImports = append(unusedImports, displayName) + } + } + return unusedImports +} + +func isImportUsed(imp, content string) bool { + scanner := bufio.NewScanner(strings.NewReader(content)) + for scanner.Scan() { + line := scanner.Text() + if strings.HasPrefix(strings.TrimSpace(line), "//") { + continue + } + if strings.Contains(line, "import") { + continue + } + if strings.Contains(line, imp) { + return true + } + } + return false +} diff --git a/packages/contracts-bedrock/scripts/deploy/ChainAssertions.sol b/packages/contracts-bedrock/scripts/deploy/ChainAssertions.sol index d8cebf1fb22c..25d67be3828c 100644 --- a/packages/contracts-bedrock/scripts/deploy/ChainAssertions.sol +++ b/packages/contracts-bedrock/scripts/deploy/ChainAssertions.sol @@ -7,8 +7,6 @@ import { console2 as console } from "forge-std/console2.sol"; // Scripts import { DeployConfig } from "scripts/deploy/DeployConfig.s.sol"; -import { Deployer } from "scripts/deploy/Deployer.sol"; -import { ISystemConfigV0 } from "scripts/interfaces/ISystemConfigV0.sol"; import { ISystemConfigInterop } from "src/L1/interfaces/ISystemConfigInterop.sol"; // Libraries @@ -584,6 +582,9 @@ library ChainAssertions { function assertInitializedSlotIsSet(address _contractAddress, uint256 _slot, uint256 _offset) internal view { bytes32 slotVal = vm.load(_contractAddress, bytes32(_slot)); uint8 val = uint8((uint256(slotVal) >> (_offset * 8)) & 0xFF); - require(val == uint8(1) || val == uint8(0xff), "Storage value is not 1 or 0xff at the given slot and offset"); + require( + val == uint8(1) || val == uint8(0xff), + "ChainAssertions: storage value is not 1 or 0xff at the given slot and offset" + ); } } diff --git a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol index ea8efdda507f..3f70d78b2049 100644 --- a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.0; // Testing import { VmSafe } from "forge-std/Vm.sol"; -import { Script } from "forge-std/Script.sol"; import { console2 as console } from "forge-std/console2.sol"; import { stdJson } from "forge-std/StdJson.sol"; import { AlphabetVM } from "test/mocks/AlphabetVM.sol"; @@ -40,17 +39,15 @@ import { IProxy } from "src/universal/interfaces/IProxy.sol"; import { IProxyAdmin } from "src/universal/interfaces/IProxyAdmin.sol"; import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol"; import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol"; -import { IOptimismPortalInterop } from "src/L1/interfaces/IOptimismPortalInterop.sol"; import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; import { IL1CrossDomainMessenger } from "src/L1/interfaces/IL1CrossDomainMessenger.sol"; import { IL2OutputOracle } from "src/L1/interfaces/IL2OutputOracle.sol"; import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; -import { ISystemConfigInterop } from "src/L1/interfaces/ISystemConfigInterop.sol"; import { IDataAvailabilityChallenge } from "src/L1/interfaces/IDataAvailabilityChallenge.sol"; import { IL1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol"; import { IL1StandardBridge } from "src/L1/interfaces/IL1StandardBridge.sol"; -import { IProtocolVersions, ProtocolVersion } from "src/L1/interfaces/IProtocolVersions.sol"; +import { ProtocolVersion } from "src/L1/interfaces/IProtocolVersions.sol"; import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; @@ -236,8 +233,8 @@ contract Deploy is Deployer { ) public { - require(_superchainConfigProxy != address(0), "must specify address for superchain config proxy"); - require(_protocolVersionsProxy != address(0), "must specify address for protocol versions proxy"); + require(_superchainConfigProxy != address(0), "Deploy: must specify address for superchain config proxy"); + require(_protocolVersionsProxy != address(0), "Deploy: must specify address for protocol versions proxy"); vm.chainId(cfg.l1ChainID()); @@ -357,6 +354,7 @@ contract Deploy is Deployer { dii.set(dii.challengePeriodSeconds.selector, cfg.preimageOracleChallengePeriod()); dii.set(dii.proofMaturityDelaySeconds.selector, cfg.proofMaturityDelaySeconds()); dii.set(dii.disputeGameFinalityDelaySeconds.selector, cfg.disputeGameFinalityDelaySeconds()); + dii.set(dii.mipsVersion.selector, Config.useMultithreadedCannon() ? 2 : 1); string memory release = "dev"; dii.set(dii.release.selector, release); dii.set( @@ -1289,7 +1287,9 @@ contract Deploy is Deployer { commands[1] = "-c"; commands[2] = string.concat("[[ -f ", filePath, " ]] && echo \"present\""); if (Process.run(commands).length == 0) { - revert("Cannon prestate dump not found, generate it with `make cannon-prestate` in the monorepo root."); + revert( + "Deploy: cannon prestate dump not found, generate it with `make cannon-prestate` in the monorepo root" + ); } commands[2] = string.concat("cat ", filePath, " | jq -r .pre"); mipsAbsolutePrestate_ = Claim.wrap(abi.decode(Process.run(commands), (bytes32))); @@ -1310,7 +1310,7 @@ contract Deploy is Deployer { commands[2] = string.concat("[[ -f ", filePath, " ]] && echo \"present\""); if (Process.run(commands).length == 0) { revert( - "MT-Cannon prestate dump not found, generate it with `make cannon-prestate-mt` in the monorepo root." + "Deploy: MT-Cannon prestate dump not found, generate it with `make cannon-prestate-mt` in the monorepo root" ); } commands[2] = string.concat("cat ", filePath, " | jq -r .pre"); diff --git a/packages/contracts-bedrock/scripts/deploy/DeployConfig.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployConfig.s.sol index d9a8abcf8805..9288111b6e6b 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployConfig.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployConfig.s.sol @@ -6,7 +6,6 @@ import { console2 as console } from "forge-std/console2.sol"; import { stdJson } from "forge-std/StdJson.sol"; import { Executables } from "scripts/libraries/Executables.sol"; import { Process } from "scripts/libraries/Process.sol"; -import { Chains } from "scripts/libraries/Chains.sol"; import { Config, Fork, ForkUtils } from "scripts/libraries/Config.sol"; /// @title DeployConfig @@ -97,7 +96,7 @@ contract DeployConfig is Script { try vm.readFile(_path) returns (string memory data_) { _json = data_; } catch { - require(false, string.concat("Cannot find deploy config file at ", _path)); + require(false, string.concat("DeployConfig: cannot find deploy config file at ", _path)); } finalSystemOwner = stdJson.readAddress(_json, "$.finalSystemOwner"); @@ -202,7 +201,9 @@ contract DeployConfig is Script { } catch { } } } - revert("l1StartingBlockTag must be a bytes32, string or uint256 or cannot fetch l1StartingBlockTag"); + revert( + "DeployConfig: l1StartingBlockTag must be a bytes32, string or uint256 or cannot fetch l1StartingBlockTag" + ); } function l2OutputOracleStartingTimestamp() public returns (uint256) { diff --git a/packages/contracts-bedrock/scripts/deploy/DeployOwnership.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployOwnership.s.sol index dfc4811e3373..e126c39f18c9 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployOwnership.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployOwnership.s.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.0; import { console2 as console } from "forge-std/console2.sol"; -import { stdJson } from "forge-std/StdJson.sol"; import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol"; import { GnosisSafeProxyFactory as SafeProxyFactory } from "safe-contracts/proxies/GnosisSafeProxyFactory.sol"; @@ -374,7 +373,7 @@ contract DeployOwnership is Deploy { address[] memory owners = safe.getOwners(); require( safe.getThreshold() == LivenessModule(livenessModule).getRequiredThreshold(owners.length), - "Safe threshold must be equal to the LivenessModule's required threshold" + "DeployOwnership: safe threshold must be equal to the LivenessModule's required threshold" ); addr_ = address(safe); diff --git a/packages/contracts-bedrock/scripts/interfaces/IGnosisSafe.sol b/packages/contracts-bedrock/scripts/interfaces/IGnosisSafe.sol deleted file mode 100644 index 068f3815134a..000000000000 --- a/packages/contracts-bedrock/scripts/interfaces/IGnosisSafe.sol +++ /dev/null @@ -1,150 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.8.0; - -/// @title Enum - Collection of enums used in Safe contracts. -/// @author Richard Meissner - @rmeissner -abstract contract Enum { - enum Operation { - Call, - DelegateCall - } -} - -/// @title IGnosisSafe - Gnosis Safe Interface -interface IGnosisSafe { - event AddedOwner(address owner); - event ApproveHash(bytes32 indexed approvedHash, address indexed owner); - event ChangedFallbackHandler(address handler); - event ChangedGuard(address guard); - event ChangedThreshold(uint256 threshold); - event DisabledModule(address module); - event EnabledModule(address module); - event ExecutionFailure(bytes32 txHash, uint256 payment); - event ExecutionFromModuleFailure(address indexed module); - event ExecutionFromModuleSuccess(address indexed module); - event ExecutionSuccess(bytes32 txHash, uint256 payment); - event RemovedOwner(address owner); - event SafeReceived(address indexed sender, uint256 value); - event SafeSetup( - address indexed initiator, address[] owners, uint256 threshold, address initializer, address fallbackHandler - ); - event SignMsg(bytes32 indexed msgHash); - - function VERSION() external view returns (string memory); - function addOwnerWithThreshold(address owner, uint256 _threshold) external; - function approveHash(bytes32 hashToApprove) external; - function approvedHashes(address, bytes32) external view returns (uint256); - function changeThreshold(uint256 _threshold) external; - function checkNSignatures( - bytes32 dataHash, - bytes memory data, - bytes memory signatures, - uint256 requiredSignatures - ) - external - view; - function checkSignatures(bytes32 dataHash, bytes memory data, bytes memory signatures) external view; - function disableModule(address prevModule, address module) external; - function domainSeparator() external view returns (bytes32); - function enableModule(address module) external; - function encodeTransactionData( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation, - uint256 safeTxGas, - uint256 baseGas, - uint256 gasPrice, - address gasToken, - address refundReceiver, - uint256 _nonce - ) - external - view - returns (bytes memory); - function execTransaction( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation, - uint256 safeTxGas, - uint256 baseGas, - uint256 gasPrice, - address gasToken, - address refundReceiver, - bytes memory signatures - ) - external - payable - returns (bool success); - function execTransactionFromModule( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation - ) - external - returns (bool success); - function execTransactionFromModuleReturnData( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation - ) - external - returns (bool success, bytes memory returnData); - function getChainId() external view returns (uint256); - function getModulesPaginated( - address start, - uint256 pageSize - ) - external - view - returns (address[] memory array, address next); - function getOwners() external view returns (address[] memory); - function getStorageAt(uint256 offset, uint256 length) external view returns (bytes memory); - function getThreshold() external view returns (uint256); - function getTransactionHash( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation, - uint256 safeTxGas, - uint256 baseGas, - uint256 gasPrice, - address gasToken, - address refundReceiver, - uint256 _nonce - ) - external - view - returns (bytes32); - function isModuleEnabled(address module) external view returns (bool); - function isOwner(address owner) external view returns (bool); - function nonce() external view returns (uint256); - function removeOwner(address prevOwner, address owner, uint256 _threshold) external; - function requiredTxGas( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation - ) - external - returns (uint256); - function setFallbackHandler(address handler) external; - function setGuard(address guard) external; - function setup( - address[] memory _owners, - uint256 _threshold, - address to, - bytes memory data, - address fallbackHandler, - address paymentToken, - uint256 payment, - address paymentReceiver - ) - external; - function signedMessages(bytes32) external view returns (uint256); - function simulateAndRevert(address targetContract, bytes memory calldataPayload) external; - function swapOwner(address prevOwner, address oldOwner, address newOwner) external; -} diff --git a/packages/contracts-bedrock/scripts/interfaces/ISystemConfigV0.sol b/packages/contracts-bedrock/scripts/interfaces/ISystemConfigV0.sol deleted file mode 100644 index af1397d72645..000000000000 --- a/packages/contracts-bedrock/scripts/interfaces/ISystemConfigV0.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; - -/// @title ISystemConfigV0 -/// @notice Minimal interface of the Legacy SystemConfig containing only getters. -/// Based on -/// https://github.com/ethereum-optimism/optimism/blob/f54a2234f2f350795552011f35f704a3feb56a08/packages/contracts-bedrock/src/L1/SystemConfig.sol -interface ISystemConfigV0 { - function owner() external view returns (address); - function VERSION() external view returns (uint256); - function overhead() external view returns (uint256); - function scalar() external view returns (uint256); - function batcherHash() external view returns (bytes32); - function gasLimit() external view returns (uint64); - function resourceConfig() external view returns (IResourceMetering.ResourceConfig memory); - function unsafeBlockSigner() external view returns (address); -} diff --git a/packages/contracts-bedrock/scripts/libraries/DeployUtils.sol b/packages/contracts-bedrock/scripts/libraries/DeployUtils.sol index 3654424696b7..669ebd0f65c7 100644 --- a/packages/contracts-bedrock/scripts/libraries/DeployUtils.sol +++ b/packages/contracts-bedrock/scripts/libraries/DeployUtils.sol @@ -9,9 +9,13 @@ import { Artifacts } from "scripts/Artifacts.s.sol"; // Libraries import { LibString } from "@solady/utils/LibString.sol"; import { Bytes } from "src/libraries/Bytes.sol"; +import { Constants } from "src/libraries/Constants.sol"; // Interfaces import { IProxy } from "src/universal/interfaces/IProxy.sol"; +import { IAddressManager } from "src/legacy/interfaces/IAddressManager.sol"; +import { IL1ChugSplashProxy, IStaticL1ChugSplashProxy } from "src/legacy/interfaces/IL1ChugSplashProxy.sol"; +import { IResolvedDelegateProxy } from "src/legacy/interfaces/IResolvedDelegateProxy.sol"; library DeployUtils { Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); @@ -204,7 +208,7 @@ library DeployUtils { /// @param _data constructor arguments prefixed with a psuedo-constructor function signature /// @return encodedData_ constructor arguments without the psuedo-constructor function signature prefix function encodeConstructor(bytes memory _data) internal pure returns (bytes memory encodedData_) { - require(_data.length >= 4, "encodeConstructor takes in _data of length >= 4"); + require(_data.length >= 4, "DeployUtils: encodeConstructor takes in _data of length >= 4"); encodedData_ = Bytes.slice(_data, 4); } @@ -217,12 +221,99 @@ library DeployUtils { /// @notice Asserts that the given proxy has an implementation set. /// @param _proxy Proxy to check. - function assertImplementationSet(address _proxy) internal { + function assertERC1967ImplementationSet(address _proxy) internal returns (address implementation_) { // We prank as the zero address due to the Proxy's `proxyCallIfNotAdmin` modifier. // Pranking inside this function also means it can no longer be considered `view`. vm.prank(address(0)); - address implementation = IProxy(payable(_proxy)).implementation(); - assertValidContractAddress(implementation); + implementation_ = IProxy(payable(_proxy)).implementation(); + assertValidContractAddress(implementation_); + } + + /// @notice Asserts that the given L1ChugSplashProxy has an implementation set. + /// @param _proxy L1ChugSplashProxy to check. + function assertL1ChugSplashImplementationSet(address _proxy) internal returns (address implementation_) { + vm.prank(address(0)); + implementation_ = IStaticL1ChugSplashProxy(_proxy).getImplementation(); + assertValidContractAddress(implementation_); + } + + /// @notice Asserts that the given ResolvedDelegateProxy has an implementation set. + /// @param _implementationName Name of the implementation contract. + /// @param _addressManager AddressManager contract. + function assertResolvedDelegateProxyImplementationSet( + string memory _implementationName, + IAddressManager _addressManager + ) + internal + view + returns (address implementation_) + { + implementation_ = _addressManager.getAddress(_implementationName); + assertValidContractAddress(implementation_); + } + + /// @notice Builds an ERC1967 Proxy with a dummy implementation. + /// @param _proxyImplName Name of the implementation contract. + function buildERC1967ProxyWithImpl(string memory _proxyImplName) public returns (IProxy genericProxy_) { + genericProxy_ = IProxy( + create1({ + _name: "Proxy", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IProxy.__constructor__, (address(0)))) + }) + ); + address implementation = address(vm.addr(uint256(keccak256(abi.encodePacked(_proxyImplName))))); + vm.etch(address(implementation), hex"01"); + vm.prank(address(0)); + genericProxy_.upgradeTo(address(implementation)); + vm.etch(address(genericProxy_), address(genericProxy_).code); + } + + /// @notice Builds an L1ChugSplashProxy with a dummy implementation. + /// @param _proxyImplName Name of the implementation contract. + function buildL1ChugSplashProxyWithImpl(string memory _proxyImplName) public returns (IL1ChugSplashProxy proxy_) { + proxy_ = IL1ChugSplashProxy( + create1({ + _name: "L1ChugSplashProxy", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IL1ChugSplashProxy.__constructor__, (address(0)))) + }) + ); + address implementation = address(vm.addr(uint256(keccak256(abi.encodePacked(_proxyImplName))))); + vm.etch(address(implementation), hex"01"); + vm.prank(address(0)); + proxy_.setStorage(Constants.PROXY_IMPLEMENTATION_ADDRESS, bytes32(uint256(uint160(implementation)))); + } + + /// @notice Builds a ResolvedDelegateProxy with a dummy implementation. + /// @param _addressManager AddressManager contract. + /// @param _proxyImplName Name of the implementation contract. + function buildResolvedDelegateProxyWithImpl( + IAddressManager _addressManager, + string memory _proxyImplName + ) + public + returns (IResolvedDelegateProxy proxy_) + { + proxy_ = IResolvedDelegateProxy( + create1({ + _name: "ResolvedDelegateProxy", + _args: DeployUtils.encodeConstructor( + abi.encodeCall(IResolvedDelegateProxy.__constructor__, (_addressManager, _proxyImplName)) + ) + }) + ); + address implementation = address(vm.addr(uint256(keccak256(abi.encodePacked(_proxyImplName))))); + vm.etch(address(implementation), hex"01"); + _addressManager.setAddress(_proxyImplName, implementation); + } + + /// @notice Builds an AddressManager contract. + function buildAddressManager() public returns (IAddressManager addressManager_) { + addressManager_ = IAddressManager( + create1({ + _name: "AddressManager", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IAddressManager.__constructor__, ())) + }) + ); } /// @notice Asserts that the given addresses are valid contract addresses. @@ -238,9 +329,12 @@ library DeployUtils { // All addresses should be unique. for (uint256 i = 0; i < _addrs.length; i++) { for (uint256 j = i + 1; j < _addrs.length; j++) { - string memory err = - string.concat("check failed: duplicates at ", LibString.toString(i), ",", LibString.toString(j)); - require(_addrs[i] != _addrs[j], err); + require( + _addrs[i] != _addrs[j], + string.concat( + "DeployUtils: check failed, duplicates at ", LibString.toString(i), ",", LibString.toString(j) + ) + ); } } } @@ -253,7 +347,7 @@ library DeployUtils { uint8 value = uint8((uint256(slotVal) >> (_offset * 8)) & 0xFF); require( value == 1 || value == type(uint8).max, - "Value at the given slot and offset does not indicate initialization" + "DeployUtils: value at the given slot and offset does not indicate initialization" ); } } diff --git a/packages/contracts-bedrock/scripts/ops/FeeVaultWithdrawal.s.sol b/packages/contracts-bedrock/scripts/ops/FeeVaultWithdrawal.s.sol index 5a7b48847614..9e5bb96cfe31 100644 --- a/packages/contracts-bedrock/scripts/ops/FeeVaultWithdrawal.s.sol +++ b/packages/contracts-bedrock/scripts/ops/FeeVaultWithdrawal.s.sol @@ -5,7 +5,7 @@ import { console } from "forge-std/console.sol"; import { Script } from "forge-std/Script.sol"; import { IMulticall3 } from "forge-std/interfaces/IMulticall3.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { FeeVault } from "src/universal/FeeVault.sol"; +import { IFeeVault } from "src/L2/interfaces/IFeeVault.sol"; /// @title FeeVaultWithdrawal /// @notice A script to make it very simple to withdraw from the fee vaults. @@ -35,11 +35,11 @@ contract FeeVaultWithdrawal is Script { IMulticall3.Call3({ target: vault, allowFailure: false, - callData: abi.encodeWithSelector(FeeVault.withdraw.selector) + callData: abi.encodeWithSelector(IFeeVault.withdraw.selector) }) ); - address recipient = FeeVault(payable(vault)).RECIPIENT(); + address recipient = IFeeVault(payable(vault)).RECIPIENT(); uint256 balance = vault.balance; log(balance, recipient, vault); } else { @@ -59,7 +59,7 @@ contract FeeVaultWithdrawal is Script { /// @notice Checks whether or not a FeeVault can be withdrawn. The balance of the account must /// be larger than the `MIN_WITHDRAWAL_AMOUNT`. function canWithdrawal(address _vault) internal view returns (bool) { - uint256 minWithdrawalAmount = FeeVault(payable(_vault)).MIN_WITHDRAWAL_AMOUNT(); + uint256 minWithdrawalAmount = IFeeVault(payable(_vault)).MIN_WITHDRAWAL_AMOUNT(); uint256 balance = _vault.balance; return balance >= minWithdrawalAmount; } diff --git a/packages/contracts-bedrock/scripts/periphery/deploy/DeployPeriphery.s.sol b/packages/contracts-bedrock/scripts/periphery/deploy/DeployPeriphery.s.sol index ea7cf2f4f5c3..95a6c4622e3e 100644 --- a/packages/contracts-bedrock/scripts/periphery/deploy/DeployPeriphery.s.sol +++ b/packages/contracts-bedrock/scripts/periphery/deploy/DeployPeriphery.s.sol @@ -277,7 +277,7 @@ contract DeployPeriphery is Script, Artifacts { assembly { addr_ := create2(0, add(initCode, 0x20), mload(initCode), salt) } - require(addr_ != address(0), "deployment failed"); + require(addr_ != address(0), "DeployPeriphery: deployment failed"); save(_name, addr_); console.log("%s deployed at %s", _name, addr_); } diff --git a/packages/contracts-bedrock/scripts/utils/restructure_tests.py b/packages/contracts-bedrock/scripts/utils/restructure_tests.py deleted file mode 100644 index 711753f3a3d1..000000000000 --- a/packages/contracts-bedrock/scripts/utils/restructure_tests.py +++ /dev/null @@ -1,57 +0,0 @@ -import os -import shutil - - -def mimic_directory_structure(src_folder: str, test_folder: str) -> None: - """ - This function takes a source folder and a test folder as input, and restructures - the test folder to match the directory structure of the source folder. - - Only moves test files (".t.sol") at the root level of the `test` folder. - """ - - # Walk through the src folder and collect a list of all .sol files - sol_files = [] - for root, _, files in os.walk(src_folder): - for file in files: - if file.endswith(".sol"): - sol_files.append(os.path.join(root, file)) - - # Iterate through each .t.sol file in the test folder - for test_file in os.listdir(test_folder): - if test_file.endswith(".t.sol"): - # Construct the corresponding .sol file name - sol_file = test_file.replace(".t.sol", ".sol") - - # Find the full path of the corresponding .sol file in the src folder - src_path = None - for sol_path in sol_files: - if sol_path.endswith(os.path.sep + sol_file): - src_path = sol_path - break - - if src_path: - # Calculate the relative path from the src folder to the .sol file - rel_path = os.path.relpath(src_path, src_folder) - - # Construct the destination path within the test folder - dest_path = os.path.join( - test_folder, rel_path).replace(".sol", ".t.sol") - - # Create the directory structure if it doesn't exist - dest_dir = os.path.dirname(dest_path) - os.makedirs(dest_dir, exist_ok=True) - - # Copy the .t.sol file to the destination folder - shutil.move(os.path.join(test_folder, test_file), dest_path) - print(f"Moved {test_file} to {dest_path}") - else: - print(f"No corresponding .sol file found for {test_file}") - - -# Specify the source and test folder paths -src_folder = "src" -test_folder = "test" - -# Call the mimic_directory_structure function -mimic_directory_structure(src_folder, test_folder) diff --git a/packages/contracts-bedrock/scripts/utils/statediff.sh b/packages/contracts-bedrock/scripts/utils/statediff.sh deleted file mode 100755 index cce1138c962b..000000000000 --- a/packages/contracts-bedrock/scripts/utils/statediff.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -echo "> Deploying contracts to generate state diff (non-broadcast)" -forge script -vvv scripts/deploy/Deploy.s.sol:Deploy --sig 'runWithStateDiff()' diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index ca879f5b2bde..8c3cf97d0087 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -12,16 +12,16 @@ "sourceCodeHash": "0x848ec3774be17bcc8ba65a23d08e35e979b3f39f9d2ac8a810188f945c69c9ea" }, "src/L1/L1ERC721Bridge.sol": { - "initCodeHash": "0xfb8b3c51e1790a0b951eaba05ed7368309fbfc7ddc558b4ce1de29da087fb4bd", - "sourceCodeHash": "0xcb125e7f640cf5f372c7bf4f8e36150328914ceef99b6fd5d65ae12b6db430b5" + "initCodeHash": "0x63dc4da75200f4b968f57e27e81834e6eb3f6625826410882526ab1eec7847ff", + "sourceCodeHash": "0xfec29cfbb7aa05473e32a6c2484deebfc1ff50c0e08c42e8ee70696ad701ceaa" }, "src/L1/L1StandardBridge.sol": { "initCodeHash": "0x2868b09ecbe9f2bbc885605c2886b4c79f1c8e4171626c63776603b1b84698a8", "sourceCodeHash": "0xc03da137b3ea72e0109fb284229283b21a0303104afbe37d2fe86ad806392a7f" }, "src/L1/L2OutputOracle.sol": { - "initCodeHash": "0x433fac9de52d8ce8fc3471b78ef6cc9cff1019f480c9ad91b6e09ab8738a8edb", - "sourceCodeHash": "0xde4df0f9633dc0cdb1c9f634003ea5b0f7c5c1aebc407bc1b2f44c0ecf938649" + "initCodeHash": "0x1182bfb87c4ab399b912ca7fe18cdbf4b24c414e078fb0a55bd3c44d442d3ed1", + "sourceCodeHash": "0x4132ff37d267cb12224b75ea806c0aa7d25407b0d66ce526d7fcda8f7d223882" }, "src/L1/OPContractsManager.sol": { "initCodeHash": "0xd58cb3978affc5c1457cdd498ff8420c90aef804d4c3b62cf42ab2691986d6d2", @@ -40,8 +40,8 @@ "sourceCodeHash": "0x6401b81f04093863557ef46192f56793daa0d412618065383ab353b2ed2929d8" }, "src/L1/ProtocolVersions.sol": { - "initCodeHash": "0xf7a9ed8c772cfb1234988fd6fd195dc21615b216bb39e728e7699b875040d902", - "sourceCodeHash": "0x92f15d62361bffc305f0db48a5676329f8e5ed2e454f8c8ff83ef7d3667d7f01" + "initCodeHash": "0xefd4806e8737716d5d2022ca2e9e9fba0a0cb5714b026166b58e472222c7d15f", + "sourceCodeHash": "0x15205131bf420aa6d03c558bb75dd49cd7439caed7ccdcbfd89c4170a48c94f5" }, "src/L1/SuperchainConfig.sol": { "initCodeHash": "0xfca12d9016c746e5c275b186e0ca40cfd65cf45a5665aab7589a669fea3abb47", @@ -56,8 +56,8 @@ "sourceCodeHash": "0x441d1e3e8e987f829f55996b5b6c850da8c59ad48f09cf7e0a69a1fa559d42a2" }, "src/L2/BaseFeeVault.sol": { - "initCodeHash": "0x3bfcd57e25ad54b66c374f63e24e33a6cf107044aa8f5f69ef21202c380b5c5b", - "sourceCodeHash": "0x2dc2284cf7c68e743da50e4113e96ffeab435de2390aeba2eab2f1e8ca411ce9" + "initCodeHash": "0xbf49824cf37e201181484a8a423fcad8f504dc925921a2b28e83398197858dec", + "sourceCodeHash": "0x983e8e248c61e362ba6a01dd2e217a535c9bb828dc0b4421f5f27e0577f2e14c" }, "src/L2/CrossL2Inbox.sol": { "initCodeHash": "0x66b052adce7e9194d054952d67d08b53964120067600358243ec86c85b90877b", @@ -80,16 +80,16 @@ "sourceCodeHash": "0x7417677643e1df1ae1782513b94c7821097b9529d3f8626c3bcb8b3a9ae0d180" }, "src/L2/L1FeeVault.sol": { - "initCodeHash": "0x3bfcd57e25ad54b66c374f63e24e33a6cf107044aa8f5f69ef21202c380b5c5b", - "sourceCodeHash": "0x927cc729bf5c9f209112df597f649493f276c4c50e17a57f7da02c2be266b192" + "initCodeHash": "0xbf49824cf37e201181484a8a423fcad8f504dc925921a2b28e83398197858dec", + "sourceCodeHash": "0xc7cda130f2bb3648e04d5a480082aa1789e16456c1280954d822b05d30100b2d" }, "src/L2/L2CrossDomainMessenger.sol": { - "initCodeHash": "0xcc4527d21cceeedbb3cbf8e7028e22fe12bc1ab30365dbebd0713499451b959d", - "sourceCodeHash": "0x66e4ae82b58693cb394d70159308d50270ccdd56c495c5e2aaf55de1fdc78695" + "initCodeHash": "0xc496495496b96ea0eaf417c5e56b295836c12db3e6aafe2e607563e7a50b5b65", + "sourceCodeHash": "0x56edf0f36366326a92722ae3c7502bce3d80b2ee5e354181dc09ba801437a488" }, "src/L2/L2ERC721Bridge.sol": { - "initCodeHash": "0x827077e1a0ce6c8f9ee1196c409ea77d831efd440992b3969b05259083cdf0bd", - "sourceCodeHash": "0x51a44e1fcef9483cc58ba0c9895cb3eec675785145428ece9aa7acd1a1a5b57c" + "initCodeHash": "0x558fff5939a26b9d5d86e6b907d9dd9c7c917eaef7657a8b5acfeb58de1442f0", + "sourceCodeHash": "0xca9acd19fd5f42e6a7a5b1de6359f2d841814fb54d377664c2fe9c3f9c6be34a" }, "src/L2/L2StandardBridge.sol": { "initCodeHash": "0x651eed10044d0b19b7e4eba864345df15e252be1401f39a552ec0d2f9c4df064", @@ -108,8 +108,8 @@ "sourceCodeHash": "0xfea53344596d735eff3be945ed1300dc75a6f8b7b2c02c0043af5b0036f5f239" }, "src/L2/OptimismSuperchainERC20.sol": { - "initCodeHash": "0xe3dbb0851669708901a4c6bb7ad7d55f9896deeec02cbe53ac58d689ff95b88b", - "sourceCodeHash": "0xe853817da47d32b4ec5bb5392405278c82a1e9620aef377491dcb371fbbe682f" + "initCodeHash": "0x965af580568bad2b47d04c6ea536490aa263e9fcb5fb43e6c8bc00929fda3df5", + "sourceCodeHash": "0x9de349519900b1051f45d507b2fac1cf3f3ae8e2cfb1ceb56875a7ace1cb6ab8" }, "src/L2/OptimismSuperchainERC20Beacon.sol": { "initCodeHash": "0x99ce8095b23c124850d866cbc144fee6cee05dbc6bb5d83acadfe00b90cf42c7", @@ -120,8 +120,8 @@ "sourceCodeHash": "0x155a4b22ff8e266560d1fae72e1db7fc164afd84b8a81afb74c69414e0d5438e" }, "src/L2/SequencerFeeVault.sol": { - "initCodeHash": "0x2e6551705e493bacba8cffe22e564d5c401ae5bb02577a5424e0d32784e13e74", - "sourceCodeHash": "0xd56922cb04597dea469c65e5a49d4b3c50c171e603601e6f41da9517cae0b11a" + "initCodeHash": "0xcaadbf08057b5d47f7704257e9385a29e42a7a08c818646d109c5952d3d35218", + "sourceCodeHash": "0x05bbc6039e5a9ff38987e7b9b89c69e2ee8aa4b7ca20dd002ea1bbd3d70f27f3" }, "src/L2/SuperchainWETH.sol": { "initCodeHash": "0x4ccd25f37a816205bc26f8532afa66e02f2b36ca7b7404d0fa48a4313ed16f0c", @@ -132,16 +132,16 @@ "sourceCodeHash": "0x2ab6be69795109a1ee04c5693a34d6ce0ff90b62e404cdeb18178bab18d06784" }, "src/cannon/MIPS.sol": { - "initCodeHash": "0xa9a9db7bedf25800f20c947df10310c64beb2ead8eb6be991c83189e975df0fe", - "sourceCodeHash": "0x83aabf115ac0ad407868e633a521602c41d86864d82198e6abbf69d33daaea65" + "initCodeHash": "0x3e426acc53ebd6ad01037ea321410fab2df08e1d1183195c15be9ff48fef4d44", + "sourceCodeHash": "0xaf7416f27db1b393092f51d290a29293184105bc5f0d89cd6048f687cebc7d69" }, "src/cannon/MIPS2.sol": { "initCodeHash": "0xbb203b0d83efddfa0f664dbc63ec55844318b48fe8133758307f64e87c892a47", "sourceCodeHash": "0x16614cc0e6abf7e81e1e5dc2c0773ee7101cb38af40e0907a8800ca7eddd3b5a" }, "src/cannon/PreimageOracle.sol": { - "initCodeHash": "0xa0b19e18561da9990c95ebea9750dd901f73147b32b8b234eca0f35073c5a970", - "sourceCodeHash": "0x6235d602f84c4173e7a58666791e3db4c9e9651eaccb20db5aed2f898b76e896" + "initCodeHash": "0x64ea814bf9769257c91da57928675d3f8462374b0c23bdf860ccfc79f41f7801", + "sourceCodeHash": "0xac290a77986d54efe404c73ee58d11429e1b1fb47e4d06d4c38b6ecc20751d78" }, "src/dispute/AnchorStateRegistry.sol": { "initCodeHash": "0x13d00eef8c3f769863fc766180acc8586f5da309ca0a098e67d4d90bd3243341", @@ -156,8 +156,8 @@ "sourceCodeHash": "0xc8f21c777b2c5a37c2d2f92e8eeceba3b231b500a7d9cb0b607b774478f8be6b" }, "src/dispute/FaultDisputeGame.sol": { - "initCodeHash": "0xdb724dfd12dcea804d1adbc5a7e919625615c62b940035cf4b9115ea3a63e0ae", - "sourceCodeHash": "0x223428ee91532af397cef72356430ff59221e0ac0cbf697a881d36bb1d672392" + "initCodeHash": "0x04e6c36ee49f7744e5277c1d83ba78616ef3e3cef62406d32e2d9c72bca2010a", + "sourceCodeHash": "0x9b9e971748d253790b3ce9da0b1cbbcb6df77bb252ee2d1c5088bb6bae6491aa" }, "src/legacy/DeployerWhitelist.sol": { "initCodeHash": "0x0b8177ed75b69eddbb9ce6537683f69a9935efed86a1d6faa8feaafbd151c1bd", @@ -212,8 +212,8 @@ "sourceCodeHash": "0x5ea7c1b0cef5609f25c4193f5795fc9ce8f3ae08dbbf2945afe38e5af58f32c3" }, "src/universal/OptimismMintableERC721Factory.sol": { - "initCodeHash": "0x1e247d46b5ac3cc8ac6b51193917cd5b88ff00fbea7bf768c65fa35a115f8607", - "sourceCodeHash": "0x1c4bc4727f08d80e8364561b49397ee57bb485072cb004b7a430559cbfa019a6" + "initCodeHash": "0x63d2ceafd3f3b3b54e31749574563e8022fef9c6da7bb8c7a113b3dbf571cfa2", + "sourceCodeHash": "0x705e270925fcad14e805b5ec1bbbb9e78b5b44e3b128f284b0113a4d68c82ef6" }, "src/universal/StorageSetter.sol": { "initCodeHash": "0x21b3059e9b13b330f76d02b61f61dcfa3abf3517a0b56afa0895c4b8291740bf", diff --git a/packages/contracts-bedrock/snapshots/abi/BaseFeeVault.json b/packages/contracts-bedrock/snapshots/abi/BaseFeeVault.json index 9b98c78abed2..b745bcb8184c 100644 --- a/packages/contracts-bedrock/snapshots/abi/BaseFeeVault.json +++ b/packages/contracts-bedrock/snapshots/abi/BaseFeeVault.json @@ -12,7 +12,7 @@ "type": "uint256" }, { - "internalType": "enum FeeVault.WithdrawalNetwork", + "internalType": "enum Types.WithdrawalNetwork", "name": "_withdrawalNetwork", "type": "uint8" } @@ -55,7 +55,7 @@ "name": "WITHDRAWAL_NETWORK", "outputs": [ { - "internalType": "enum FeeVault.WithdrawalNetwork", + "internalType": "enum Types.WithdrawalNetwork", "name": "", "type": "uint8" } @@ -127,7 +127,7 @@ "name": "withdrawalNetwork", "outputs": [ { - "internalType": "enum FeeVault.WithdrawalNetwork", + "internalType": "enum Types.WithdrawalNetwork", "name": "network_", "type": "uint8" } @@ -183,7 +183,7 @@ }, { "indexed": false, - "internalType": "enum FeeVault.WithdrawalNetwork", + "internalType": "enum Types.WithdrawalNetwork", "name": "withdrawalNetwork", "type": "uint8" } diff --git a/packages/contracts-bedrock/snapshots/abi/L1FeeVault.json b/packages/contracts-bedrock/snapshots/abi/L1FeeVault.json index 9b98c78abed2..b745bcb8184c 100644 --- a/packages/contracts-bedrock/snapshots/abi/L1FeeVault.json +++ b/packages/contracts-bedrock/snapshots/abi/L1FeeVault.json @@ -12,7 +12,7 @@ "type": "uint256" }, { - "internalType": "enum FeeVault.WithdrawalNetwork", + "internalType": "enum Types.WithdrawalNetwork", "name": "_withdrawalNetwork", "type": "uint8" } @@ -55,7 +55,7 @@ "name": "WITHDRAWAL_NETWORK", "outputs": [ { - "internalType": "enum FeeVault.WithdrawalNetwork", + "internalType": "enum Types.WithdrawalNetwork", "name": "", "type": "uint8" } @@ -127,7 +127,7 @@ "name": "withdrawalNetwork", "outputs": [ { - "internalType": "enum FeeVault.WithdrawalNetwork", + "internalType": "enum Types.WithdrawalNetwork", "name": "network_", "type": "uint8" } @@ -183,7 +183,7 @@ }, { "indexed": false, - "internalType": "enum FeeVault.WithdrawalNetwork", + "internalType": "enum Types.WithdrawalNetwork", "name": "withdrawalNetwork", "type": "uint8" } diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismMintableERC721Factory.json b/packages/contracts-bedrock/snapshots/abi/OptimismMintableERC721Factory.json index 14a23db1be69..e6ecac1d9381 100644 --- a/packages/contracts-bedrock/snapshots/abi/OptimismMintableERC721Factory.json +++ b/packages/contracts-bedrock/snapshots/abi/OptimismMintableERC721Factory.json @@ -41,6 +41,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "bridge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -89,6 +102,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "remoteChainID", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "version", diff --git a/packages/contracts-bedrock/snapshots/abi/SequencerFeeVault.json b/packages/contracts-bedrock/snapshots/abi/SequencerFeeVault.json index 98c97149b215..700e7d7b9810 100644 --- a/packages/contracts-bedrock/snapshots/abi/SequencerFeeVault.json +++ b/packages/contracts-bedrock/snapshots/abi/SequencerFeeVault.json @@ -12,7 +12,7 @@ "type": "uint256" }, { - "internalType": "enum FeeVault.WithdrawalNetwork", + "internalType": "enum Types.WithdrawalNetwork", "name": "_withdrawalNetwork", "type": "uint8" } @@ -55,7 +55,7 @@ "name": "WITHDRAWAL_NETWORK", "outputs": [ { - "internalType": "enum FeeVault.WithdrawalNetwork", + "internalType": "enum Types.WithdrawalNetwork", "name": "", "type": "uint8" } @@ -140,7 +140,7 @@ "name": "withdrawalNetwork", "outputs": [ { - "internalType": "enum FeeVault.WithdrawalNetwork", + "internalType": "enum Types.WithdrawalNetwork", "name": "network_", "type": "uint8" } @@ -196,7 +196,7 @@ }, { "indexed": false, - "internalType": "enum FeeVault.WithdrawalNetwork", + "internalType": "enum Types.WithdrawalNetwork", "name": "withdrawalNetwork", "type": "uint8" } diff --git a/packages/contracts-bedrock/src/L1/L1ERC721Bridge.sol b/packages/contracts-bedrock/src/L1/L1ERC721Bridge.sol index 46e7e9f71b4c..dd01ff5cd2d3 100644 --- a/packages/contracts-bedrock/src/L1/L1ERC721Bridge.sol +++ b/packages/contracts-bedrock/src/L1/L1ERC721Bridge.sol @@ -6,7 +6,6 @@ import { ERC721Bridge } from "src/universal/ERC721Bridge.sol"; // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; -import { Constants } from "src/libraries/Constants.sol"; // Interfaces import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; @@ -29,8 +28,8 @@ contract L1ERC721Bridge is ERC721Bridge, ISemver { ISuperchainConfig public superchainConfig; /// @notice Semantic version. - /// @custom:semver 2.1.1-beta.3 - string public constant version = "2.1.1-beta.3"; + /// @custom:semver 2.1.1-beta.4 + string public constant version = "2.1.1-beta.4"; /// @notice Constructs the L1ERC721Bridge contract. constructor() ERC721Bridge() { diff --git a/packages/contracts-bedrock/src/L1/L2OutputOracle.sol b/packages/contracts-bedrock/src/L1/L2OutputOracle.sol index fb8d681227bf..99d5645dceca 100644 --- a/packages/contracts-bedrock/src/L1/L2OutputOracle.sol +++ b/packages/contracts-bedrock/src/L1/L2OutputOracle.sol @@ -6,7 +6,6 @@ import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable // Libraries import { Types } from "src/libraries/Types.sol"; -import { Constants } from "src/libraries/Constants.sol"; // Interfaces import { ISemver } from "src/universal/interfaces/ISemver.sol"; @@ -61,8 +60,8 @@ contract L2OutputOracle is Initializable, ISemver { event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex); /// @notice Semantic version. - /// @custom:semver 1.8.1-beta.1 - string public constant version = "1.8.1-beta.1"; + /// @custom:semver 1.8.1-beta.2 + string public constant version = "1.8.1-beta.2"; /// @notice Constructs the L2OutputOracle contract. Initializes variables to the same values as /// in the getting-started config. diff --git a/packages/contracts-bedrock/src/L1/ProtocolVersions.sol b/packages/contracts-bedrock/src/L1/ProtocolVersions.sol index 2be060604c86..8d4982ecea0c 100644 --- a/packages/contracts-bedrock/src/L1/ProtocolVersions.sol +++ b/packages/contracts-bedrock/src/L1/ProtocolVersions.sol @@ -4,7 +4,6 @@ pragma solidity 0.8.15; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { Storage } from "src/libraries/Storage.sol"; -import { Constants } from "src/libraries/Constants.sol"; /// @notice ProtocolVersion is a numeric identifier of the protocol version. type ProtocolVersion is uint256; @@ -37,8 +36,8 @@ contract ProtocolVersions is OwnableUpgradeable, ISemver { event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); /// @notice Semantic version. - /// @custom:semver 1.0.1-beta.2 - string public constant version = "1.0.1-beta.2"; + /// @custom:semver 1.0.1-beta.3 + string public constant version = "1.0.1-beta.3"; /// @notice Constructs the ProtocolVersion contract. Cannot set /// the owner to `address(0)` due to the Ownable contract's diff --git a/packages/contracts-bedrock/src/L1/interfaces/IL1CrossDomainMessengerV160.sol b/packages/contracts-bedrock/src/L1/interfaces/IL1CrossDomainMessengerV160.sol index a1023100d92d..d81bb5d25565 100644 --- a/packages/contracts-bedrock/src/L1/interfaces/IL1CrossDomainMessengerV160.sol +++ b/packages/contracts-bedrock/src/L1/interfaces/IL1CrossDomainMessengerV160.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.0; import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol"; -import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; /// @notice This interface corresponds to the op-contracts/v1.6.0 release of the L1CrossDomainMessenger /// contract, which has a semver of 2.3.0 as specified in diff --git a/packages/contracts-bedrock/src/L2/BaseFeeVault.sol b/packages/contracts-bedrock/src/L2/BaseFeeVault.sol index 2ae63efd599b..2fd33b9290bf 100644 --- a/packages/contracts-bedrock/src/L2/BaseFeeVault.sol +++ b/packages/contracts-bedrock/src/L2/BaseFeeVault.sol @@ -2,7 +2,9 @@ pragma solidity 0.8.15; import { ISemver } from "src/universal/interfaces/ISemver.sol"; -import { FeeVault } from "src/universal/FeeVault.sol"; +import { FeeVault } from "src/L2/FeeVault.sol"; + +import { Types } from "src/libraries/Types.sol"; /// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000019 @@ -10,8 +12,8 @@ import { FeeVault } from "src/universal/FeeVault.sol"; /// @notice The BaseFeeVault accumulates the base fee that is paid by transactions. contract BaseFeeVault is FeeVault, ISemver { /// @notice Semantic version. - /// @custom:semver 1.5.0-beta.2 - string public constant version = "1.5.0-beta.2"; + /// @custom:semver 1.5.0-beta.3 + string public constant version = "1.5.0-beta.3"; /// @notice Constructs the BaseFeeVault contract. /// @param _recipient Wallet that will receive the fees. @@ -20,7 +22,7 @@ contract BaseFeeVault is FeeVault, ISemver { constructor( address _recipient, uint256 _minWithdrawalAmount, - WithdrawalNetwork _withdrawalNetwork + Types.WithdrawalNetwork _withdrawalNetwork ) FeeVault(_recipient, _minWithdrawalAmount, _withdrawalNetwork) { } diff --git a/packages/contracts-bedrock/src/universal/FeeVault.sol b/packages/contracts-bedrock/src/L2/FeeVault.sol similarity index 88% rename from packages/contracts-bedrock/src/universal/FeeVault.sol rename to packages/contracts-bedrock/src/L2/FeeVault.sol index 542cd88447a4..856985d7827b 100644 --- a/packages/contracts-bedrock/src/universal/FeeVault.sol +++ b/packages/contracts-bedrock/src/L2/FeeVault.sol @@ -8,18 +8,13 @@ import { Predeploys } from "src/libraries/Predeploys.sol"; // Interfaces import { IL2ToL1MessagePasser } from "src/L2/interfaces/IL2ToL1MessagePasser.sol"; +// Libraries +import { Types } from "src/libraries/Types.sol"; + /// @title FeeVault /// @notice The FeeVault contract contains the basic logic for the various different vault contracts /// used to hold fee revenue generated by the L2 system. abstract contract FeeVault { - /// @notice Enum representing where the FeeVault withdraws funds to. - /// @custom:value L1 FeeVault withdraws funds to L1. - /// @custom:value L2 FeeVault withdraws funds to L2. - enum WithdrawalNetwork { - L1, - L2 - } - /// @notice Minimum balance before a withdrawal can be triggered. /// Use the `minWithdrawalAmount()` getter as this is deprecated /// and is subject to be removed in the future. @@ -36,7 +31,7 @@ abstract contract FeeVault { /// Use the `withdrawalNetwork()` getter as this is deprecated /// and is subject to be removed in the future. /// @custom:legacy - WithdrawalNetwork public immutable WITHDRAWAL_NETWORK; + Types.WithdrawalNetwork public immutable WITHDRAWAL_NETWORK; /// @notice The minimum gas limit for the FeeVault withdrawal transaction. uint32 internal constant WITHDRAWAL_MIN_GAS = 400_000; @@ -59,12 +54,12 @@ abstract contract FeeVault { /// @param to Address that the funds were sent to. /// @param from Address that triggered the withdrawal. /// @param withdrawalNetwork Network which the to address will receive funds on. - event Withdrawal(uint256 value, address to, address from, WithdrawalNetwork withdrawalNetwork); + event Withdrawal(uint256 value, address to, address from, Types.WithdrawalNetwork withdrawalNetwork); /// @param _recipient Wallet that will receive the fees. /// @param _minWithdrawalAmount Minimum balance for withdrawals. /// @param _withdrawalNetwork Network which the recipient will receive fees on. - constructor(address _recipient, uint256 _minWithdrawalAmount, WithdrawalNetwork _withdrawalNetwork) { + constructor(address _recipient, uint256 _minWithdrawalAmount, Types.WithdrawalNetwork _withdrawalNetwork) { RECIPIENT = _recipient; MIN_WITHDRAWAL_AMOUNT = _minWithdrawalAmount; WITHDRAWAL_NETWORK = _withdrawalNetwork; @@ -84,7 +79,7 @@ abstract contract FeeVault { } /// @notice Network which the recipient will receive fees on. - function withdrawalNetwork() public view returns (WithdrawalNetwork network_) { + function withdrawalNetwork() public view returns (Types.WithdrawalNetwork network_) { network_ = WITHDRAWAL_NETWORK; } @@ -101,7 +96,7 @@ abstract contract FeeVault { emit Withdrawal(value, RECIPIENT, msg.sender); emit Withdrawal(value, RECIPIENT, msg.sender, WITHDRAWAL_NETWORK); - if (WITHDRAWAL_NETWORK == WithdrawalNetwork.L2) { + if (WITHDRAWAL_NETWORK == Types.WithdrawalNetwork.L2) { bool success = SafeCall.send(RECIPIENT, value); require(success, "FeeVault: failed to send ETH to L2 fee recipient"); } else { diff --git a/packages/contracts-bedrock/src/L2/L1FeeVault.sol b/packages/contracts-bedrock/src/L2/L1FeeVault.sol index d62db2a25c3b..c80c40b98493 100644 --- a/packages/contracts-bedrock/src/L2/L1FeeVault.sol +++ b/packages/contracts-bedrock/src/L2/L1FeeVault.sol @@ -2,7 +2,9 @@ pragma solidity 0.8.15; import { ISemver } from "src/universal/interfaces/ISemver.sol"; -import { FeeVault } from "src/universal/FeeVault.sol"; +import { FeeVault } from "src/L2/FeeVault.sol"; + +import { Types } from "src/libraries/Types.sol"; /// @custom:proxied true /// @custom:predeploy 0x420000000000000000000000000000000000001A @@ -10,8 +12,8 @@ import { FeeVault } from "src/universal/FeeVault.sol"; /// @notice The L1FeeVault accumulates the L1 portion of the transaction fees. contract L1FeeVault is FeeVault, ISemver { /// @notice Semantic version. - /// @custom:semver 1.5.0-beta.2 - string public constant version = "1.5.0-beta.2"; + /// @custom:semver 1.5.0-beta.3 + string public constant version = "1.5.0-beta.3"; /// @notice Constructs the L1FeeVault contract. /// @param _recipient Wallet that will receive the fees. @@ -20,7 +22,7 @@ contract L1FeeVault is FeeVault, ISemver { constructor( address _recipient, uint256 _minWithdrawalAmount, - WithdrawalNetwork _withdrawalNetwork + Types.WithdrawalNetwork _withdrawalNetwork ) FeeVault(_recipient, _minWithdrawalAmount, _withdrawalNetwork) { } diff --git a/packages/contracts-bedrock/src/L2/L2CrossDomainMessenger.sol b/packages/contracts-bedrock/src/L2/L2CrossDomainMessenger.sol index bbfc82578ab6..2461e46d2cf5 100644 --- a/packages/contracts-bedrock/src/L2/L2CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/src/L2/L2CrossDomainMessenger.sol @@ -7,8 +7,6 @@ import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; // Libraries import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { Constants } from "src/libraries/Constants.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; // Interfaces import { ISemver } from "src/universal/interfaces/ISemver.sol"; @@ -22,8 +20,8 @@ import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; /// L2 on the L2 side. Users are generally encouraged to use this contract instead of lower /// level message passing contracts. contract L2CrossDomainMessenger is CrossDomainMessenger, ISemver { - /// @custom:semver 2.1.1-beta.3 - string public constant version = "2.1.1-beta.3"; + /// @custom:semver 2.1.1-beta.4 + string public constant version = "2.1.1-beta.4"; /// @notice Constructs the L2CrossDomainMessenger contract. constructor() CrossDomainMessenger() { diff --git a/packages/contracts-bedrock/src/L2/L2ERC721Bridge.sol b/packages/contracts-bedrock/src/L2/L2ERC721Bridge.sol index 4f3231c677f0..950f25203981 100644 --- a/packages/contracts-bedrock/src/L2/L2ERC721Bridge.sol +++ b/packages/contracts-bedrock/src/L2/L2ERC721Bridge.sol @@ -6,7 +6,6 @@ import { ERC721Bridge } from "src/universal/ERC721Bridge.sol"; // Libraries import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; -import { Constants } from "src/libraries/Constants.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; // Interfaces @@ -27,8 +26,8 @@ import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// wait for the one-week challenge period to elapse before their Optimism-native NFT /// can be refunded on L2. contract L2ERC721Bridge is ERC721Bridge, ISemver { - /// @custom:semver 1.7.1-beta.2 - string public constant version = "1.7.1-beta.2"; + /// @custom:semver 1.7.1-beta.3 + string public constant version = "1.7.1-beta.3"; /// @notice Constructs the L2ERC721Bridge contract. constructor() ERC721Bridge() { diff --git a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol index ffbec844e2ff..6b500e2b4dfc 100644 --- a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol +++ b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.25; import { IOptimismSuperchainERC20Extension } from "src/L2/interfaces/IOptimismSuperchainERC20.sol"; -import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { ERC20 } from "@solady/tokens/ERC20.sol"; @@ -63,8 +62,8 @@ contract OptimismSuperchainERC20 is } /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.4 - string public constant version = "1.0.0-beta.4"; + /// @custom:semver 1.0.0-beta.5 + string public constant version = "1.0.0-beta.5"; /// @notice Constructs the OptimismSuperchainERC20 contract. constructor() { diff --git a/packages/contracts-bedrock/src/L2/SequencerFeeVault.sol b/packages/contracts-bedrock/src/L2/SequencerFeeVault.sol index fecbb7e1b7cd..69a78219e5bd 100644 --- a/packages/contracts-bedrock/src/L2/SequencerFeeVault.sol +++ b/packages/contracts-bedrock/src/L2/SequencerFeeVault.sol @@ -2,7 +2,9 @@ pragma solidity 0.8.15; import { ISemver } from "src/universal/interfaces/ISemver.sol"; -import { FeeVault } from "src/universal/FeeVault.sol"; +import { FeeVault } from "src/L2/FeeVault.sol"; + +import { Types } from "src/libraries/Types.sol"; /// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000011 @@ -10,8 +12,8 @@ import { FeeVault } from "src/universal/FeeVault.sol"; /// @notice The SequencerFeeVault is the contract that holds any fees paid to the Sequencer during /// transaction processing and block production. contract SequencerFeeVault is FeeVault, ISemver { - /// @custom:semver 1.5.0-beta.2 - string public constant version = "1.5.0-beta.2"; + /// @custom:semver 1.5.0-beta.3 + string public constant version = "1.5.0-beta.3"; /// @notice Constructs the SequencerFeeVault contract. /// @param _recipient Wallet that will receive the fees. @@ -20,7 +22,7 @@ contract SequencerFeeVault is FeeVault, ISemver { constructor( address _recipient, uint256 _minWithdrawalAmount, - WithdrawalNetwork _withdrawalNetwork + Types.WithdrawalNetwork _withdrawalNetwork ) FeeVault(_recipient, _minWithdrawalAmount, _withdrawalNetwork) { } diff --git a/packages/contracts-bedrock/src/L2/interfaces/IBaseFeeVault.sol b/packages/contracts-bedrock/src/L2/interfaces/IBaseFeeVault.sol index 5906281cf747..456964409c83 100644 --- a/packages/contracts-bedrock/src/L2/interfaces/IBaseFeeVault.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/IBaseFeeVault.sol @@ -1,29 +1,34 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { IFeeVault } from "src/universal/interfaces/IFeeVault.sol"; +library Types { + enum WithdrawalNetwork { + L1, + L2 + } +} interface IBaseFeeVault { event Withdrawal(uint256 value, address to, address from); - event Withdrawal(uint256 value, address to, address from, IFeeVault.WithdrawalNetwork withdrawalNetwork); + event Withdrawal(uint256 value, address to, address from, Types.WithdrawalNetwork withdrawalNetwork); receive() external payable; function MIN_WITHDRAWAL_AMOUNT() external view returns (uint256); function RECIPIENT() external view returns (address); - function WITHDRAWAL_NETWORK() external view returns (IFeeVault.WithdrawalNetwork); + function WITHDRAWAL_NETWORK() external view returns (Types.WithdrawalNetwork); function minWithdrawalAmount() external view returns (uint256 amount_); function recipient() external view returns (address recipient_); function totalProcessed() external view returns (uint256); function withdraw() external; - function withdrawalNetwork() external view returns (IFeeVault.WithdrawalNetwork network_); + function withdrawalNetwork() external view returns (Types.WithdrawalNetwork network_); function version() external view returns (string memory); function __constructor__( address _recipient, uint256 _minWithdrawalAmount, - IFeeVault.WithdrawalNetwork _withdrawalNetwork + Types.WithdrawalNetwork _withdrawalNetwork ) external; } diff --git a/packages/contracts-bedrock/src/universal/interfaces/IFeeVault.sol b/packages/contracts-bedrock/src/L2/interfaces/IFeeVault.sol similarity index 68% rename from packages/contracts-bedrock/src/universal/interfaces/IFeeVault.sol rename to packages/contracts-bedrock/src/L2/interfaces/IFeeVault.sol index 403f603fae0c..3b4cd0209f13 100644 --- a/packages/contracts-bedrock/src/universal/interfaces/IFeeVault.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/IFeeVault.sol @@ -1,25 +1,27 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -interface IFeeVault { +library Types { enum WithdrawalNetwork { L1, L2 } +} +interface IFeeVault { event Withdrawal(uint256 value, address to, address from); - event Withdrawal(uint256 value, address to, address from, WithdrawalNetwork withdrawalNetwork); + event Withdrawal(uint256 value, address to, address from, Types.WithdrawalNetwork withdrawalNetwork); receive() external payable; function MIN_WITHDRAWAL_AMOUNT() external view returns (uint256); function RECIPIENT() external view returns (address); - function WITHDRAWAL_NETWORK() external view returns (WithdrawalNetwork); + function WITHDRAWAL_NETWORK() external view returns (Types.WithdrawalNetwork); function minWithdrawalAmount() external view returns (uint256 amount_); function recipient() external view returns (address recipient_); function totalProcessed() external view returns (uint256); function withdraw() external; - function withdrawalNetwork() external view returns (WithdrawalNetwork network_); + function withdrawalNetwork() external view returns (Types.WithdrawalNetwork network_); function __constructor__() external; } diff --git a/packages/contracts-bedrock/src/L2/interfaces/IL1FeeVault.sol b/packages/contracts-bedrock/src/L2/interfaces/IL1FeeVault.sol index 7853375bcd3a..5b0e5795abb1 100644 --- a/packages/contracts-bedrock/src/L2/interfaces/IL1FeeVault.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/IL1FeeVault.sol @@ -1,29 +1,34 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { IFeeVault } from "src/universal/interfaces/IFeeVault.sol"; +library Types { + enum WithdrawalNetwork { + L1, + L2 + } +} interface IL1FeeVault { event Withdrawal(uint256 value, address to, address from); - event Withdrawal(uint256 value, address to, address from, IFeeVault.WithdrawalNetwork withdrawalNetwork); + event Withdrawal(uint256 value, address to, address from, Types.WithdrawalNetwork withdrawalNetwork); receive() external payable; function MIN_WITHDRAWAL_AMOUNT() external view returns (uint256); function RECIPIENT() external view returns (address); - function WITHDRAWAL_NETWORK() external view returns (IFeeVault.WithdrawalNetwork); + function WITHDRAWAL_NETWORK() external view returns (Types.WithdrawalNetwork); function minWithdrawalAmount() external view returns (uint256 amount_); function recipient() external view returns (address recipient_); function totalProcessed() external view returns (uint256); function withdraw() external; - function withdrawalNetwork() external view returns (IFeeVault.WithdrawalNetwork network_); + function withdrawalNetwork() external view returns (Types.WithdrawalNetwork network_); function version() external view returns (string memory); function __constructor__( address _recipient, uint256 _minWithdrawalAmount, - IFeeVault.WithdrawalNetwork _withdrawalNetwork + Types.WithdrawalNetwork _withdrawalNetwork ) external; } diff --git a/packages/contracts-bedrock/src/L2/interfaces/ISequencerFeeVault.sol b/packages/contracts-bedrock/src/L2/interfaces/ISequencerFeeVault.sol index 51d31d99322b..9d5e60f9cca9 100644 --- a/packages/contracts-bedrock/src/L2/interfaces/ISequencerFeeVault.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/ISequencerFeeVault.sol @@ -1,22 +1,27 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { IFeeVault } from "src/universal/interfaces/IFeeVault.sol"; +library Types { + enum WithdrawalNetwork { + L1, + L2 + } +} interface ISequencerFeeVault { event Withdrawal(uint256 value, address to, address from); - event Withdrawal(uint256 value, address to, address from, IFeeVault.WithdrawalNetwork withdrawalNetwork); + event Withdrawal(uint256 value, address to, address from, Types.WithdrawalNetwork withdrawalNetwork); receive() external payable; function MIN_WITHDRAWAL_AMOUNT() external view returns (uint256); function RECIPIENT() external view returns (address); - function WITHDRAWAL_NETWORK() external view returns (IFeeVault.WithdrawalNetwork); + function WITHDRAWAL_NETWORK() external view returns (Types.WithdrawalNetwork); function minWithdrawalAmount() external view returns (uint256 amount_); function recipient() external view returns (address recipient_); function totalProcessed() external view returns (uint256); function withdraw() external; - function withdrawalNetwork() external view returns (IFeeVault.WithdrawalNetwork network_); + function withdrawalNetwork() external view returns (Types.WithdrawalNetwork network_); function version() external view returns (string memory); function l1FeeWallet() external view returns (address); @@ -24,7 +29,7 @@ interface ISequencerFeeVault { function __constructor__( address _recipient, uint256 _minWithdrawalAmount, - IFeeVault.WithdrawalNetwork _withdrawalNetwork + Types.WithdrawalNetwork _withdrawalNetwork ) external; } diff --git a/packages/contracts-bedrock/src/cannon/MIPS.sol b/packages/contracts-bedrock/src/cannon/MIPS.sol index e6c8d02cc349..7b544b25a3b8 100644 --- a/packages/contracts-bedrock/src/cannon/MIPS.sol +++ b/packages/contracts-bedrock/src/cannon/MIPS.sol @@ -3,7 +3,6 @@ pragma solidity 0.8.15; import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { IPreimageOracle } from "./interfaces/IPreimageOracle.sol"; -import { PreimageKeyLib } from "./PreimageKeyLib.sol"; import { MIPSInstructions as ins } from "src/cannon/libraries/MIPSInstructions.sol"; import { MIPSSyscalls as sys } from "src/cannon/libraries/MIPSSyscalls.sol"; import { MIPSState as st } from "src/cannon/libraries/MIPSState.sol"; @@ -45,8 +44,8 @@ contract MIPS is ISemver { } /// @notice The semantic version of the MIPS contract. - /// @custom:semver 1.2.1-beta.2 - string public constant version = "1.2.1-beta.2"; + /// @custom:semver 1.2.1-beta.3 + string public constant version = "1.2.1-beta.3"; /// @notice The preimage oracle contract. IPreimageOracle internal immutable ORACLE; diff --git a/packages/contracts-bedrock/src/cannon/PreimageOracle.sol b/packages/contracts-bedrock/src/cannon/PreimageOracle.sol index ac8e70b8da76..4dea97fc68b1 100644 --- a/packages/contracts-bedrock/src/cannon/PreimageOracle.sol +++ b/packages/contracts-bedrock/src/cannon/PreimageOracle.sol @@ -33,8 +33,8 @@ contract PreimageOracle is ISemver { uint256 public constant PRECOMPILE_CALL_RESERVED_GAS = 100_000; /// @notice The semantic version of the Preimage Oracle contract. - /// @custom:semver 1.1.3-beta.4 - string public constant version = "1.1.3-beta.4"; + /// @custom:semver 1.1.3-beta.5 + string public constant version = "1.1.3-beta.5"; //////////////////////////////////////////////////////////////// // Authorized Preimage Parts // @@ -97,7 +97,7 @@ contract PreimageOracle is ISemver { // Make sure challenge period fits within uint64 so that it can safely be used within the // FaultDisputeGame contract to compute clock extensions. Adding this check is simpler than // changing the existing contract ABI. - require(_challengePeriod <= type(uint64).max, "challenge period too large"); + require(_challengePeriod <= type(uint64).max, "PreimageOracle: challenge period too large"); // Compute hashes in empty sparse Merkle tree. The first hash is not set, and kept as zero as the identity. for (uint256 height = 0; height < KECCAK_TREE_DEPTH - 1; height++) { diff --git a/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol b/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol index a11cdd9be0c8..ccd29fac9d11 100644 --- a/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol @@ -14,7 +14,6 @@ import "src/dispute/lib/Errors.sol"; // Interfaces import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; -import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; import { IBigStepper, IPreimageOracle } from "src/dispute/interfaces/IBigStepper.sol"; import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; @@ -104,8 +103,8 @@ contract FaultDisputeGame is Clone, ISemver { uint256 internal constant HEADER_BLOCK_NUMBER_INDEX = 8; /// @notice Semantic version. - /// @custom:semver 1.3.1-beta.3 - string public constant version = "1.3.1-beta.3"; + /// @custom:semver 1.3.1-beta.4 + string public constant version = "1.3.1-beta.4"; /// @notice The starting timestamp of the game Timestamp public createdAt; diff --git a/packages/contracts-bedrock/src/legacy/interfaces/IDeployerWhitelist.sol b/packages/contracts-bedrock/src/legacy/interfaces/IDeployerWhitelist.sol index d1e711ea42ff..0650db4f8f7a 100644 --- a/packages/contracts-bedrock/src/legacy/interfaces/IDeployerWhitelist.sol +++ b/packages/contracts-bedrock/src/legacy/interfaces/IDeployerWhitelist.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { ISemver } from "src/universal/interfaces/ISemver.sol"; - /// @title IDeployerWhitelist /// @notice Interface for the DeployerWhitelist contract. interface IDeployerWhitelist { diff --git a/packages/contracts-bedrock/src/libraries/Types.sol b/packages/contracts-bedrock/src/libraries/Types.sol index 36582d5d3354..7e9a65654bc1 100644 --- a/packages/contracts-bedrock/src/libraries/Types.sol +++ b/packages/contracts-bedrock/src/libraries/Types.sol @@ -67,4 +67,12 @@ library Types { uint256 gasLimit; bytes data; } + + /// @notice Enum representing where the FeeVault withdraws funds to. + /// @custom:value L1 FeeVault withdraws funds to L1. + /// @custom:value L2 FeeVault withdraws funds to L2. + enum WithdrawalNetwork { + L1, + L2 + } } diff --git a/packages/contracts-bedrock/src/universal/OptimismMintableERC721Factory.sol b/packages/contracts-bedrock/src/universal/OptimismMintableERC721Factory.sol index e9bc81524f86..943859a7db1c 100644 --- a/packages/contracts-bedrock/src/universal/OptimismMintableERC721Factory.sol +++ b/packages/contracts-bedrock/src/universal/OptimismMintableERC721Factory.sol @@ -7,9 +7,11 @@ import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// @title OptimismMintableERC721Factory /// @notice Factory contract for creating OptimismMintableERC721 contracts. contract OptimismMintableERC721Factory is ISemver { + /// @custom:legacy true /// @notice Address of the ERC721 bridge on this network. address public immutable BRIDGE; + /// @custom:legacy true /// @notice Chain ID for the remote network. uint256 public immutable REMOTE_CHAIN_ID; @@ -23,8 +25,8 @@ contract OptimismMintableERC721Factory is ISemver { event OptimismMintableERC721Created(address indexed localToken, address indexed remoteToken, address deployer); /// @notice Semantic version. - /// @custom:semver 1.4.1-beta.2 - string public constant version = "1.4.1-beta.2"; + /// @custom:semver 1.4.1-beta.3 + string public constant version = "1.4.1-beta.3"; /// @notice The semver MUST be bumped any time that there is a change in /// the OptimismMintableERC721 token contract since this contract @@ -36,6 +38,16 @@ contract OptimismMintableERC721Factory is ISemver { REMOTE_CHAIN_ID = _remoteChainId; } + /// @notice Address of the ERC721 bridge on this network. + function bridge() external view returns (address) { + return BRIDGE; + } + + /// @notice Chain ID for the remote network. + function remoteChainID() external view returns (uint256) { + return REMOTE_CHAIN_ID; + } + /// @notice Creates an instance of the standard ERC721. /// @param _remoteToken Address of the corresponding token on the other domain. /// @param _name ERC721 name. diff --git a/packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC721Factory.sol b/packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC721Factory.sol index 2b09da39e515..be3e8ad05425 100644 --- a/packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC721Factory.sol +++ b/packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC721Factory.sol @@ -6,6 +6,7 @@ interface IOptimismMintableERC721Factory { function BRIDGE() external view returns (address); function REMOTE_CHAIN_ID() external view returns (uint256); + function bridge() external view returns (address); function createOptimismMintableERC721( address _remoteToken, string memory _name, @@ -14,6 +15,7 @@ interface IOptimismMintableERC721Factory { external returns (address); function isOptimismMintableERC721(address) external view returns (bool); + function remoteChainID() external view returns (uint256); function version() external view returns (string memory); function __constructor__(address _bridge, uint256 _remoteChainId) external; diff --git a/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol index 8740c09d38ca..2c6b5b66456d 100644 --- a/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol @@ -3,14 +3,13 @@ pragma solidity 0.8.15; // Testing utilities import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; -import { Reverter, ConfigurableCaller } from "test/mocks/Callers.sol"; +import { Reverter } from "test/mocks/Callers.sol"; // Libraries import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { Hashing } from "src/libraries/Hashing.sol"; import { Encoding } from "src/libraries/Encoding.sol"; -import { Constants } from "src/libraries/Constants.sol"; // Target contract dependencies import { IL1CrossDomainMessenger } from "src/L1/interfaces/IL1CrossDomainMessenger.sol"; diff --git a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol index abe7196070e8..f01572733bc4 100644 --- a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol @@ -11,7 +11,6 @@ import { StandardBridge } from "src/universal/StandardBridge.sol"; // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; -import { Constants } from "src/libraries/Constants.sol"; import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; // Interfaces diff --git a/packages/contracts-bedrock/test/L1/L2OutputOracle.t.sol b/packages/contracts-bedrock/test/L1/L2OutputOracle.t.sol index 7acca0fae187..035fffd263d3 100644 --- a/packages/contracts-bedrock/test/L1/L2OutputOracle.t.sol +++ b/packages/contracts-bedrock/test/L1/L2OutputOracle.t.sol @@ -9,7 +9,6 @@ import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; // Libraries import { Types } from "src/libraries/Types.sol"; -import { Constants } from "src/libraries/Constants.sol"; // Target contract dependencies import { Proxy } from "src/universal/Proxy.sol"; diff --git a/packages/contracts-bedrock/test/L1/ProtocolVersions.t.sol b/packages/contracts-bedrock/test/L1/ProtocolVersions.t.sol index 41eed4a930e6..fc6ea447d231 100644 --- a/packages/contracts-bedrock/test/L1/ProtocolVersions.t.sol +++ b/packages/contracts-bedrock/test/L1/ProtocolVersions.t.sol @@ -5,9 +5,6 @@ pragma solidity 0.8.15; import { CommonTest } from "test/setup/CommonTest.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; -// Libraries -import { Constants } from "src/libraries/Constants.sol"; - // Interfaces import { IProxy } from "src/universal/interfaces/IProxy.sol"; import { IProtocolVersions, ProtocolVersion } from "src/L1/interfaces/IProtocolVersions.sol"; diff --git a/packages/contracts-bedrock/test/L1/SuperchainConfig.t.sol b/packages/contracts-bedrock/test/L1/SuperchainConfig.t.sol index 409bb0003941..ece5c68254c9 100644 --- a/packages/contracts-bedrock/test/L1/SuperchainConfig.t.sol +++ b/packages/contracts-bedrock/test/L1/SuperchainConfig.t.sol @@ -3,10 +3,6 @@ pragma solidity 0.8.15; import { CommonTest } from "test/setup/CommonTest.sol"; -// Libraries -import { Types } from "src/libraries/Types.sol"; -import { Hashing } from "src/libraries/Hashing.sol"; - // Target contract dependencies import { Proxy } from "src/universal/Proxy.sol"; diff --git a/packages/contracts-bedrock/test/L1/SystemConfig.t.sol b/packages/contracts-bedrock/test/L1/SystemConfig.t.sol index aad093e3283a..f2a0af0d0b99 100644 --- a/packages/contracts-bedrock/test/L1/SystemConfig.t.sol +++ b/packages/contracts-bedrock/test/L1/SystemConfig.t.sol @@ -3,7 +3,6 @@ pragma solidity 0.8.15; // Testing import { CommonTest } from "test/setup/CommonTest.sol"; -import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; // Contracts import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; diff --git a/packages/contracts-bedrock/test/universal/FeeVault.t.sol b/packages/contracts-bedrock/test/L2/BaseFeeVault.t.sol similarity index 51% rename from packages/contracts-bedrock/test/universal/FeeVault.t.sol rename to packages/contracts-bedrock/test/L2/BaseFeeVault.t.sol index b9630d73b3f6..bf63a700c098 100644 --- a/packages/contracts-bedrock/test/universal/FeeVault.t.sol +++ b/packages/contracts-bedrock/test/L2/BaseFeeVault.t.sol @@ -4,28 +4,18 @@ pragma solidity 0.8.15; // Testing utilities import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; -// Target contract -import { FeeVault } from "src/universal/FeeVault.sol"; +// Libraries +import { Types } from "src/libraries/Types.sol"; // Test the implementations of the FeeVault contract FeeVault_Test is Bridge_Initializer { - /// @dev Tests that the constructor sets the correct values. - function test_constructor_l1FeeVault_succeeds() external view { - assertEq(l1FeeVault.RECIPIENT(), deploy.cfg().l1FeeVaultRecipient()); - assertEq(l1FeeVault.recipient(), deploy.cfg().l1FeeVaultRecipient()); - assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), deploy.cfg().l1FeeVaultMinimumWithdrawalAmount()); - assertEq(l1FeeVault.minWithdrawalAmount(), deploy.cfg().l1FeeVaultMinimumWithdrawalAmount()); - assertEq(uint8(l1FeeVault.WITHDRAWAL_NETWORK()), uint8(FeeVault.WithdrawalNetwork.L1)); - assertEq(uint8(l1FeeVault.withdrawalNetwork()), uint8(FeeVault.WithdrawalNetwork.L1)); - } - /// @dev Tests that the constructor sets the correct values. function test_constructor_baseFeeVault_succeeds() external view { assertEq(baseFeeVault.RECIPIENT(), deploy.cfg().baseFeeVaultRecipient()); assertEq(baseFeeVault.recipient(), deploy.cfg().baseFeeVaultRecipient()); assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), deploy.cfg().baseFeeVaultMinimumWithdrawalAmount()); assertEq(baseFeeVault.minWithdrawalAmount(), deploy.cfg().baseFeeVaultMinimumWithdrawalAmount()); - assertEq(uint8(baseFeeVault.WITHDRAWAL_NETWORK()), uint8(FeeVault.WithdrawalNetwork.L1)); - assertEq(uint8(baseFeeVault.withdrawalNetwork()), uint8(FeeVault.WithdrawalNetwork.L1)); + assertEq(uint8(baseFeeVault.WITHDRAWAL_NETWORK()), uint8(Types.WithdrawalNetwork.L1)); + assertEq(uint8(baseFeeVault.withdrawalNetwork()), uint8(Types.WithdrawalNetwork.L1)); } } diff --git a/packages/contracts-bedrock/test/L2/L1FeeVault.t.sol b/packages/contracts-bedrock/test/L2/L1FeeVault.t.sol new file mode 100644 index 000000000000..03a3e7e5ad9b --- /dev/null +++ b/packages/contracts-bedrock/test/L2/L1FeeVault.t.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +// Testing utilities +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; + +// Libraries +import { Types } from "src/libraries/Types.sol"; + +// Test the implementations of the FeeVault +contract FeeVault_Test is Bridge_Initializer { + /// @dev Tests that the constructor sets the correct values. + function test_constructor_l1FeeVault_succeeds() external view { + assertEq(l1FeeVault.RECIPIENT(), deploy.cfg().l1FeeVaultRecipient()); + assertEq(l1FeeVault.recipient(), deploy.cfg().l1FeeVaultRecipient()); + assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), deploy.cfg().l1FeeVaultMinimumWithdrawalAmount()); + assertEq(l1FeeVault.minWithdrawalAmount(), deploy.cfg().l1FeeVaultMinimumWithdrawalAmount()); + assertEq(uint8(l1FeeVault.WITHDRAWAL_NETWORK()), uint8(Types.WithdrawalNetwork.L1)); + assertEq(uint8(l1FeeVault.withdrawalNetwork()), uint8(Types.WithdrawalNetwork.L1)); + } +} diff --git a/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol index 1c13ece264fc..26fc9f2d039d 100644 --- a/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol @@ -3,14 +3,13 @@ pragma solidity 0.8.15; // Testing import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; -import { Reverter, ConfigurableCaller } from "test/mocks/Callers.sol"; +import { Reverter } from "test/mocks/Callers.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; // Libraries import { Hashing } from "src/libraries/Hashing.sol"; import { Encoding } from "src/libraries/Encoding.sol"; import { Types } from "src/libraries/Types.sol"; -import { Constants } from "src/libraries/Constants.sol"; import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; // Interfaces diff --git a/packages/contracts-bedrock/test/L2/L2ERC721Bridge.t.sol b/packages/contracts-bedrock/test/L2/L2ERC721Bridge.t.sol index 664655f38a3b..6ee1312d94d7 100644 --- a/packages/contracts-bedrock/test/L2/L2ERC721Bridge.t.sol +++ b/packages/contracts-bedrock/test/L2/L2ERC721Bridge.t.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.15; // Testing -import { console } from "forge-std/console.sol"; import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; // Contracts diff --git a/packages/contracts-bedrock/test/L2/L2StandardBridgeInterop.t.sol b/packages/contracts-bedrock/test/L2/L2StandardBridgeInterop.t.sol index db8ca94e37c8..819b3562c98e 100644 --- a/packages/contracts-bedrock/test/L2/L2StandardBridgeInterop.t.sol +++ b/packages/contracts-bedrock/test/L2/L2StandardBridgeInterop.t.sol @@ -4,10 +4,6 @@ pragma solidity 0.8.15; // Testing import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; -// Libraries -// TODO: Replace Predeploys.OPTIMISM_SUPERCHAIN_ERC20_FACTORY with optimismSuperchainERC20Factory -import { Predeploys } from "src/libraries/Predeploys.sol"; - // Interfaces import { IL2StandardBridgeInterop, IMintableAndBurnable } from "src/L2/interfaces/IL2StandardBridgeInterop.sol"; import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; diff --git a/packages/contracts-bedrock/test/L2/OptimismSuperchainERC20.t.sol b/packages/contracts-bedrock/test/L2/OptimismSuperchainERC20.t.sol index b8de1468421b..95091c5f0ded 100644 --- a/packages/contracts-bedrock/test/L2/OptimismSuperchainERC20.t.sol +++ b/packages/contracts-bedrock/test/L2/OptimismSuperchainERC20.t.sol @@ -9,7 +9,6 @@ import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { IERC20 } from "@openzeppelin/contracts-v5/token/ERC20/IERC20.sol"; import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; -import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; import { Initializable } from "@openzeppelin/contracts-v5/proxy/utils/Initializable.sol"; import { IERC165 } from "@openzeppelin/contracts-v5/utils/introspection/IERC165.sol"; import { IBeacon } from "@openzeppelin/contracts-v5/proxy/beacon/IBeacon.sol"; diff --git a/packages/contracts-bedrock/test/L2/Predeploys.t.sol b/packages/contracts-bedrock/test/L2/Predeploys.t.sol index 6c9ac3750a03..5baa22534ecf 100644 --- a/packages/contracts-bedrock/test/L2/Predeploys.t.sol +++ b/packages/contracts-bedrock/test/L2/Predeploys.t.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.15; import { CommonTest } from "test/setup/CommonTest.sol"; -import { ForgeArtifacts } from "scripts/libraries/ForgeArtifacts.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; diff --git a/packages/contracts-bedrock/test/L2/Preinstalls.t.sol b/packages/contracts-bedrock/test/L2/Preinstalls.t.sol index 9154dfc064c6..ad14e5ea32fb 100644 --- a/packages/contracts-bedrock/test/L2/Preinstalls.t.sol +++ b/packages/contracts-bedrock/test/L2/Preinstalls.t.sol @@ -4,7 +4,6 @@ pragma solidity 0.8.15; import { CommonTest } from "test/setup/CommonTest.sol"; import { Preinstalls } from "src/libraries/Preinstalls.sol"; import { Bytes } from "src/libraries/Bytes.sol"; -import { console2 as console } from "forge-std/console2.sol"; import { IEIP712 } from "src/universal/interfaces/IEIP712.sol"; /// @title PreinstallsTest diff --git a/packages/contracts-bedrock/test/L2/SequencerFeeVault.t.sol b/packages/contracts-bedrock/test/L2/SequencerFeeVault.t.sol index 1367e00bbc9c..2d6ba4e94ec8 100644 --- a/packages/contracts-bedrock/test/L2/SequencerFeeVault.t.sol +++ b/packages/contracts-bedrock/test/L2/SequencerFeeVault.t.sol @@ -7,7 +7,6 @@ import { Reverter } from "test/mocks/Callers.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; // Contracts -import { FeeVault } from "src/universal/FeeVault.sol"; import { SequencerFeeVault } from "src/L2/SequencerFeeVault.sol"; // Libraries @@ -31,8 +30,8 @@ contract SequencerFeeVault_Test is CommonTest { assertEq(sequencerFeeVault.recipient(), recipient); assertEq(sequencerFeeVault.MIN_WITHDRAWAL_AMOUNT(), deploy.cfg().sequencerFeeVaultMinimumWithdrawalAmount()); assertEq(sequencerFeeVault.minWithdrawalAmount(), deploy.cfg().sequencerFeeVaultMinimumWithdrawalAmount()); - assertEq(uint8(sequencerFeeVault.WITHDRAWAL_NETWORK()), uint8(FeeVault.WithdrawalNetwork.L1)); - assertEq(uint8(sequencerFeeVault.withdrawalNetwork()), uint8(FeeVault.WithdrawalNetwork.L1)); + assertEq(uint8(sequencerFeeVault.WITHDRAWAL_NETWORK()), uint8(Types.WithdrawalNetwork.L1)); + assertEq(uint8(sequencerFeeVault.withdrawalNetwork()), uint8(Types.WithdrawalNetwork.L1)); } /// @dev Tests that the fee vault is able to receive ETH. @@ -66,7 +65,7 @@ contract SequencerFeeVault_Test is CommonTest { vm.expectEmit(address(Predeploys.SEQUENCER_FEE_WALLET)); emit Withdrawal(address(sequencerFeeVault).balance, recipient, address(this)); vm.expectEmit(address(Predeploys.SEQUENCER_FEE_WALLET)); - emit Withdrawal(address(sequencerFeeVault).balance, recipient, address(this), FeeVault.WithdrawalNetwork.L1); + emit Withdrawal(address(sequencerFeeVault).balance, recipient, address(this), Types.WithdrawalNetwork.L1); // The entire vault's balance is withdrawn vm.expectCall(Predeploys.L2_TO_L1_MESSAGE_PASSER, address(sequencerFeeVault).balance, hex""); @@ -116,7 +115,7 @@ contract SequencerFeeVault_L2Withdrawal_Test is CommonTest { new SequencerFeeVault( deploy.cfg().sequencerFeeVaultRecipient(), deploy.cfg().sequencerFeeVaultMinimumWithdrawalAmount(), - FeeVault.WithdrawalNetwork.L2 + Types.WithdrawalNetwork.L2 ) ).code ); @@ -136,10 +135,7 @@ contract SequencerFeeVault_L2Withdrawal_Test is CommonTest { emit Withdrawal(address(sequencerFeeVault).balance, sequencerFeeVault.RECIPIENT(), address(this)); vm.expectEmit(address(Predeploys.SEQUENCER_FEE_WALLET)); emit Withdrawal( - address(sequencerFeeVault).balance, - sequencerFeeVault.RECIPIENT(), - address(this), - FeeVault.WithdrawalNetwork.L2 + address(sequencerFeeVault).balance, sequencerFeeVault.RECIPIENT(), address(this), Types.WithdrawalNetwork.L2 ); // The entire vault's balance is withdrawn diff --git a/packages/contracts-bedrock/test/cannon/PreimageOracle.t.sol b/packages/contracts-bedrock/test/cannon/PreimageOracle.t.sol index 902f22b41ad5..1d01f699632a 100644 --- a/packages/contracts-bedrock/test/cannon/PreimageOracle.t.sol +++ b/packages/contracts-bedrock/test/cannon/PreimageOracle.t.sol @@ -24,7 +24,7 @@ contract PreimageOracle_Test is Test { /// @param _challengePeriod The challenge period to test. function testFuzz_constructor_challengePeriodTooLarge_reverts(uint256 _challengePeriod) public { _challengePeriod = bound(_challengePeriod, uint256(type(uint64).max) + 1, type(uint256).max); - vm.expectRevert("challenge period too large"); + vm.expectRevert("PreimageOracle: challenge period too large"); new PreimageOracle(0, _challengePeriod); } @@ -860,6 +860,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { /// @notice Tests that squeezing a large preimage proposal after the challenge period has passed always succeeds and /// persists the correct data. + /// forge-config: ciheavy.fuzz.runs = 512 function testFuzz_squeezeLPP_succeeds(uint256 _numBlocks, uint32 _partOffset) public { _numBlocks = bound(_numBlocks, 1, 2 ** 8); _partOffset = uint32(bound(_partOffset, 0, _numBlocks * LibKeccak.BLOCK_SIZE_BYTES + 8 - 1)); @@ -1057,6 +1058,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { /// @notice Tests that challenging the first divergence in a large preimage proposal at an arbitrary location /// in the leaf values always succeeds. + /// forge-config: ciheavy.fuzz.runs = 512 function testFuzz_challenge_arbitraryLocation_succeeds(uint256 _lastCorrectLeafIdx, uint256 _numBlocks) public { _numBlocks = bound(_numBlocks, 1, 2 ** 8); _lastCorrectLeafIdx = bound(_lastCorrectLeafIdx, 0, _numBlocks - 1); @@ -1109,6 +1111,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { } /// @notice Tests that challenging the a divergence in a large preimage proposal at the first leaf always succeeds. + /// forge-config: ciheavy.fuzz.runs = 1024 function testFuzz_challengeFirst_succeeds(uint256 _numBlocks) public { _numBlocks = bound(_numBlocks, 1, 2 ** 8); diff --git a/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol b/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol index 36577a836df1..d26c31bd5324 100644 --- a/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol +++ b/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.15; // Testing import { Test } from "forge-std/Test.sol"; -import { Vm } from "forge-std/Vm.sol"; import { DisputeGameFactory_Init } from "test/dispute/DisputeGameFactory.t.sol"; import { AlphabetVM } from "test/mocks/AlphabetVM.sol"; @@ -13,12 +12,11 @@ import { PreimageOracle } from "src/cannon/PreimageOracle.sol"; import { DelayedWETH } from "src/dispute/DelayedWETH.sol"; // Libraries -import { Types } from "src/libraries/Types.sol"; import "src/dispute/lib/Types.sol"; import "src/dispute/lib/Errors.sol"; // Interfaces -import { IBigStepper, IPreimageOracle } from "src/dispute/interfaces/IBigStepper.sol"; +import { IPreimageOracle } from "src/dispute/interfaces/IBigStepper.sol"; import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; import { IPermissionedDisputeGame } from "src/dispute/interfaces/IPermissionedDisputeGame.sol"; diff --git a/packages/contracts-bedrock/test/dispute/lib/LibGameId.t.sol b/packages/contracts-bedrock/test/dispute/lib/LibGameId.t.sol index 70ca0dab6a8a..d7481dc042a6 100644 --- a/packages/contracts-bedrock/test/dispute/lib/LibGameId.t.sol +++ b/packages/contracts-bedrock/test/dispute/lib/LibGameId.t.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.15; import { Test } from "forge-std/Test.sol"; -import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; import "src/dispute/lib/Types.sol"; contract LibGameId_Test is Test { diff --git a/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/OptimismSuperchainERC20.t.sol b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/OptimismSuperchainERC20.t.sol index d90e90a2f811..4ecbafb05969 100644 --- a/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/OptimismSuperchainERC20.t.sol +++ b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/OptimismSuperchainERC20.t.sol @@ -2,15 +2,11 @@ pragma solidity 0.8.25; // Testing utilities -import { Test, StdUtils, Vm } from "forge-std/Test.sol"; -import { StdInvariant } from "forge-std/StdInvariant.sol"; -import { StdAssertions } from "forge-std/StdAssertions.sol"; -import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; +import { Test } from "forge-std/Test.sol"; // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; -import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; import { ProtocolGuided } from "./fuzz/Protocol.guided.t.sol"; import { ProtocolUnguided } from "./fuzz/Protocol.unguided.t.sol"; import { HandlerGetters } from "./helpers/HandlerGetters.t.sol"; diff --git a/packages/contracts-bedrock/test/kontrol/proofs/L1ERC721Bridge.k.sol b/packages/contracts-bedrock/test/kontrol/proofs/L1ERC721Bridge.k.sol index f7887f0f1a71..7f9df837739e 100644 --- a/packages/contracts-bedrock/test/kontrol/proofs/L1ERC721Bridge.k.sol +++ b/packages/contracts-bedrock/test/kontrol/proofs/L1ERC721Bridge.k.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.13; import { DeploymentSummary } from "./utils/DeploymentSummary.sol"; import { KontrolUtils } from "./utils/KontrolUtils.sol"; -import { Types } from "src/libraries/Types.sol"; import { IL1ERC721Bridge as L1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol"; import { ISuperchainConfig as SuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; import { ICrossDomainMessenger as CrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; diff --git a/packages/contracts-bedrock/test/kontrol/proofs/L1StandardBridge.k.sol b/packages/contracts-bedrock/test/kontrol/proofs/L1StandardBridge.k.sol index 8cefd5546e9e..1af1f600bff7 100644 --- a/packages/contracts-bedrock/test/kontrol/proofs/L1StandardBridge.k.sol +++ b/packages/contracts-bedrock/test/kontrol/proofs/L1StandardBridge.k.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.13; import { DeploymentSummary } from "./utils/DeploymentSummary.sol"; import { KontrolUtils } from "./utils/KontrolUtils.sol"; -import { Types } from "src/libraries/Types.sol"; import { IL1StandardBridge as L1StandardBridge } from "src/L1/interfaces/IL1StandardBridge.sol"; import { ISuperchainConfig as SuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; import { ICrossDomainMessenger as CrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; diff --git a/packages/contracts-bedrock/test/opcm/DeployImplementations.t.sol b/packages/contracts-bedrock/test/opcm/DeployImplementations.t.sol index 8e7ee96d388d..490d764698ca 100644 --- a/packages/contracts-bedrock/test/opcm/DeployImplementations.t.sol +++ b/packages/contracts-bedrock/test/opcm/DeployImplementations.t.sol @@ -438,6 +438,7 @@ contract DeployImplementations_Test is Test { dii.set(dii.challengePeriodSeconds.selector, challengePeriodSeconds); dii.set(dii.proofMaturityDelaySeconds.selector, proofMaturityDelaySeconds); dii.set(dii.disputeGameFinalityDelaySeconds.selector, disputeGameFinalityDelaySeconds); + dii.set(dii.mipsVersion.selector, 1); dii.set(dii.release.selector, release); dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy)); dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy)); @@ -451,6 +452,7 @@ contract DeployImplementations_Test is Test { assertEq(challengePeriodSeconds, dii.challengePeriodSeconds(), "300"); assertEq(proofMaturityDelaySeconds, dii.proofMaturityDelaySeconds(), "400"); assertEq(disputeGameFinalityDelaySeconds, dii.disputeGameFinalityDelaySeconds(), "500"); + assertEq(1, dii.mipsVersion(), "512"); assertEq(release, dii.release(), "525"); assertEq(address(superchainConfigProxy), address(dii.superchainConfigProxy()), "550"); assertEq(address(protocolVersionsProxy), address(dii.protocolVersionsProxy()), "575"); @@ -471,6 +473,7 @@ contract DeployImplementations_Test is Test { dii.set(dii.challengePeriodSeconds.selector, challengePeriodSeconds); dii.set(dii.proofMaturityDelaySeconds.selector, proofMaturityDelaySeconds); dii.set(dii.disputeGameFinalityDelaySeconds.selector, disputeGameFinalityDelaySeconds); + dii.set(dii.mipsVersion.selector, 1); string memory release = "dev-release"; dii.set(dii.release.selector, release); dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy)); diff --git a/packages/contracts-bedrock/test/opcm/DeployOPChain.t.sol b/packages/contracts-bedrock/test/opcm/DeployOPChain.t.sol index ec93c0ab2464..13460f35c632 100644 --- a/packages/contracts-bedrock/test/opcm/DeployOPChain.t.sol +++ b/packages/contracts-bedrock/test/opcm/DeployOPChain.t.sol @@ -16,21 +16,15 @@ import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; import { IProxyAdmin } from "src/universal/interfaces/IProxyAdmin.sol"; import { IAddressManager } from "src/legacy/interfaces/IAddressManager.sol"; -import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; -import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; import { IPermissionedDisputeGame } from "src/dispute/interfaces/IPermissionedDisputeGame.sol"; +import { IL1ChugSplashProxy } from "src/legacy/interfaces/IL1ChugSplashProxy.sol"; +import { IResolvedDelegateProxy } from "src/legacy/interfaces/IResolvedDelegateProxy.sol"; import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; import { IProtocolVersions, ProtocolVersion } from "src/L1/interfaces/IProtocolVersions.sol"; import { OPContractsManager } from "src/L1/OPContractsManager.sol"; -import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol"; -import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; -import { IL1CrossDomainMessenger } from "src/L1/interfaces/IL1CrossDomainMessenger.sol"; -import { IL1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol"; -import { IL1StandardBridge } from "src/L1/interfaces/IL1StandardBridge.sol"; -import { IOptimismMintableERC20Factory } from "src/universal/interfaces/IOptimismMintableERC20Factory.sol"; import { IProxy } from "src/universal/interfaces/IProxy.sol"; import { Claim, Duration, GameType, GameTypes, Hash, OutputRoot } from "src/dispute/lib/Types.sol"; @@ -55,20 +49,6 @@ contract DeployOPChainInput_Test is Test { doi = new DeployOPChainInput(); } - function buildOpcmProxy() public returns (IProxy opcmProxy) { - opcmProxy = IProxy( - DeployUtils.create1({ - _name: "Proxy", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IProxy.__constructor__, (address(0)))) - }) - ); - OPContractsManager opcmImpl = OPContractsManager(address(makeAddr("opcmImpl"))); - vm.prank(address(0)); - opcmProxy.upgradeTo(address(opcmImpl)); - vm.etch(address(opcmProxy), address(opcmProxy).code); - vm.etch(address(opcmImpl), hex"01"); - } - function test_set_succeeds() public { doi.set(doi.opChainProxyAdminOwner.selector, opChainProxyAdminOwner); doi.set(doi.systemConfigOwner.selector, systemConfigOwner); @@ -80,7 +60,7 @@ contract DeployOPChainInput_Test is Test { doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar); doi.set(doi.l2ChainId.selector, l2ChainId); - (IProxy opcmProxy) = buildOpcmProxy(); + (IProxy opcmProxy) = DeployUtils.buildERC1967ProxyWithImpl("opcmProxy"); doi.set(doi.opcmProxy.selector, address(opcmProxy)); // Compare the default inputs to the getter methods. @@ -131,27 +111,13 @@ contract DeployOPChainInput_Test is Test { contract DeployOPChainOutput_Test is Test { DeployOPChainOutput doo; - // Define default outputs to set. - // We set these in storage because doing it locally in test_set_succeeds results in stack too deep. - IProxyAdmin opChainProxyAdmin = IProxyAdmin(makeAddr("optimismPortal2Impl")); - IAddressManager addressManager = IAddressManager(makeAddr("delayedWETHImpl")); - IL1ERC721Bridge l1ERC721BridgeProxy = IL1ERC721Bridge(makeAddr("l1ERC721BridgeProxy")); - ISystemConfig systemConfigProxy = ISystemConfig(makeAddr("systemConfigProxy")); - IOptimismMintableERC20Factory optimismMintableERC20FactoryProxy = - IOptimismMintableERC20Factory(makeAddr("optimismMintableERC20FactoryProxy")); - IL1StandardBridge l1StandardBridgeProxy = IL1StandardBridge(payable(makeAddr("l1StandardBridgeProxy"))); - IL1CrossDomainMessenger l1CrossDomainMessengerProxy = - IL1CrossDomainMessenger(makeAddr("l1CrossDomainMessengerProxy")); - IOptimismPortal2 optimismPortalProxy = IOptimismPortal2(payable(makeAddr("optimismPortalProxy"))); - IDisputeGameFactory disputeGameFactoryProxy = IDisputeGameFactory(makeAddr("disputeGameFactoryProxy")); - IAnchorStateRegistry anchorStateRegistryProxy = IAnchorStateRegistry(makeAddr("anchorStateRegistryProxy")); + // We set the non proxy contracts in storage because doing it locally in 'test_set_succeeds' function results in + // stack too deep. + IAddressManager addressManager = DeployUtils.buildAddressManager(); + IProxyAdmin opChainProxyAdmin = IProxyAdmin(makeAddr("opChainProxyAdmin")); IAnchorStateRegistry anchorStateRegistryImpl = IAnchorStateRegistry(makeAddr("anchorStateRegistryImpl")); IFaultDisputeGame faultDisputeGame = IFaultDisputeGame(makeAddr("faultDisputeGame")); IPermissionedDisputeGame permissionedDisputeGame = IPermissionedDisputeGame(makeAddr("permissionedDisputeGame")); - IDelayedWETH delayedWETHPermissionedGameProxy = IDelayedWETH(payable(makeAddr("delayedWETHPermissionedGameProxy"))); - // TODO: Eventually switch from Permissioned to Permissionless. - // DelayedWETH delayedWETHPermissionlessGameProxy = - // DelayedWETH(payable(makeAddr("delayedWETHPermissionlessGameProxy"))); function setUp() public { doo = new DeployOPChainOutput(); @@ -159,21 +125,24 @@ contract DeployOPChainOutput_Test is Test { function test_set_succeeds() public { vm.etch(address(opChainProxyAdmin), hex"01"); - vm.etch(address(addressManager), hex"01"); - vm.etch(address(l1ERC721BridgeProxy), hex"01"); - vm.etch(address(systemConfigProxy), hex"01"); - vm.etch(address(optimismMintableERC20FactoryProxy), hex"01"); - vm.etch(address(l1StandardBridgeProxy), hex"01"); - vm.etch(address(l1CrossDomainMessengerProxy), hex"01"); - vm.etch(address(optimismPortalProxy), hex"01"); - vm.etch(address(disputeGameFactoryProxy), hex"01"); - vm.etch(address(anchorStateRegistryProxy), hex"01"); + (IProxy l1ERC721BridgeProxy) = DeployUtils.buildERC1967ProxyWithImpl("l1ERC721BridgeProxy"); + (IProxy systemConfigProxy) = DeployUtils.buildERC1967ProxyWithImpl("systemConfigProxy"); + (IProxy optimismMintableERC20FactoryProxy) = + DeployUtils.buildERC1967ProxyWithImpl("optimismMintableERC20FactoryProxy"); + (IL1ChugSplashProxy l1StandardBridgeProxy) = DeployUtils.buildL1ChugSplashProxyWithImpl("l1StandardBridgeProxy"); + (IResolvedDelegateProxy l1CrossDomainMessengerProxy) = + DeployUtils.buildResolvedDelegateProxyWithImpl(addressManager, "OVM_L1CrossDomainMessenger"); + (IProxy optimismPortalProxy) = DeployUtils.buildERC1967ProxyWithImpl("optimismPortalProxy"); + (IProxy disputeGameFactoryProxy) = DeployUtils.buildERC1967ProxyWithImpl("disputeGameFactoryProxy"); + (IProxy anchorStateRegistryProxy) = DeployUtils.buildERC1967ProxyWithImpl("anchorStateRegistryProxy"); vm.etch(address(anchorStateRegistryImpl), hex"01"); vm.etch(address(faultDisputeGame), hex"01"); vm.etch(address(permissionedDisputeGame), hex"01"); - vm.etch(address(delayedWETHPermissionedGameProxy), hex"01"); // TODO: Eventually switch from Permissioned to Permissionless. - // vm.etch(address(delayedWETHPermissionlessGameProxy), hex"01"); + // (IProxy delayedWETHPermissionlessGameProxy) = + // DeployUtils.buildERC1967ProxyWithImpl("delayedWETHPermissionlessGameProxy"); + (IProxy delayedWETHPermissionedGameProxy) = + DeployUtils.buildERC1967ProxyWithImpl("delayedWETHPermissionedGameProxy"); doo.set(doo.opChainProxyAdmin.selector, address(opChainProxyAdmin)); doo.set(doo.addressManager.selector, address(addressManager)); @@ -424,6 +393,7 @@ contract DeployOPChain_TestBase is Test { dii.set(dii.challengePeriodSeconds.selector, challengePeriodSeconds); dii.set(dii.proofMaturityDelaySeconds.selector, proofMaturityDelaySeconds); dii.set(dii.disputeGameFinalityDelaySeconds.selector, disputeGameFinalityDelaySeconds); + dii.set(dii.mipsVersion.selector, 1); dii.set(dii.release.selector, release); dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy)); dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy)); @@ -544,9 +514,22 @@ contract DeployOPChain_Test is DeployOPChain_TestBase { assertEq(doo.disputeGameFactoryProxy().initBonds(GameTypes.CANNON), 0, "2700"); assertEq(doo.disputeGameFactoryProxy().initBonds(GameTypes.PERMISSIONED_CANNON), 0, "2800"); - // Most architecture assertions are handled within the OP Contracts Manager itself and therefore - // we only assert on the things that are not visible onchain. - // TODO add these assertions: AddressManager, Proxy, ProxyAdmin, etc. + (Hash actualRoot,) = doo.anchorStateRegistryProxy().anchors(GameTypes.PERMISSIONED_CANNON); + assertEq(Hash.unwrap(actualRoot), 0xdead000000000000000000000000000000000000000000000000000000000000, "2900"); + assertEq(doo.permissionedDisputeGame().l2BlockNumber(), 0, "3000"); + assertEq( + Claim.unwrap(doo.permissionedDisputeGame().absolutePrestate()), + 0x038512e02c4c3f7bdaec27d00edf55b7155e0905301e1a88083e4e0a6764d54c, + "3100" + ); + assertEq(Duration.unwrap(doo.permissionedDisputeGame().clockExtension()), 10800, "3200"); + assertEq(Duration.unwrap(doo.permissionedDisputeGame().maxClockDuration()), 302400, "3300"); + assertEq(doo.permissionedDisputeGame().splitDepth(), 30, "3400"); + assertEq(doo.permissionedDisputeGame().maxGameDepth(), 73, "3500"); + + assertEq(address(doo.opChainProxyAdmin().addressManager().owner()), address(doo.opChainProxyAdmin()), "3600"); + assertEq(address(doo.opChainProxyAdmin().addressManager()), address(doo.addressManager()), "3700"); + assertEq(address(doo.opChainProxyAdmin().owner()), opChainProxyAdminOwner, "3800"); } } diff --git a/packages/contracts-bedrock/test/periphery/op-nft/Optimist.t.sol b/packages/contracts-bedrock/test/periphery/op-nft/Optimist.t.sol index 22b6effc7ed4..912b04ab33f6 100644 --- a/packages/contracts-bedrock/test/periphery/op-nft/Optimist.t.sol +++ b/packages/contracts-bedrock/test/periphery/op-nft/Optimist.t.sol @@ -9,7 +9,6 @@ import { Optimist } from "src/periphery/op-nft/Optimist.sol"; import { OptimistAllowlist } from "src/periphery/op-nft/OptimistAllowlist.sol"; import { OptimistInviter } from "src/periphery/op-nft/OptimistInviter.sol"; import { OptimistInviterHelper } from "test/mocks/OptimistInviterHelper.sol"; -import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; library Multicall { diff --git a/packages/contracts-bedrock/test/periphery/op-nft/OptimistInviter.t.sol b/packages/contracts-bedrock/test/periphery/op-nft/OptimistInviter.t.sol index a51ba54eff9c..58e71a13a8d7 100644 --- a/packages/contracts-bedrock/test/periphery/op-nft/OptimistInviter.t.sol +++ b/packages/contracts-bedrock/test/periphery/op-nft/OptimistInviter.t.sol @@ -6,7 +6,6 @@ import { Test } from "forge-std/Test.sol"; import { AttestationStation } from "src/periphery/op-nft/AttestationStation.sol"; import { OptimistInviter } from "src/periphery/op-nft/OptimistInviter.sol"; import { Optimist } from "src/periphery/op-nft/Optimist.sol"; -import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { TestERC1271Wallet } from "test/mocks/TestERC1271Wallet.sol"; import { OptimistInviterHelper } from "test/mocks/OptimistInviterHelper.sol"; import { OptimistConstants } from "src/periphery/op-nft/libraries/OptimistConstants.sol"; diff --git a/packages/contracts-bedrock/test/safe/DeployOwnership.t.sol b/packages/contracts-bedrock/test/safe/DeployOwnership.t.sol index 8e3a939686cb..973b888ddf68 100644 --- a/packages/contracts-bedrock/test/safe/DeployOwnership.t.sol +++ b/packages/contracts-bedrock/test/safe/DeployOwnership.t.sol @@ -13,7 +13,6 @@ import { Test } from "forge-std/Test.sol"; import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol"; import { ModuleManager } from "safe-contracts/base/ModuleManager.sol"; -import { GuardManager } from "safe-contracts/base/GuardManager.sol"; import { LivenessGuard } from "src/safe/LivenessGuard.sol"; import { LivenessModule } from "src/safe/LivenessModule.sol"; diff --git a/packages/contracts-bedrock/test/safe/LivenessModule.t.sol b/packages/contracts-bedrock/test/safe/LivenessModule.t.sol index 060dfb389ca4..e101f59ca5a4 100644 --- a/packages/contracts-bedrock/test/safe/LivenessModule.t.sol +++ b/packages/contracts-bedrock/test/safe/LivenessModule.t.sol @@ -4,7 +4,6 @@ pragma solidity 0.8.15; import { Test } from "forge-std/Test.sol"; import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol"; import { OwnerManager } from "safe-contracts/base/OwnerManager.sol"; -import { Enum } from "safe-contracts/common/Enum.sol"; import "test/safe-tools/SafeTestTools.sol"; import { LivenessModule } from "src/safe/LivenessModule.sol"; diff --git a/packages/contracts-bedrock/test/setup/Events.sol b/packages/contracts-bedrock/test/setup/Events.sol index a8eceed88fae..7f8017bfb2c1 100644 --- a/packages/contracts-bedrock/test/setup/Events.sol +++ b/packages/contracts-bedrock/test/setup/Events.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { FeeVault } from "src/universal/FeeVault.sol"; import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; import "src/dispute/lib/Types.sol"; +import { Types } from "src/libraries/Types.sol"; + /// @title Events /// @dev Contains various events that are tested against. This contract needs to /// exist until we either modularize the implementations or use a newer version of @@ -52,7 +53,7 @@ contract Events { event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex); event Withdrawal(uint256 value, address to, address from); - event Withdrawal(uint256 value, address to, address from, FeeVault.WithdrawalNetwork withdrawalNetwork); + event Withdrawal(uint256 value, address to, address from, Types.WithdrawalNetwork withdrawalNetwork); event ETHDepositInitiated(address indexed from, address indexed to, uint256 amount, bytes data); diff --git a/packages/contracts-bedrock/test/setup/Setup.sol b/packages/contracts-bedrock/test/setup/Setup.sol index 591f073c0949..32fe86b66b9f 100644 --- a/packages/contracts-bedrock/test/setup/Setup.sol +++ b/packages/contracts-bedrock/test/setup/Setup.sol @@ -6,12 +6,10 @@ import { console2 as console } from "forge-std/console2.sol"; import { Vm } from "forge-std/Vm.sol"; // Scripts -import { DeployConfig } from "scripts/deploy/DeployConfig.s.sol"; import { Deploy } from "scripts/deploy/Deploy.s.sol"; import { Fork, LATEST_FORK } from "scripts/libraries/Config.sol"; import { L2Genesis, L1Dependencies } from "scripts/L2Genesis.s.sol"; import { OutputMode, Fork, ForkUtils } from "scripts/libraries/Config.sol"; -import { Executables } from "scripts/libraries/Executables.sol"; // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; @@ -29,6 +27,7 @@ import { IDataAvailabilityChallenge } from "src/L1/interfaces/IDataAvailabilityC import { IL1StandardBridge } from "src/L1/interfaces/IL1StandardBridge.sol"; import { IProtocolVersions } from "src/L1/interfaces/IProtocolVersions.sol"; import { IL1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol"; +import { IOptimismMintableERC721Factory } from "src/universal/interfaces/IOptimismMintableERC721Factory.sol"; import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; @@ -96,6 +95,8 @@ contract Setup { IOptimismMintableERC20Factory l2OptimismMintableERC20Factory = IOptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY); IL2ERC721Bridge l2ERC721Bridge = IL2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE); + IOptimismMintableERC721Factory l2OptimismMintableERC721Factory = + IOptimismMintableERC721Factory(Predeploys.OPTIMISM_MINTABLE_ERC721_FACTORY); IBaseFeeVault baseFeeVault = IBaseFeeVault(payable(Predeploys.BASE_FEE_VAULT)); ISequencerFeeVault sequencerFeeVault = ISequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET)); IL1FeeVault l1FeeVault = IL1FeeVault(payable(Predeploys.L1_FEE_VAULT)); @@ -221,6 +222,7 @@ contract Setup { labelPredeploy(Predeploys.L2_TO_L1_MESSAGE_PASSER); labelPredeploy(Predeploys.SEQUENCER_FEE_WALLET); labelPredeploy(Predeploys.L2_ERC721_BRIDGE); + labelPredeploy(Predeploys.OPTIMISM_MINTABLE_ERC721_FACTORY); labelPredeploy(Predeploys.BASE_FEE_VAULT); labelPredeploy(Predeploys.L1_FEE_VAULT); labelPredeploy(Predeploys.L1_BLOCK_ATTRIBUTES); diff --git a/packages/contracts-bedrock/test/universal/CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/universal/CrossDomainMessenger.t.sol index 1fab9c6db1ce..dddb09d41239 100644 --- a/packages/contracts-bedrock/test/universal/CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/universal/CrossDomainMessenger.t.sol @@ -4,7 +4,6 @@ pragma solidity 0.8.15; // Testing utilities import { Test } from "forge-std/Test.sol"; import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; -import { CallerCaller, Reverter } from "test/mocks/Callers.sol"; // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; diff --git a/packages/contracts-bedrock/test/universal/OptimismMintableERC721Factory.t.sol b/packages/contracts-bedrock/test/universal/OptimismMintableERC721Factory.t.sol index 7fb6d079b85c..ef9019eafa04 100644 --- a/packages/contracts-bedrock/test/universal/OptimismMintableERC721Factory.t.sol +++ b/packages/contracts-bedrock/test/universal/OptimismMintableERC721Factory.t.sol @@ -7,23 +7,13 @@ import { OptimismMintableERC721 } from "src/universal/OptimismMintableERC721.sol import { OptimismMintableERC721Factory } from "src/universal/OptimismMintableERC721Factory.sol"; contract OptimismMintableERC721Factory_Test is Bridge_Initializer { - OptimismMintableERC721Factory internal factory; - event OptimismMintableERC721Created(address indexed localToken, address indexed remoteToken, address deployer); - function setUp() public override { - super.setUp(); - - // Set up the token pair. - factory = new OptimismMintableERC721Factory(address(l2ERC721Bridge), 1); - - // Label the addresses for nice traces. - vm.label(address(factory), "OptimismMintableERC721Factory"); - } - function test_constructor_succeeds() external view { - assertEq(factory.BRIDGE(), address(l2ERC721Bridge)); - assertEq(factory.REMOTE_CHAIN_ID(), 1); + assertEq(l2OptimismMintableERC721Factory.BRIDGE(), address(l2ERC721Bridge)); + assertEq(l2OptimismMintableERC721Factory.bridge(), address(l2ERC721Bridge)); + assertEq(l2OptimismMintableERC721Factory.REMOTE_CHAIN_ID(), deploy.cfg().l1ChainID()); + assertEq(l2OptimismMintableERC721Factory.remoteChainID(), deploy.cfg().l1ChainID()); } function test_createOptimismMintableERC721_succeeds() external { @@ -31,44 +21,45 @@ contract OptimismMintableERC721Factory_Test is Bridge_Initializer { address local = calculateTokenAddress(address(1234), "L2Token", "L2T"); // Expect a token creation event. - vm.expectEmit(true, true, true, true); + vm.expectEmit(address(l2OptimismMintableERC721Factory)); emit OptimismMintableERC721Created(local, remote, alice); // Create the token. vm.prank(alice); - OptimismMintableERC721 created = - OptimismMintableERC721(factory.createOptimismMintableERC721(remote, "L2Token", "L2T")); + OptimismMintableERC721 created = OptimismMintableERC721( + l2OptimismMintableERC721Factory.createOptimismMintableERC721(remote, "L2Token", "L2T") + ); // Token address should be correct. assertEq(address(created), local); // Should be marked as created by the factory. - assertEq(factory.isOptimismMintableERC721(address(created)), true); + assertTrue(l2OptimismMintableERC721Factory.isOptimismMintableERC721(address(created))); // Token should've been constructed correctly. assertEq(created.name(), "L2Token"); assertEq(created.symbol(), "L2T"); assertEq(created.REMOTE_TOKEN(), remote); assertEq(created.BRIDGE(), address(l2ERC721Bridge)); - assertEq(created.REMOTE_CHAIN_ID(), 1); + assertEq(created.REMOTE_CHAIN_ID(), deploy.cfg().l1ChainID()); } function test_createOptimismMintableERC721_sameTwice_reverts() external { address remote = address(1234); vm.prank(alice); - factory.createOptimismMintableERC721(remote, "L2Token", "L2T"); + l2OptimismMintableERC721Factory.createOptimismMintableERC721(remote, "L2Token", "L2T"); vm.expectRevert(bytes("")); vm.prank(alice); - factory.createOptimismMintableERC721(remote, "L2Token", "L2T"); + l2OptimismMintableERC721Factory.createOptimismMintableERC721(remote, "L2Token", "L2T"); } function test_createOptimismMintableERC721_zeroRemoteToken_reverts() external { // Try to create a token with a zero remote token address. vm.expectRevert("OptimismMintableERC721Factory: L1 token address cannot be address(0)"); - factory.createOptimismMintableERC721(address(0), "L2Token", "L2T"); + l2OptimismMintableERC721Factory.createOptimismMintableERC721(address(0), "L2Token", "L2T"); } function calculateTokenAddress( @@ -80,10 +71,13 @@ contract OptimismMintableERC721Factory_Test is Bridge_Initializer { view returns (address) { - bytes memory constructorArgs = abi.encode(address(l2ERC721Bridge), 1, _remote, _name, _symbol); + bytes memory constructorArgs = + abi.encode(address(l2ERC721Bridge), deploy.cfg().l1ChainID(), _remote, _name, _symbol); bytes memory bytecode = abi.encodePacked(type(OptimismMintableERC721).creationCode, constructorArgs); bytes32 salt = keccak256(abi.encode(_remote, _name, _symbol)); - bytes32 hash = keccak256(abi.encodePacked(bytes1(0xff), address(factory), salt, keccak256(bytecode))); + bytes32 hash = keccak256( + abi.encodePacked(bytes1(0xff), address(l2OptimismMintableERC721Factory), salt, keccak256(bytecode)) + ); return address(uint160(uint256(hash))); } } diff --git a/packages/contracts-bedrock/test/universal/Specs.t.sol b/packages/contracts-bedrock/test/universal/Specs.t.sol index b95604135eb0..5ffb38fd572e 100644 --- a/packages/contracts-bedrock/test/universal/Specs.t.sol +++ b/packages/contracts-bedrock/test/universal/Specs.t.sol @@ -6,7 +6,6 @@ import { CommonTest } from "test/setup/CommonTest.sol"; import { console2 as console } from "forge-std/console2.sol"; // Scripts -import { Executables } from "scripts/libraries/Executables.sol"; import { ForgeArtifacts, Abi, AbiEntry } from "scripts/libraries/ForgeArtifacts.sol"; // Contracts diff --git a/packages/contracts-bedrock/test/vendor/Initializable.t.sol b/packages/contracts-bedrock/test/vendor/Initializable.t.sol index 7b7596b9bafe..eaa0c420915a 100644 --- a/packages/contracts-bedrock/test/vendor/Initializable.t.sol +++ b/packages/contracts-bedrock/test/vendor/Initializable.t.sol @@ -12,7 +12,6 @@ import { Process } from "scripts/libraries/Process.sol"; // Libraries import { LibString } from "@solady/utils/LibString.sol"; import { Constants } from "src/libraries/Constants.sol"; -import { GameTypes } from "src/dispute/lib/Types.sol"; import "src/dispute/lib/Types.sol"; import "scripts/deploy/Deployer.sol";