Issues: monorepo
Pull requests: monorepo
User docs:
Specs:
The op-proposer
is a light-weight service to automate output-root proposal transactions on regular interval.
Each proposal transaction submits a claim of the L2 state to L1.
Chains with a pre-Fault-Proof deployment make proposal-transactions towards a pre-fault-proofs OptimismPortal
deployment.
Chains with permissioned or permissionless Fault Proofs make proposal-transactions to the DisputeGameFactory
,
which instantiates claims (each claim being a new fault-proof "game"),
which can then be resolved for the proposals to persist.
Withdrawals are authenticated against resolved proposals, with an inclusion-proof of a withdrawn message (as registered in the L2 withdrawal-contract storage).
go run ./op-proposer/cmd \
--l1-eth-rpc http://l1:8545 \
--rollup-rpc: http://op-node:8545 \
--game-factory-address=changeme \
--game-type=changeme
See Proposer Configuration docs for customization of the transaction-managent, and usage of a remote signer to isolate the proposer secret key.
On test networks, --allow-non-finalized
may be used to make proposals sooner, to reduce test time.
make op-proposer
./bin/op-proposer --help
# from op-proposer dir:
go run ./cmd --help
See op-proposer
docker-bake target.
The op-proposer relays subjective finalized
blocks (irreversible, as locally verified)
to L1 by constructing and submitting proposals.
The proposed claims can then be resolved, and used for withdrawals on L1.
sequenceDiagram
autonumber
participant portal as OptimismPortal (v2)<br/> contract
participant challenger as op-challenger
participant claim as Fault Dispute Game<br/> contract
participant dgf as Dispute Game Factory<br/> contract on L1
participant proposer as op-proposer
participant opnode as op-node
participant el as Execution Engine<br/> (e.g. op-geth)
proposer ->>opnode: query output-root
opnode ->>el: query block and withdrawals-root
el -->> opnode: return block and withdrawals-root
opnode -->> proposer: return output root
proposer ->> dgf: send claim
proposer ->> proposer: repeat with next claim
dgf ->> claim: create game contract
challenger ->> claim: resolve (or counter) claim
portal -->> claim: proveWithdrawalTransaction checks game state
The op-proposer
itself is a light-weight loop to maintain this relay:
schedule when to propose, inspect what to propose, transact on L1 to proposer, and repeat.
The op-proposer
code optimizes for simplicity.
Proposals are few and far-between, commonly only at a 1 hour interval. Proposal execution speed affects tests more than it does production, and thus not a primary optimization target.
Most costs are made in the proposal contract execution, not the operation of the op-proposer, and thus not the primary optimization concern.
Proposals are critical to safety however, and simplicity is thus important to this service.
The pre-fault-proof proposal functionality is effectively unused code, and may be removed in the near future. Solutions for alternative proving systems are a work in progress.
With the proposed withdrawals-root feature (see Isthmus upgrade feature), the op-node will soon no longer have to query the storage separately from the block-header that it constructs an output-root for. This lowers the requirements to run a proposer, since no archive-node is required anymore to determine the withdrawals-root.
Testing of this service may be further improved by decoupling the scheduling and processing. Better encapsulated processing would lend itself better to op-e2e action-tests.
- Reuse the transaction-management: this is the most complicated part of the op-proposer, but is common with other services.
- Keep the proposal flow simple: given that we only expect one transaction per hour, but the transaction is a critical claim, we have a strong preference for safety over liveness.
While disabled by default, the op-proposer is capable of submitting proposals too eagerly. A proposal for unfinalized L2 state that does not hold true later may result in an invalid claim on L1, and thus in dispute-game penalties.
Assuming finality, the op-proposer is only really subject to liveness failures:
- to L1 RPC failure (mitigated with redundancy in L1 RPC)
- local temporary failure, e.g. offline execution engine (mitigated with alerts) or odd tx-inclusion situations (mitigated with fresh state upon restart).
The op-proposer
integration is covered in system op-e2e
tests.