Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,11 @@ See [this document](./op-e2e/README.md)
#### Running contract static analysis

We perform static analysis with [`slither`](https://github.com/crytic/slither).
You must have Python 3.x installed to run `slither`.
To run `slither` locally, do:
Slither is pinned in `mise.toml`. To run it locally, do:

```bash
cd packages/contracts-bedrock
pip3 install slither-analyzer
just slither
mise exec -- slither . --config-file test/slither/slither.config.json
```

## Labels
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ For example if geth is at `v1.12.0`, the corresponding op-geth version would be
Note that we pad out to three characters for the geth minor version and two characters for the geth patch version.
Since we cannot left-pad with zeroes, the geth major version is not padded.

See the [Node Software Releases](https://docs.optimism.io/builders/node-operators/releases) page of the documentation for more information about releases for the latest node components.
See the [GitHub releases](https://github.com/ethereum-optimism/optimism/releases) page for more information about releases for the latest node components.

The full set of components that have releases are:

Expand Down
12 changes: 6 additions & 6 deletions op-acceptance-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ This directory contains the OP Stack acceptance tests. They run against the in-p

The supported execution path is:

- `just` or `just acceptance-test-all`
- `gotestsum -- go test ./op-acceptance-tests/tests/...`
- `just` or `just acceptance-test`
- `gotestsum -- go test ./tests/...`

`devtest.T.MarkFlaky(...)` is used for tests that should downgrade failures to skips in the normal acceptance run. Set `DEVNET_FAIL_FLAKY_TESTS=true` to force those tests to fail normally. Acceptance runs also emit a `flaky-tests.txt` artifact in `op-acceptance-tests/logs/...` listing the current `MarkFlaky(...)` call sites.

Expand All @@ -32,21 +32,21 @@ just

# Explicit alias
just acceptance-test
just acceptance-test-all
```

### Direct CLI Usage

```bash
gotestsum --format testname --junitfile ./op-acceptance-tests/results/results.xml -- \
-count=1 -p 4 -parallel 4 -timeout 2h ./op-acceptance-tests/tests/...
mkdir -p results
gotestsum --format testname --junitfile ./results/results.xml -- \
-count=1 -p 4 -parallel 4 -timeout 30m ./tests/...
```

The `just` wrapper computes defaults from available CPUs:

- package jobs: CPU count
- in-package `t.Parallel`: half the CPU count
- timeout: `2h`
- timeout: `30m`

Override them with `ACCEPTANCE_TEST_JOBS`, `ACCEPTANCE_TEST_PARALLEL`, and `ACCEPTANCE_TEST_TIMEOUT`.

Expand Down
4 changes: 2 additions & 2 deletions op-chain-ops/cmd/ecotone-scalar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ Build and run using the `ecotone-scalar` target. Inside of `/op-chain-ops`, run:
```sh
just ecotone-scalar
```
to create a binary in [../../bin/ecotone-scalar](../../bin/ecotone-scalar) that can
be executed, providing the `--scalar` and `--blob-scalar` flags to specify the base bee scalar and
to create a binary in `./bin/ecotone-scalar` that can
be executed, providing the `--scalar` and `--blob-scalar` flags to specify the base fee scalar and
blob base fee parameters respectively, for example:

```sh
Expand Down
2 changes: 1 addition & 1 deletion op-node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Pull requests:

User docs:

- [How to run a node](https://docs.optimism.io/builders/node-operators/rollup-node)
- [How to run a node](https://docs.optimism.io/node-operators/tutorials/run-node-from-source)

Specs:

Expand Down
4 changes: 2 additions & 2 deletions op-program/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# op-program

> **Deprecated:** op-program is deprecated and being replaced by [kona-client](../../rust/kona/).
> **Deprecated:** op-program is deprecated and being replaced by [kona-client](../rust/kona/).
> Existing deployments will be supported until the Karst hardfork, at which point migration to kona-client is required.
> See the [end-of-support notice](https://docs.optimism.io/notices/op-geth-deprecation) for full details and migration guidance.

Expand Down Expand Up @@ -43,7 +43,7 @@ The absolute pre-state of the op-program can be generated by executing the
`reproducible-prestate` target. Effectively, this builds a docker image specified
by [Dockerfile.repro](./Dockerfile.repro) with pinned dependency versions to ensure the build is reproducible.

After running `just reproducible-prestate`, the generated prestates files can be found in [./bin/](./bin/).
After running `just reproducible-prestate`, the generated prestates files can be found in `./bin/`.

The `prestate-proof-*.json` files contain the absolute pre-state hash under the `.pre` key that is also used by the
[contracts][ctb] deploy script. The `prestate-*.bin.gz` files contain the actual prestate.
Expand Down
4 changes: 2 additions & 2 deletions op-proposer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Pull requests: [monorepo](https://github.com/ethereum-optimism/optimism/pulls?q=
User docs:
- [Proposer Configuration docs]

[Proposer Configuration docs]: https://docs.optimism.io/builders/chain-operators/configuration/proposer
[Proposer Configuration docs]: https://docs.optimism.io/chain-operators/guides/configuration/proposer

Specs:
- [`proposals.md`](https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/proposals.md)
Expand All @@ -31,7 +31,7 @@ with an inclusion-proof of a withdrawn message (as registered in the L2 withdraw
```bash
go run ./op-proposer/cmd \
--l1-eth-rpc http://l1:8545 \
--rollup-rpc: http://op-node:8545 \
--rollup-rpc http://op-node:8545 \
--game-factory-address=changeme \
--game-type=changeme
```
Expand Down
48 changes: 30 additions & 18 deletions op-supernode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,53 @@
Run multiple OP Stack chains in a single process. OP Supernode virtualizes OP Node so each chain runs as an isolated in-memory worker with per-chain config, data, and logs.

## Major Features

### Chain Containers
Chain Containers represent the concerns of one specific Chain being managed by the `op-supernode`

Chain Containers represent the concerns of one specific chain being managed by `op-supernode`.

#### Chain Isolation / Interfacing

Chain Containers abstract away the local Consensus Layer / Derivation Pipeline, as well as the Execution Engine.
Chain containers manage the runtime of the CL as a local process called a "Virtual Node", which presently is implemented
only by `op-node` itself.
Chain Containers provide a stable interface to get data from the chain or affect the chain without needing to operate on the internals of
that chain.
Chain Containers also allow for multiple chains to be derived inside of the same `op-supernode`. Because theya re isolated,
Chain Containers also allow for multiple chains to be derived inside of the same `op-supernode`. Because they are isolated,
running many chains worth of derivation is trivial.


#### Shared Chain Resources

Chain Containers also benefit from running in a shared environment through the use of shared resources.
Shared resources are Dependencies which have been injected into the Virtual Node such that the original behavior is in-tact,
Shared resources are dependencies injected into the Virtual Node such that the original behavior is intact,
but redundant access is eliminated.

- Shared L1 and Beacon Client mean shared caching and only a single pipe to the L1 across all chains.
- Shared RPCs through a namespaced RPC registration system. Call `11155420/` for OP Sepolia's RPC capabilities, or `84532/` for Base Sepolia.
- Metrics are shared through similar namespacing, but will likely be joined via prometheus dimensions in the future.
- Data Directories are namespaced to protect SafeDB and P2P resources
- Metrics are shared through similar namespacing, but will likely be joined via Prometheus dimensions in the future.
- Data directories are namespaced to protect SafeDB and P2P resources.
- Flag configuration can be shared amongst chains for common setup.

#### Safety labels
See [this document](./safety-labels.md)
#### Safety Labels

See [this document](./safety-labels.md).

#### Flag Configuration Tips

Because `op-node` is the only implementation of Virtual Nodes presently, it gets special treatment when the application starts up.
In specific, all those flags which are found in `op-node` are upstreamed with namespacing into the `op-supernode` flags.
This allows for *roughly* 1:1 setup and behavior between Node and Supernode, with cavets listed below.
Specifically, all flags found in `op-node` are upstreamed with namespacing into the `op-supernode` flags.
This allows for *roughly* 1:1 setup and behavior between Node and Supernode, with the caveats listed below.

- To set a value for one chain, use `--vn.<chainID>.<flag>`
- To set a value for *all* chains, use `--vn.all.<flag>`
- Some behaviors are expected to be configured at the `op-supernode` level and are not respected per usual when the application starts:
- Some behaviors are expected to be configured at the `op-supernode` level and are not respected the usual way when the application starts:
- `l1` and `l1.beacon` are used to create the shared L1 client. Any L1 configuration will not be respected by a Virtual Node.
- Log and Metric settings are passed down to the Virtual node from the top level Log/Metric flags, and individual chain settings may not be respected.
- `p2p` is enabled/disabled at the top level. While enabled, listen ports default to `0` (dynamic) to prevent collisions, but `--vn.all.p2p.listen.tcp` / `--vn.all.p2p.listen.udp` and the per-chain `--vn.<chainID>.p2p.listen.tcp` / `--vn.<chainID>.p2p.listen.udp` flags are honoured when set. The user is responsible for picking distinct ports across chains. Per-chain P2P functionality will be added via a shared resource in the future.

Example launch of Supernode:
```

```bash
./bin/op-supernode \
--l1='...' \
--l1.beacon='...' \
Expand All @@ -55,24 +61,28 @@ Example launch of Supernode:
--vn.11155420.network=op-sepolia \
--vn.11155420.l2='...' \
--vn.84532.network=base-sepolia \
--vn.84532.l2='...'
--vn.84532.l2='...' \
--vn.84532.l1.beacon-archiver='...' \
--vn.all.l2.jwt-secret=../../jwt-secret.txt \
```
--vn.all.l2.jwt-secret=../../jwt-secret.txt
```

Note: consult the `help` printout of the application as currently there is a mistake in the naming of Environment Variables for flags.
Env Vars may be used, but at present their names include inappropriate `op-node` markers.
Note: consult the `help` printout of the application as currently there is a mistake in the naming of environment variables for flags.
Environment variables may be used, but at present their names include inappropriate `op-node` markers.

### Activities

Activities represent the concerns of `op-supernode` which fall outside of any one chain, and are modular plugins to the capabilities of the software.

#### RPC Activities

Components which expose RPC functionality and register as an Activity will have their RPC namespaces registered against the `op-supernode` root.

#### Runnable Activities
Components which expose Start/Stop are given a goroutine to work during `op-supernode` runtime

Components which expose Start/Stop are given a goroutine to work during `op-supernode` runtime.

#### Current Activities:

- `Heartbeat`
- RPC: `heartbeat_check` produces a random-hex sign of life when called.
- Runtime: emits a simple heartbeat message to the logs to show liveness.
Expand All @@ -82,7 +92,9 @@ Components which expose Start/Stop are given a goroutine to work during `op-supe
- RPC: `supernode_syncStatus` returns aggregate per-chain sync status across the dependency set.

### Quickstart

Build:

```bash
just op-supernode
```
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,8 @@ contract BadStorageLayout {

All contracts should be assumed to live behind proxies (except in certain special circumstances).
This means that new contracts MUST be built under the assumption of upgradeability.
We use a minimal [`Proxy`](../src/universal/Proxy.sol) contract designed to be owned by a
corresponding [`ProxyAdmin`](../src/universal/ProxyAdmin.sol) which follow the interfaces
We use a minimal [`Proxy`](../../../src/universal/Proxy.sol) contract designed to be owned by a
corresponding [`ProxyAdmin`](../../../src/universal/ProxyAdmin.sol) which follow the interfaces
of OpenZeppelin's `Proxy` and `ProxyAdmin` contracts, respectively.

Unless explicitly discussed otherwise, you MUST include the following basic upgradeability
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ contract OPContractsManagerMigrationValidator {
address sharedASR = address(firstPortal.anchorStateRegistry());
IETHLockbox sharedLockbox = firstPortal.ethLockbox();
IDisputeGameFactory sharedDGF = IDisputeGameFactory(_chainSystemConfigs[0].disputeGameFactory());
address sharedWETH = _chainSystemConfigs[0].delayedWETH();

// Guard against missing lockbox — would revert on authorizedPortals call.
if (address(sharedLockbox) == address(0)) {
Expand Down Expand Up @@ -482,6 +483,10 @@ contract OPContractsManagerMigrationValidator {
string.concat("MIG-CHAIN-", idx, "-110"),
_errors
);

_errors = internalRequire(
_chainSystemConfigs[i].delayedWETH() == sharedWETH, string.concat("MIG-CHAIN-", idx, "-120"), _errors
);
}

return _errors;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ contract OPContractsManagerMigrator is OPContractsManagerUtilsCaller {

// Migrate each portal to the new ETHLockbox and AnchorStateRegistry.
for (uint256 i = 0; i < _input.chainSystemConfigs.length; i++) {
_updateSystemConfigDelayedWETH(_input.chainSystemConfigs[i], delayedWETH, impls.systemConfigImpl);
_migratePortal(_input.chainSystemConfigs[i], ethLockbox, anchorStateRegistry);
}
}
Expand All @@ -246,6 +247,61 @@ contract OPContractsManagerMigrator is OPContractsManagerUtilsCaller {
}
}

/// @notice Updates a chain's SystemConfig to point at the shared DelayedWETH while preserving
/// all other per-chain configuration values.
/// @param _systemConfig The system config for the chain being migrated.
/// @param _delayedWETH The shared DelayedWETH to store in the SystemConfig.
/// @param _systemConfigImpl The SystemConfig implementation to reinitialize with.
function _updateSystemConfigDelayedWETH(
ISystemConfig _systemConfig,
IDelayedWETH _delayedWETH,
address _systemConfigImpl
)
internal
{
ISystemConfig.Addresses memory addrs = _systemConfig.getAddresses();
addrs.delayedWETH = address(_delayedWETH);
addrs.opcm = _systemConfig.lastUsedOPCM();

_upgrade(
_systemConfig.proxyAdmin(),
address(_systemConfig),
_systemConfigImpl,
_makeSystemConfigInitArgs(_systemConfig, addrs)
);
}

/// @notice Builds SystemConfig initialize calldata from the chain's current values.
/// @dev Kept separate from _updateSystemConfigDelayedWETH to avoid stack-too-deep errors.
/// @param _systemConfig The system config to read existing values from.
/// @param _addrs The L1 contract address set to write.
/// @return Calldata for SystemConfig.initialize.
function _makeSystemConfigInitArgs(
ISystemConfig _systemConfig,
ISystemConfig.Addresses memory _addrs
)
internal
view
returns (bytes memory)
{
return abi.encodeCall(
ISystemConfig.initialize,
(
_systemConfig.owner(),
_systemConfig.basefeeScalar(),
_systemConfig.blobbasefeeScalar(),
_systemConfig.batcherHash(),
_systemConfig.gasLimit(),
_systemConfig.unsafeBlockSigner(),
_systemConfig.resourceConfig(),
_systemConfig.batchInbox(),
_addrs,
_systemConfig.l2ChainId(),
_systemConfig.superchainConfig()
)
);
}

/// @notice Migrates a single portal to the new ETHLockbox and AnchorStateRegistry.
/// @param _systemConfig The system config for the chain being migrated.
/// @param _newLockbox The new ETHLockbox.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,16 @@ contract OPContractsManagerMigrationValidator_PerChain_Test is OPContractsManage
);
assertEq("MIG-CHAIN-0-110", _validateMigration(true));
}

/// @notice MIG-CHAIN-1-120: Second chain's SystemConfig delayedWETH doesn't match shared WETH.
function test_validate_chain1120DelayedWethMismatch_succeeds() public {
vm.mockCall(
address(chainContracts2.systemConfig),
abi.encodeCall(ISystemConfig.delayedWETH, ()),
abi.encode(address(0xbadDE1a4ed))
);
assertEq("MIG-CHAIN-1-120", _validateMigration(true));
}
}

/// @title OPContractsManagerMigrationValidator_SharedDGF_Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { ForgeArtifacts, StorageSlot } from "scripts/libraries/ForgeArtifacts.so
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
import { Claim, Duration, Hash } from "src/dispute/lib/LibUDT.sol";
import { GameType, GameTypes, Proposal } from "src/dispute/lib/Types.sol";
import { LibGameArgs } from "src/dispute/lib/LibGameArgs.sol";
import { Constants } from "src/libraries/Constants.sol";
import { DevFeatures } from "src/libraries/DevFeatures.sol";
import { Features } from "src/libraries/Features.sol";
Expand Down Expand Up @@ -2320,6 +2321,12 @@ contract OPContractsManagerV2_Migrate_Test is OPContractsManagerV2_TestInit {
0.08 ether,
"SUPER_PERMISSIONED_CANNON init bond mismatch"
);
{
IDisputeGameFactory sharedDGF = IDisputeGameFactory(asr.disputeGameFactory());
address sharedWETH = LibGameArgs.decode(sharedDGF.gameArgs(GameTypes.SUPER_PERMISSIONED_CANNON)).weth;
assertEq(chainContracts1.systemConfig.delayedWETH(), sharedWETH, "Chain 1 delayedWETH mismatch");
assertEq(chainContracts2.systemConfig.delayedWETH(), sharedWETH, "Chain 2 delayedWETH mismatch");
}

// Check that portal liquidity was migrated directly to the new shared lockbox.
assertEq(address(portal1).balance, 0, "Portal 1 should have 0 balance after migration");
Expand Down
1 change: 1 addition & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ cfg-if = "1.0.4"
chrono = "0.4.43"
clap = "4.5.58"
color-eyre = "0.6.5"
crossbeam-channel = "0.5.13"
crossterm = "0.29.0"
dashmap = "6.1"
derive_more = { version = "2.1.1", default-features = false, features = [
Expand Down
Loading