diff --git a/docs/public-docs/chain-operators/reference/batcher-configuration.mdx b/docs/public-docs/chain-operators/reference/batcher-configuration.mdx index 776dbc66c18..04dc3e76ad5 100644 --- a/docs/public-docs/chain-operators/reference/batcher-configuration.mdx +++ b/docs/public-docs/chain-operators/reference/batcher-configuration.mdx @@ -4,761 +4,63 @@ description: Reference for all op-batcher configuration options, covering CLI fl diataxis: reference --- +import OpBatcherFlags from '/snippets/generated/op-batcher-flags.mdx'; + This page catalogues every configuration option for the op-batcher, the service -that posts L2 sequencer data to L1 to make it available for verifiers. The -options are from the `--help` in [v1.10.0](https://github.com/ethereum-optimism/optimism/releases/tag/op-batcher%2Fv1.10.0). +that posts L2 sequencer data to L1 to make it available for verifiers. + +The flag tables below are generated directly from the op-batcher's flag +definitions in the monorepo (`op-batcher/flags`), and CI keeps them in sync +with the source: a flag change that is not reflected here fails the build, so +the tables cannot silently fall behind a release. Every flag can also be set +through the environment variable listed next to it. For guidance on choosing values — the batcher policy, cost tuning, multi-blob transactions, and sequencer throttling — see the [batcher configuration guide](/chain-operators/guides/configuration/batcher). -## Batch generation - -### batch-type - -The batch type. 0 for `SingularBatch` and 1 for `SpanBatch`. The default value -is `0` for `SingularBatch`. -See the [span batch feature page](/op-stack/features/span-batches) to learn more. - - - `--batch-type=` - `--batch-type=singular` - `OP_BATCHER_BATCH_TYPE=` - - -### max-blocks-per-span-batch - -Maximum number of blocks to add to a span batch. The default value is `0`, -meaning no maximum. - - - `--max-blocks-per-span-batch=` - `--max-blocks-per-span-batch=0` - `OP_BATCHER_MAX_BLOCKS_PER_SPAN_BATCH=0` - - -### compression-algo - -The compression algorithm to use. Valid options: zlib, brotli, brotli-9, -brotli-10, brotli-11. The default value is `zlib`. - - - `--compression-algo=` - `--compression-algo=zlib` - `OP_BATCHER_COMPRESSION_ALGO=zlib` - - -### compressor +## Flags -The type of compressor. Valid options: none, ratio, shadow. The default value -is `shadow`. + - - `--compressor=` - `--compressor=shadow` - `OP_BATCHER_COMPRESSOR=shadow` - - -### approx-compr-ratio +## Throttling -Only relevant for ratio compressor. The approximate compression ratio (`<=1.0`). The default value is `0.6`. +The `throttle.*` flags control how the batcher limits data availability (DA) +usage when a backlog builds up. When the amount of sequenced data that has not +yet been posted to L1 (the `unsafe_da_bytes` metric) exceeds +`--throttle.unsafe-da-bytes-lower-threshold`, the batcher instructs block +builders — over the `--l2-eth-rpc` endpoints, plus any endpoints listed in +`--throttle.additional-endpoints` — to limit transaction and block DA sizes, +scaling between the configured upper and lower size limits as the backlog +grows. - - `--approx-compr-ratio=` - `--approx-compr-ratio=0.6` - `OP_BATCHER_APPROX_COMPR_RATIO=0.6` - +`--throttle.controller-type` selects how throttling intensity ramps with the +backlog: `step`, `linear`, `quadratic` (the default), or the experimental +`pid` controller, which is tuned with the six `throttle.pid-*` flags. -### poll-interval +For the design of the throttling subsystem, including the PID controller, see +[`op-batcher/throttling.md`](https://github.com/ethereum-optimism/optimism/blob/develop/op-batcher/throttling.md) +in the monorepo. -How frequently to poll L2 for new blocks. The default value is `6s`. +## Notes on selected flags - - `--poll-interval=` - `--poll-interval=6s` - `OP_BATCHER_POLL_INTERVAL=6s` - +### batch-type -## Batch submission +Span batches (`--batch-type=1`) aggregate consecutive L2 blocks into a single +batch for better compression. See the +[span batch feature page](/op-stack/features/span-batches) to learn more. ### data-availability-type - Setting this flag to `auto` will allow the batcher to automatically switch between `calldata` and `blobs` based on the current L1 gas price. + Setting this flag to `auto` allows the batcher to automatically switch + between `calldata` and `blobs` based on the current L1 gas price. -The data availability type to use for submitting batches to the L1. Valid -options: `calldata`, `blobs`, and `auto`. The default value is `calldata`. - - - `--data-availability-type=` - `--data-availability-type=calldata` - `OP_BATCHER_DATA_AVAILABILITY_TYPE=calldata` - - -### target-num-frames - -The target number of frames to create per channel. Controls number of blobs per -blob tx, if using Blob DA. The default value is `1`. - - - `--target-num-frames=` - `--target-num-frames=1` - `OP_BATCHER_TARGET_NUM_FRAMES=1` - - -### max-channel-duration - -The maximum duration of L1-blocks to keep a channel open. 0 to disable. The -default value is `0`. - - - `--max-channel-duration=` - `--max-channel-duration=0` - `OP_BATCHER_MAX_CHANNEL_DURATION=0` - - -### sub-safety-margin - -The batcher tx submission safety margin (in #L1-blocks) to subtract from a -channel's timeout and sequencing window, to guarantee safe inclusion of a -channel on L1. The default value is `10`. - - - `--sub-safety-margin=` - `--sub-safety-margin=10` - `OP_BATCHER_SUB_SAFETY_MARGIN=10s` - - -### max-l1-tx-size-bytes - -The maximum size of a batch tx submitted to L1. Ignored for blobs, where max -blob size will be used. The default value is `120000`. - - - `--max-l1-tx-size-bytes=` - `--max-l1-tx-size-bytes=120000` - `OP_BATCHER_MAX_L1_TX_SIZE_BYTES=120000` - - -## Batcher startup - -### wait-node-sync - -Indicates if, during startup, the batcher should wait for a recent batcher tx -on L1 to finalize (via more block confirmations). This should help avoid -duplicate batcher txs. The default value is `false`. - - - `--wait-node-sync=` - `--wait-node-sync=false` - `OP_BATCHER_WAIT_NODE_SYNC=false` - - -### check-recent-txs-depth - -Indicates how many blocks back the batcher should look during startup for a -recent batch tx on L1. This can speed up waiting for node sync. It should be -set to the verifier confirmation depth of the sequencer (e.g. 4). The default -value is `0`. - - - `--check-recent-txs-depth=` - `--check-recent-txs-depth=0` - `OP_BATCHER_CHECK_RECENT_TXS_DEPTH=0` - - -### stopped - -Initialize the batcher in a stopped state. The batcher can be started using the -admin\_startBatcher RPC. The default value is `false`. - - - `--stopped=` - `--stopped=false` - `OP_BATCHER_STOPPED=false` - - -## Throttling - -The batcher supports throttling configuration to limit DA usage for transactions and blocks, and to control throttle intensity via several controller types. The following flags are available: - -### throttle.additional-endpoints -Comma-separated list of endpoints to distribute throttling configuration to (in addition to the L2 endpoints specified with `--l2-eth-rpc`). - - - `--throttle.additional-endpoints=,,...` - `--throttle.additional-endpoints=http://builder1:8545,http://builder2:8545` - `OP_BATCHER_THROTTLE_ADDITIONAL_ENDPOINTS=http://builder1:8545,http://builder2:8545` - - -### throttle.tx-size-lower-limit -The DA size limit for individual transactions when the throttle intensity is at its maximum. `0` disables limits; use `1` as the smallest effective limit. - - - `--throttle.tx-size-lower-limit=` - `--throttle.tx-size-lower-limit=150` - `OP_BATCHER_THROTTLE_TX_SIZE_LOWER_LIMIT=150` - - -### throttle.tx-size-upper-limit -The DA size limit for individual transactions as throttle intensity approaches `0` (minimal throttling). Not applied when throttling is inactive. - - - `--throttle.tx-size-upper-limit=` - `--throttle.tx-size-upper-limit=20000` - `OP_BATCHER_THROTTLE_TX_SIZE_UPPER_LIMIT=20000` - - -### throttle.block-size-lower-limit -The DA size limit for blocks when throttle intensity is at maximum (applies for linear and quadratic controllers). `0` disables limits; use `1` as the smallest effective limit. - - - `--throttle.block-size-lower-limit=` - `--throttle.block-size-lower-limit=2000` - `OP_BATCHER_THROTTLE_BLOCK_SIZE_LOWER_LIMIT=2000` - - -### throttle.block-size-upper-limit -The DA size limit for blocks when throttling is inactive (throttle intensity = 0). - - - `--throttle.block-size-upper-limit=` - `--throttle.block-size-upper-limit=130000` - `OP_BATCHER_THROTTLE_BLOCK_SIZE_UPPER_LIMIT=130000` - - -### throttle.controller-type -Type of throttle controller to use. Valid values: `step`, `linear`, or `quadratic` (default). - - - `--throttle.controller-type=` - `--throttle.controller-type=quadratic` - `OP_BATCHER_THROTTLE_CONTROLLER_TYPE=quadratic` - - -### throttle.unsafe-da-bytes-lower-threshold -Threshold on `unsafe_da_bytes` beyond which the batcher will start to throttle the block builder. `0` disables throttling. - - - `--throttle.unsafe-da-bytes-lower-threshold=` - `--throttle.unsafe-da-bytes-lower-threshold=3200000` - `OP_BATCHER_THROTTLE_UNSAFE_DA_BYTES_LOWER_THRESHOLD=3200000` - - -### throttle.unsafe-da-bytes-upper-threshold -Threshold on `unsafe_da_bytes` at which throttling reaches maximum intensity (applies for linear and quadratic controllers). - - - `--throttle.unsafe-da-bytes-upper-threshold=` - `--throttle.unsafe-da-bytes-upper-threshold=12800000` - `OP_BATCHER_THROTTLE_UNSAFE_DA_BYTES_UPPER_THRESHOLD=12800000` - - -## Transaction manager - -### num-confirmations - -Number of confirmations which we will wait after sending a transaction. The -default value is `10`. - - - `--num-confirmations=` - `--num-confirmations=10` - `OP_BATCHER_NUM_CONFIRMATIONS=10` - - -### max-pending-tx - -The maximum number of pending transactions. 0 for no limit. The default value -is `1`. - - - `--max-pending-tx=` - `--max-pending-tx=1` - `OP_BATCHER_MAX_PENDING_TX=1` - - -### resubmission-timeout - -Duration we will wait before resubmitting a transaction to L1. The default -value is `48s`. - - - `--resubmission-timeout=` - `--resubmission-timeout=48s` - `OP_BATCHER_RESUBMISSION_TIMEOUT=48s` - - -### safe-abort-nonce-too-low-count - -Number of ErrNonceTooLow observations required to give up on a tx at a -particular nonce without receiving confirmation. The default value is `3`. - - - `--safe-abort-nonce-too-low-count=` - `--safe-abort-nonce-too-low-count=3` - `OP_BATCHER_SAFE_ABORT_NONCE_TOO_LOW_COUNT=3` - - -### txmgr.min-basefee - -Enforces a minimum base fee (in GWei) to assume when determining tx fees. 1 -GWei by default. The default value is `1`. - - - `--txmgr.min-basefee=` - `--txmgr.min-basefee=1` - `OP_BATCHER_TXMGR_MIN_BASEFEE=1` - - -### txmgr.min-tip-cap - -Enforces a minimum tip cap (in GWei) to use when determining tx fees. 1 GWei by -default. The default value is `1`. - - - `--txmgr.min-tip-cap=` - `--txmgr.min-tip-cap=1` - `OP_BATCHER_TXMGR_MIN_TIP_CAP=1` - - -### fee-limit-multiplier - -The multiplier applied to fee suggestions to put a hard limit on fee increases. -The default value is `5`. - - - `--fee-limit-multiplier=` - `--fee-limit-multiplier=5` - `OP_BATCHER_TXMGR_FEE_LIMIT_MULTIPLIER=5` - - -### txmgr.fee-limit-threshold - -The minimum threshold (in GWei) at which fee bumping starts to be capped. -Allows arbitrary fee bumps below this threshold. The default value is `100`. - - - `--txmgr.fee-limit-threshold=` - `--txmgr.fee-limit-threshold=100` - `OP_BATCHER_TXMGR_FEE_LIMIT_THRESHOLD=100` - - -### txmgr.receipt-query-interval - -Frequency to poll for receipts. The default value is `12s`. - - - `--txmgr.receipt-query-interval=` - `--txmgr.receipt-query-interval=12s` - `OP_BATCHER_TXMGR_RECEIPT_QUERY_INTERVAL=12s` - - -### txmgr.not-in-mempool-timeout - -Timeout for aborting a tx send if the tx does not make it to the mempool. The -default value is `2m0s`. - - - `--txmgr.not-in-mempool-timeout=` - `--txmgr.not-in-mempool-timeout=2m0s` - `OP_BATCHER_TXMGR_TX_NOT_IN_MEMPOOL_TIMEOUT=2m0s` - - -### txmgr.send-timeout - -Timeout for sending transactions. If 0 it is disabled. The default value is -`0s`. - - - `--txmgr.send-timeout=` - `--txmgr.send-timeout=0s` - `OP_BATCHER_TXMGR_TX_SEND_TIMEOUT=0s` - - -## Authentication and wallet - -### private-key - -The private key to use with the service. Must not be used with mnemonic. - - - `--private-key=` - `--private-key=` - `OP_BATCHER_PRIVATE_KEY=` - - -### mnemonic - -The mnemonic used to derive the wallets for either the service. - - - `--mnemonic=` - `--mnemonic=` - `OP_BATCHER_MNEMONIC=` - - -### hd-path - -The HD path used to derive the sequencer wallet from the mnemonic. The mnemonic -flag must also be set. - - - `--hd-path=` - `--hd-path=` - `OP_BATCHER_HD_PATH=` - - +### altda.* -### signer.address - -Address the signer is signing transactions for. - - - `--signer.address=` - `--signer.address=` - `OP_BATCHER_SIGNER_ADDRESS=` - - -### signer.endpoint - -Signer endpoint the client will connect to. - - - `--signer.endpoint=` - `--signer.endpoint=` - `OP_BATCHER_SIGNER_ENDPOINT=` - - -### signer.header - -Headers to pass to the remote signer. Format `key=value`.\ -Value can contain any character allowed in an HTTP header.\ -When using env vars, split multiple headers with commas.\ -When using flags, provide one key-value pair per flag. - - - `--signer.header=` - `--signer.header="Authorization=Bearer 123abc"` - `OP_BATCHER_SIGNER_HEADER=Authorization=Bearer 123abc` - - -### signer.tls.ca - -tls ca cert path. The default value is `tls/ca.crt`. - - - `--signer.tls.ca=` - `--signer.tls.ca=tls/ca.crt` - `OP_BATCHER_SIGNER_TLS_CA=tls/ca.crt` - - -### signer.tls.cert - -tls cert path. The default value is `tls/tls.crt`. - - - `--signer.tls.cert=` - `--signer.tls.cert=tls/tls.crt` - `OP_BATCHER_SIGNER_TLS_CERT=` - - -### signer.tls.key - -tls key. The default value is `tls/tls.key`. - - - `--signer.tls.key=` - `--signer.tls.key=tls/tls.key` - `OP_BATCHER_SIGNER_TLS_KEY=` - - -## Network connections - -### l1-eth-rpc - -HTTP provider URL for L1. - - - `--l1-eth-rpc=` - `--l1-eth-rpc` - `OP_BATCHER_L1_ETH_RPC=` - - -### l2-eth-rpc - -HTTP provider URL for L2 execution engine. A comma-separated list enables the -active L2 endpoint provider. Such a list needs to match the number of -rollup-rpcs provided. - - - `--l2-eth-rpc=` - `--l2-eth-rpc=` - `OP_BATCHER_L2_ETH_RPC=` - - -### rollup-rpc - -HTTP provider URL for Rollup node. A comma-separated list enables the active L2 -endpoint provider. Such a list needs to match the number of l2-eth-rpcs -provided. - - - `--rollup-rpc=` - `--rollup-rpc=` - `OP_BATCHER_ROLLUP_RPC=` - - -### rpc.addr - -rpc listening address. The default value is `0.0.0.0`. - - - `--rpc.addr=` - `--rpc.addr=0.0.0.0` - `OP_BATCHER_RPC_ADDR=0.0.0.0` - - -### rpc.enable-admin - -Enable the admin API. The default value is `false`. - - - `--rpc.enable-admin=` - `--rpc.enable-admin=false` - `OP_BATCHER_RPC_ENABLE_ADMIN=false` - - -### rpc.port - -rpc listening port. The default value is `8545`. - - - `--rpc.port=` - `--rpc.port=8545` - `OP_BATCHER_RPC_PORT=8545` - - -### network-timeout - -Timeout for all network operations. The default value is `10s`. - - - `--network-timeout=` - `--network-timeout=10s` - `OP_BATCHER_NETWORK_TIMEOUT=10s` - - -## Alt-DA mode (Beta feature) - -### altda.enabled - -Enable Alt-DA mode, Alt-DA mode is a Beta feature of the OP Stack. +The `altda.*` flags configure Alt-DA mode, a Beta feature of the OP Stack. While it has received initial review from core contributors, it is still -undergoing testing, and may have bugs or other issues. -The default value is `false`. - - - `--altda.enabled=` - `--altda.enabled=false` - `OP_BATCHER_ALTDA_ENABLED=false` - - -### altda.da-server - -HTTP address of a DA Server. - - - `--altda.da-server=` - `--altda.da-server=http://da.example.com:1234` - `OP_BATCHER_ALTDA_DA_SERVER=http://da.example.com:1234` - - -### altda.da-service - -Use DA service type where commitments are generated by Alt-DA server. The default -value is `false`. - - - `--altda.da-service=` - `--altda.da-service=true` - `OP_BATCHER_ALTDA_DA_SERVER=true` - - -### altda.get-timeout - -Timeout for get requests. **0 means no timeout**. - - - `--altda.get-timeout=` - `--altda.get-timeout=5s` - `OP_BATCHER_ALTDA_GET_TIMEOUT=5s` - - -### altda.put-timeout - -Timeout for put requests. **0 means no timeout**. - - - `--altda.put-timeout=` - `--altda.put-timeout=10s` - `OP_BATCHER_ALTDA_PUT_TIMEOUT=10s` - - -### altda.max-concurrent-da-requests - -Maximum number of concurrent requests to the DA server. - - - `--altda.max-concurrent-da-requests=` - `--altda.max-concurrent-da-requests=4` - `OP_BATCHER_ALTDA_MAX_CONCURRENT_DA_REQUESTS=4` - - -### altda.verify-on-read - -Verify input data matches the commitments from the DA storage service. - - - `--altda.verify-on-read=` - `--altda.verify-on-read=true` - `OP_BATCHER_ALTDA_VERIFY_ON_READ=true` - - -## Logging and monitoring - -### log.level - -The lowest log level that will be output. The default value is `INFO`. - - - `--log.level=` - `--log.level=INFO` - `OP_BATCHER_LOG_LEVEL=INFO` - - -### log.format - -Format the log output. Supported formats: 'text', 'terminal', 'logfmt', 'json', -'json-pretty'. The default value is `text`. - - - `--log.format=` - `--log.format=text` - `OP_BATCHER_LOG_FORMAT=text` - - -### log.color - -Color the log output if in terminal mode. The default value is `false`. - - - `--log.color=` - `--log.color=false` - `OP_BATCHER_LOG_COLOR=false` - - -### log.pid - -Show PID in the log. - - - `--log.pid=` - `--log.pid=true` - `OP_BATCHER_LOG_PID=true` - - -### metrics.enabled - -Enable the metrics server. The default value is `false`. - - - `--metrics.enabled=` - `--metrics.enabled=false` - `OP_BATCHER_METRICS_ENABLED=false` - - -## Miscellaneous - -### active-sequencer-check-duration - -The duration between checks to determine the active sequencer endpoint. The -default value is `2m0s`. - - - `--active-sequencer-check-duration=` - `--active-sequencer-check-duration=2m0s` - `OP_BATCHER_ACTIVE_SEQUENCER_CHECK_DURATION=2m0s` - - -### pprof.addr - -pprof listening address. The default value is `0.0.0.0`. - - - `--pprof.addr=` - `--pprof.addr=0.0.0.0` - `OP_BATCHER_PPROF_ADDR=0.0.0.0` - - -### pprof.enabled - -Enable the pprof server. The default value is `false`. - - - `--pprof.enabled=` - `--pprof.enabled=false` - `OP_BATCHER_PPROF_ENABLED=false` - - -### pprof.path - -pprof file path. If it is a directory, the path is `{dir}/{profileType}.prof`. - - - `--pprof.path=` - `--pprof.path=` - `OP_BATCHER_PPROF_PATH=` - - -### pprof.port - -pprof listening port. The default value is `6060`. - - - `--pprof.port=` - `--pprof.port=6060` - `OP_BATCHER_PPROF_PORT=6060` - - -### pprof.type - -pprof profile type. One of cpu, heap, goroutine, threadcreate, block, mutex, -allocs. - - - `--pprof.type=` - `--pprof.type` - `OP_BATCHER_PPROF_TYPE=` - - -### help - -Show help. The default value is false. - - - `--help=` - `--help=false` - `OP_BATCHER_HELP=false` - - -### version - -Print the version. The default value is false. - - - `--version=` - `--version=false` - `OP_BATCHER_VERSION=false` - +undergoing testing, and may have bugs or other issues. See the +[Alt-DA mode guide](/chain-operators/guides/features/alt-da-mode-guide) for +setup instructions. diff --git a/docs/public-docs/scripts/gen-flags/README.md b/docs/public-docs/scripts/gen-flags/README.md new file mode 100644 index 00000000000..fe6818a3fb7 --- /dev/null +++ b/docs/public-docs/scripts/gen-flags/README.md @@ -0,0 +1,107 @@ +# gen-flags — generated flag references for docs.optimism.io + +Generates the MDX flag-reference tables under `docs/public-docs/snippets/generated/` +from the urfave/cli flag definitions the OP Stack Go services actually register. +The docs pages import these snippets instead of hand-transcribing `--help` +output, so the published flag catalogs cannot silently fall behind a release. + +## Usage + +Run from the monorepo root: + +```bash +go run ./docs/public-docs/scripts/gen-flags +``` + +To verify the committed snippets match what the current source tree generates +without rewriting them (exits nonzero on any difference): + +```bash +go run ./docs/public-docs/scripts/gen-flags -check +``` + +The monorepo Go build embeds `op-core/superchain/superchain-configs.zip` +(gitignored). On a fresh checkout, build it first: + +```bash +just build-superchain-go +``` + +## How it works + +- `main.go` imports each component's composed flag slice (for op-batcher, + `op-batcher/flags.Flags` — including the op-service flag families appended in + its `init()`: rpc, log, metrics, pprof, txmgr, altda) and renders one snippet + per component: `snippets/generated/-flags.mdx`. +- Flag name, usage, default, and environment variable come from urfave/cli's + own `DocGenerationFlag` accessors, so the output matches `--help` semantics. + Hidden flags are skipped. +- `manifest.json` records the finalized release tag each snippet was generated + at (e.g. `op-batcher/v1.16.11`), and the snippet's provenance line names the + same tag. The two are updated together, only on regeneration. + +## Regenerating for a new release + +The snippets document *released* software, so regeneration is keyed to +finalized release tags — not to every change on `develop`. When a new +finalized (non-rc, non-pre-release) `op-batcher/v*` tag is published: + +1. Check out that tag — or, if working from another commit, verify the + flag-defining packages are identical to the tag first: + `op-batcher/flags/` and the flag families it appends (`op-service/rpc`, + `op-service/log`, `op-service/metrics`, `op-service/oppprof`, + `op-service/txmgr`, `op-alt-da`), e.g. with + `git diff HEAD -- `. +2. Update the component's `tag` in `manifest.json` to the new release tag. +3. Run the generator; the snippet and its provenance line are rewritten + together. Commit the manifest and snippet in the same change. + +Never hand-edit the generated snippets (`-check` fails on any hand edit), and +never regenerate from unreleased code: if the flags changed since the manifest +tag, the regenerated table would document behavior no released binary has. + +Enforcement runs as a review-gated Mintlify docs automation on a weekly +schedule: it compares the newest finalized `op-batcher/v*` tag against the +tag in `manifest.json` and, when a newer release exists, regenerates per the +steps above and proposes the change for human review. Local runs of the +generator (`-check` for verification) cover the gap between scheduled runs. + +## Adding a component + +1. Add the component's flag slice to the `components` table in `main.go`, + mirroring its required-flag names (the components keep their required + slices unexported; a runtime sanity check catches renames). +2. Add its latest finalized release tag to `manifest.json`. +3. Run the generator and import the new snippet from the component's + reference page. +4. Extend the docs automation prompt to watch the new component's release + tag pattern. + +## Ownership + +Everything in this pipeline lives under `docs/public-docs/`, so it is covered +by the existing CODEOWNERS rule +(`/docs/public-docs/ @ethereum-optimism/solutions`) — no dedicated entries +are needed. Per the ownership model in the Solutions repo's +`projects/docs-improver/plans/option-b-truth-from-source.md`: + +| Artifact | Author of record | Reviewer | Stale-reference triage | +| --- | --- | --- | --- | +| Generator code + docs automation (this directory, the Mintlify automation config) | Matthew Cruz (@sbvegan), docs owner — proposed, pending confirmation | @ethereum-optimism/solutions (via the `/docs/public-docs/` CODEOWNERS rule) | Author of record | +| Generated snippets (`snippets/generated/`) | The pipeline — nobody hand-edits; `-check` fails on hand edits by construction | @ethereum-optimism/solutions review the automation's regeneration PRs | A snippet that can't be regenerated cleanly is filed as an `accuracy`-labelled issue on the Solutions board | +| Flag facts (`op-batcher/flags/`, op-service flag families) | Component engineers | Component team | Component team; the docs table follows at the next finalized release | + +Known residual gaps (accepted, by design): + +- The table documents the manifest release tag, not `develop`. Flag changes + merged after a release are intentionally not reflected until the next + finalized tag is published and the automation (or a maintainer) regenerates. +- The required-flag list is mirrored in `main.go` because the components do + not export it. A rename fails the generator's sanity check; adding a brand + new required flag without updating the mirror would list it as optional. +- op-batcher's `--compressor` option list (`compressor.KindKeys`) is built + from map iteration, so its order changes on every process start — in + `op-batcher --help` itself, not just here. The generator sorts that one + list (`canonicalizeUsage` in `main.go`) so output is deterministic; the + proper fix is sorting `KindKeys` at the source (one line in + `op-batcher/compressor/compressors.go`), proposed as a follow-up. diff --git a/docs/public-docs/scripts/gen-flags/main.go b/docs/public-docs/scripts/gen-flags/main.go new file mode 100644 index 00000000000..eba79276e58 --- /dev/null +++ b/docs/public-docs/scripts/gen-flags/main.go @@ -0,0 +1,285 @@ +// Command gen-flags generates MDX flag-reference tables for OP Stack Go +// services from their urfave/cli flag definitions, so the docs flag catalogs +// are derived from source instead of hand-transcribed from `--help` output. +// +// For each component listed in components below, the tool walks the composed +// flag slice the binary actually registers (including the flag families +// appended from op-service: rpc, log, metrics, pprof, txmgr, altda) and emits +// a snippet into docs/public-docs/snippets/generated/. The snippet carries a +// do-not-edit header and a provenance line naming the release tag recorded in +// manifest.json. +// +// Run from the monorepo root: +// +// go run ./docs/public-docs/scripts/gen-flags +// +// Regeneration is keyed to finalized component releases: the snippets are +// generated from the source at the release tag recorded in manifest.json and +// refreshed when a new finalized (non-rc) tag is published — see README.md in +// this directory for the procedure. Pass -check to verify the committed +// snippets match what the current source tree generates without rewriting +// them. +package main + +import ( + "encoding/json" + "flag" + "fmt" + "os" + "path/filepath" + "sort" + "strings" + + "github.com/urfave/cli/v2" + + batcherflags "github.com/ethereum-optimism/optimism/op-batcher/flags" +) + +// component describes one service whose flags are rendered into a snippet. +type component struct { + // name is the service name, e.g. "op-batcher". The snippet is written to + // /generated/-flags.mdx and the release tag is looked + // up under this key in manifest.json. + name string + // flags is the composed flag slice the binary registers. + flags []cli.Flag + // required lists the flag names the service's CheckRequired enforces. + // urfave/cli does not expose this (the components keep their required + // slices unexported), so it is mirrored here; a sanity check below + // verifies every listed name exists in the flag slice. + required []string +} + +var components = []component{ + { + name: "op-batcher", + flags: batcherflags.Flags, + // Mirrors requiredFlags in op-batcher/flags/flags.go. + required: []string{"l1-eth-rpc", "l2-eth-rpc", "rollup-rpc"}, + }, +} + +// manifest maps component name -> finalized release tag recorded in the +// provenance line, e.g. "op-batcher" -> "op-batcher/v1.16.11". The tag is +// bumped, and the snippet regenerated, when a new finalized (non-rc) +// component release is published. +type manifest map[string]struct { + Tag string `json:"tag"` +} + +type row struct { + name string + usage string + defaultText string + envVar string +} + +func main() { + docsDir := flag.String("docs-dir", "docs/public-docs", "path to the docs root (run from the monorepo root)") + check := flag.Bool("check", false, "compare committed snippets against generated output instead of writing; exit nonzero on any difference") + flag.Parse() + + docsRoot, err := filepath.Abs(filepath.Clean(*docsDir)) + if err != nil { + fatalf("resolving docs dir %s: %v", *docsDir, err) + } + + manifestPath, err := pathUnder(docsRoot, "scripts", "gen-flags", "manifest.json") + if err != nil { + fatalf("%v", err) + } + raw, err := os.ReadFile(manifestPath) + if err != nil { + fatalf("reading %s (run from the monorepo root): %v", manifestPath, err) + } + var m manifest + if err := json.Unmarshal(raw, &m); err != nil { + fatalf("parsing %s: %v", manifestPath, err) + } + + outDir, err := pathUnder(docsRoot, "snippets", "generated") + if err != nil { + fatalf("%v", err) + } + if err := os.MkdirAll(outDir, 0o750); err != nil { + fatalf("creating %s: %v", outDir, err) + } + + for _, c := range components { + entry, ok := m[c.name] + if !ok || entry.Tag == "" { + fatalf("no release tag for %q in %s", c.name, manifestPath) + } + outPath, err := pathUnder(docsRoot, "snippets", "generated", c.name+"-flags.mdx") + if err != nil { + fatalf("%v", err) + } + content, err := render(c, entry.Tag) + if err != nil { + fatalf("rendering %s: %v", c.name, err) + } + if *check { + committed, err := os.ReadFile(outPath) + if err != nil { + fatalf("reading committed snippet %s: %v", outPath, err) + } + if string(committed) != content { + fatalf("%s does not match generated output for %s (tag %s); regenerate per README.md", outPath, c.name, entry.Tag) + } + fmt.Printf("ok: %s matches generated output (%d flags, %s)\n", outPath, len(c.flags), entry.Tag) + continue + } + if err := os.WriteFile(outPath, []byte(content), 0o640); err != nil { + fatalf("writing %s: %v", outPath, err) + } + fmt.Printf("wrote %s (%d flags)\n", outPath, len(c.flags)) + } +} + +func render(c component, tag string) (string, error) { + requiredSet := make(map[string]bool, len(c.required)) + for _, name := range c.required { + requiredSet[name] = true + } + + var required, optional []row + seen := make(map[string]bool) + for _, f := range c.flags { + if vf, ok := f.(cli.VisibleFlag); ok && !vf.IsVisible() { + continue + } + df, ok := f.(cli.DocGenerationFlag) + if !ok { + return "", fmt.Errorf("flag %v does not implement cli.DocGenerationFlag", f.Names()) + } + name := f.Names()[0] + if seen[name] { + return "", fmt.Errorf("duplicate flag name %q", name) + } + seen[name] = true + r := row{ + name: name, + usage: canonicalizeUsage(c.name, name, df.GetUsage()), + defaultText: df.GetDefaultText(), + } + if envVars := df.GetEnvVars(); len(envVars) > 0 { + r.envVar = envVars[0] + } + if requiredSet[name] { + required = append(required, r) + } else { + optional = append(optional, r) + } + } + + // Sanity check: every declared required flag must exist in the slice, so + // a rename in the component surfaces here instead of drifting silently. + for _, name := range c.required { + if !seen[name] { + return "", fmt.Errorf("required flag %q not found in %s flag definitions", name, c.name) + } + } + + sort.Slice(required, func(i, j int) bool { return required[i].name < required[j].name }) + sort.Slice(optional, func(i, j int) bool { return optional[i].name < optional[j].name }) + + var b strings.Builder + fmt.Fprintf(&b, `{/* + GENERATED FILE — DO NOT EDIT. + + Generated by docs/public-docs/scripts/gen-flags from the %[1]s urfave/cli + flag definitions at the release tag below. Do not hand-edit; regenerate + per docs/public-docs/scripts/gen-flags/README.md when a new finalized + %[1]s release is published: + + go run ./docs/public-docs/scripts/gen-flags +*/} + +Generated from [`+"`%[2]s`"+`](https://github.com/ethereum-optimism/optimism/releases/tag/%[3]s) +flag definitions. %[4]d flags: %[5]d required, %[6]d optional. + +`, c.name, tag, strings.ReplaceAll(tag, "/", "%2F"), len(required)+len(optional), len(required), len(optional)) + + b.WriteString("### Required flags\n\n") + b.WriteString("| Flag | Description | Environment variable |\n") + b.WriteString("| --- | --- | --- |\n") + for _, r := range required { + fmt.Fprintf(&b, "| `--%s` | %s | %s |\n", r.name, cell(r.usage), envCell(r.envVar)) + } + + b.WriteString("\n### Optional flags\n\n") + b.WriteString("| Flag | Description | Default | Environment variable |\n") + b.WriteString("| --- | --- | --- | --- |\n") + for _, r := range optional { + fmt.Fprintf(&b, "| `--%s` | %s | %s | %s |\n", r.name, cell(r.usage), defaultCell(r.defaultText), envCell(r.envVar)) + } + + return b.String(), nil +} + +// canonicalizeUsage makes usage strings that are nondeterministic at the +// source stable across runs, so regeneration is byte-stable. op-batcher +// builds the --compressor option list from map iteration +// (op-batcher/compressor.KindKeys via slices.Collect(maps.Keys(...))), so its +// order changes on every process start — including in `op-batcher --help` +// itself. Sort that one list here. Remove this once KindKeys is sorted +// upstream (proposed as a follow-up to the B1 slice). +func canonicalizeUsage(component, flagName, usage string) string { + if component == "op-batcher" && flagName == "compressor" { + const marker = "Valid options: " + if i := strings.Index(usage, marker); i >= 0 { + head, list := usage[:i+len(marker)], usage[i+len(marker):] + options := strings.Split(list, ", ") + sort.Strings(options) + return head + strings.Join(options, ", ") + } + } + return usage +} + +// cell escapes a usage string for use inside an MDX table cell: newlines +// become spaces, and characters MDX would treat as JSX or expression syntax +// ({, }, <) or as a column separator (|) are escaped. +func cell(s string) string { + s = strings.Join(strings.Fields(s), " ") + replacer := strings.NewReplacer( + "|", "\\|", + "{", "\\{", + "}", "\\}", + "<", "\\<", + ) + return replacer.Replace(s) +} + +func defaultCell(s string) string { + if s == "" { + return "—" + } + return "`" + strings.ReplaceAll(s, "|", "\\|") + "`" +} + +func envCell(s string) string { + if s == "" { + return "—" + } + return "`" + s + "`" +} + +// pathUnder joins elems onto root, cleans the result, and verifies the +// resolved path still lies under root. Every path this tool reads or writes +// is built from in-repo constants (component names from the components table, +// manifest.json), not user input, but the check keeps a future bad component +// name or docs-dir value from escaping the docs tree. +func pathUnder(root string, elems ...string) (string, error) { + p := filepath.Clean(filepath.Join(append([]string{root}, elems...)...)) + rel, err := filepath.Rel(root, p) + if err != nil || rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) { + return "", fmt.Errorf("path %s escapes docs dir %s", p, root) + } + return p, nil +} + +func fatalf(format string, args ...any) { + fmt.Fprintf(os.Stderr, "gen-flags: "+format+"\n", args...) + os.Exit(1) +} diff --git a/docs/public-docs/scripts/gen-flags/manifest.json b/docs/public-docs/scripts/gen-flags/manifest.json new file mode 100644 index 00000000000..2a8eeb8c351 --- /dev/null +++ b/docs/public-docs/scripts/gen-flags/manifest.json @@ -0,0 +1,5 @@ +{ + "op-batcher": { + "tag": "op-batcher/v1.16.11" + } +} diff --git a/docs/public-docs/snippets/generated/op-batcher-flags.mdx b/docs/public-docs/snippets/generated/op-batcher-flags.mdx new file mode 100644 index 00000000000..c76b497d9ec --- /dev/null +++ b/docs/public-docs/snippets/generated/op-batcher-flags.mdx @@ -0,0 +1,110 @@ +{/* + GENERATED FILE — DO NOT EDIT. + + Generated by docs/public-docs/scripts/gen-flags from the op-batcher urfave/cli + flag definitions at the release tag below. Do not hand-edit; regenerate + per docs/public-docs/scripts/gen-flags/README.md when a new finalized + op-batcher release is published: + + go run ./docs/public-docs/scripts/gen-flags +*/} + +Generated from [`op-batcher/v1.16.11`](https://github.com/ethereum-optimism/optimism/releases/tag/op-batcher%2Fv1.16.11) +flag definitions. 87 flags: 3 required, 84 optional. + +### Required flags + +| Flag | Description | Environment variable | +| --- | --- | --- | +| `--l1-eth-rpc` | HTTP provider URL for L1 | `OP_BATCHER_L1_ETH_RPC` | +| `--l2-eth-rpc` | HTTP provider URL for L2 execution engine. A comma-separated list enables the active L2 endpoint provider. Such a list needs to match the number of rollup-rpcs provided. | `OP_BATCHER_L2_ETH_RPC` | +| `--rollup-rpc` | HTTP provider URL for Rollup node. A comma-separated list enables the active L2 endpoint provider. Such a list needs to match the number of l2-eth-rpcs provided. | `OP_BATCHER_ROLLUP_RPC` | + +### Optional flags + +| Flag | Description | Default | Environment variable | +| --- | --- | --- | --- | +| `--active-sequencer-check-duration` | The duration between checks to determine the active sequencer endpoint. | `5s` | `OP_BATCHER_ACTIVE_SEQUENCER_CHECK_DURATION` | +| `--altda.da-server` | HTTP address of a DA Server | — | `OP_BATCHER_ALTDA_DA_SERVER` | +| `--altda.da-service` | Use DA service type where commitments are generated by Alt-DA server | `false` | `OP_BATCHER_ALTDA_DA_SERVICE` | +| `--altda.enabled` | Enable Alt-DA mode Alt-DA Mode is a Beta feature of the MIT licensed OP Stack. While it has received initial review from core contributors, it is still undergoing testing, and may have bugs or other issues. | `false` | `OP_BATCHER_ALTDA_ENABLED` | +| `--altda.get-timeout` | Timeout for get requests. 0 means no timeout. | `0s` | `OP_BATCHER_ALTDA_GET_TIMEOUT` | +| `--altda.max-concurrent-da-requests` | Maximum number of concurrent requests to the DA server | `1` | `OP_BATCHER_ALTDA_MAX_CONCURRENT_DA_REQUESTS` | +| `--altda.put-timeout` | Timeout for put requests. 0 means no timeout. | `0s` | `OP_BATCHER_ALTDA_PUT_TIMEOUT` | +| `--altda.verify-on-read` | Verify input data matches the commitments from the DA storage service | `true` | `OP_BATCHER_ALTDA_VERIFY_ON_READ` | +| `--approx-compr-ratio` | The approximate compression ratio (\<= 1.0). Only relevant for ratio compressor. | `0.6` | `OP_BATCHER_APPROX_COMPR_RATIO` | +| `--batch-type` | The batch type. 0 for SingularBatch and 1 for SpanBatch. | `singular` | `OP_BATCHER_BATCH_TYPE` | +| `--check-recent-txs-depth` | Indicates how many blocks back the batcher should look during startup for a recent batch tx on L1. This can speed up waiting for node sync. It should be set to the verifier confirmation depth of the sequencer (e.g. 4). | `0` | `OP_BATCHER_CHECK_RECENT_TXS_DEPTH` | +| `--compression-algo` | The compression algorithm to use. Valid options: zlib, brotli, brotli-9, brotli-10, brotli-11 | `zlib` | `OP_BATCHER_COMPRESSION_ALGO` | +| `--compressor` | The type of compressor. Valid options: none, ratio, shadow | `"shadow"` | `OP_BATCHER_COMPRESSOR` | +| `--data-availability-type` | The data availability type to use for submitting batches to the L1. Valid options: calldata, blobs, auto | `calldata` | `OP_BATCHER_DATA_AVAILABILITY_TYPE` | +| `--fee-limit-multiplier` | The multiplier applied to fee suggestions to put a hard limit on fee increases | `5` | `OP_BATCHER_TXMGR_FEE_LIMIT_MULTIPLIER` | +| `--hd-path` | The HD path used to derive the sequencer wallet from the mnemonic. The mnemonic flag must also be set. | — | `OP_BATCHER_HD_PATH` | +| `--log.color` | Color the log output if in terminal mode | `false` | `OP_BATCHER_LOG_COLOR` | +| `--log.format` | Format the log output. Supported formats: text, terminal, logfmt, logfmtms, json, jsonms | `text` | `OP_BATCHER_LOG_FORMAT` | +| `--log.level` | The lowest log level that will be output | `INFO` | `OP_BATCHER_LOG_LEVEL` | +| `--log.pid` | Show pid in the log | `false` | `OP_BATCHER_LOG_PID` | +| `--max-blocks-per-span-batch` | Maximum number of blocks to add to a span batch. Default is 0 - no maximum. | `0` | `OP_BATCHER_MAX_BLOCKS_PER_SPAN_BATCH` | +| `--max-channel-duration` | The maximum duration of L1-blocks to keep a channel open. 0 to disable. | `0` | `OP_BATCHER_MAX_CHANNEL_DURATION` | +| `--max-l1-tx-size-bytes` | The maximum size of a batch tx submitted to L1. Ignored for blobs, where max blob size will be used. | `120000` | `OP_BATCHER_MAX_L1_TX_SIZE_BYTES` | +| `--max-pending-tx` | The maximum number of pending transactions. 0 for no limit. | `1` | `OP_BATCHER_MAX_PENDING_TX` | +| `--metrics.addr` | Metrics listening address | `"0.0.0.0"` | `OP_BATCHER_METRICS_ADDR` | +| `--metrics.enabled` | Enable the metrics server | `false` | `OP_BATCHER_METRICS_ENABLED` | +| `--metrics.port` | Metrics listening port | `7300` | `OP_BATCHER_METRICS_PORT` | +| `--mnemonic` | The mnemonic used to derive the wallets for either the service | — | `OP_BATCHER_MNEMONIC` | +| `--network-timeout` | Timeout for all network operations | `10s` | `OP_BATCHER_NETWORK_TIMEOUT` | +| `--num-confirmations` | Number of confirmations which we will wait after sending a transaction | `10` | `OP_BATCHER_NUM_CONFIRMATIONS` | +| `--poll-interval` | How frequently to poll L2 for new blocks | `6s` | `OP_BATCHER_POLL_INTERVAL` | +| `--pprof.addr` | pprof listening address | `"0.0.0.0"` | `OP_BATCHER_PPROF_ADDR` | +| `--pprof.enabled` | Enable the pprof server | `false` | `OP_BATCHER_PPROF_ENABLED` | +| `--pprof.path` | pprof file path. If it is a directory, the path is \{dir\}/\{profileType\}.prof | — | `OP_BATCHER_PPROF_PATH` | +| `--pprof.port` | pprof listening port | `6060` | `OP_BATCHER_PPROF_PORT` | +| `--pprof.type` | pprof profile type. One of cpu, heap, goroutine, threadcreate, block, mutex, allocs | — | `OP_BATCHER_PPROF_TYPE` | +| `--private-key` | The private key to use with the service. Must not be used with mnemonic. | — | `OP_BATCHER_PRIVATE_KEY` | +| `--resubmission-timeout` | Duration we will wait before resubmitting a transaction to L1 | `48s` | `OP_BATCHER_RESUBMISSION_TIMEOUT` | +| `--rpc.addr` | rpc listening address | `"0.0.0.0"` | `OP_BATCHER_RPC_ADDR` | +| `--rpc.enable-admin` | Enable the admin API | `false` | `OP_BATCHER_RPC_ENABLE_ADMIN` | +| `--rpc.port` | rpc listening port | `8545` | `OP_BATCHER_RPC_PORT` | +| `--safe-abort-nonce-too-low-count` | Number of ErrNonceTooLow observations required to give up on a tx at a particular nonce without receiving confirmation | `3` | `OP_BATCHER_SAFE_ABORT_NONCE_TOO_LOW_COUNT` | +| `--sequencer-hd-path` | DEPRECATED: The HD path used to derive the sequencer wallet from the mnemonic. The mnemonic flag must also be set. | — | `OP_BATCHER_SEQUENCER_HD_PATH` | +| `--signer.address` | Address the signer is signing requests for | — | `OP_BATCHER_SIGNER_ADDRESS` | +| `--signer.endpoint` | Signer endpoint the client will connect to | — | `OP_BATCHER_SIGNER_ENDPOINT` | +| `--signer.header` | Headers to pass to the remote signer. Format `key=value`. Value can contain any character allowed in a HTTP header. When using env vars, split with commas. When using flags one key value pair per flag. | — | `OP_BATCHER_SIGNER_HEADER` | +| `--signer.tls.ca` | tls ca cert path | `"tls/ca.crt"` | `OP_BATCHER_SIGNER_TLS_CA` | +| `--signer.tls.cert` | tls cert path | `"tls/tls.crt"` | `OP_BATCHER_SIGNER_TLS_CERT` | +| `--signer.tls.enabled` | Enable or disable TLS client authentication for the signer | `true` | `OP_BATCHER_SIGNER_TLS_ENABLED` | +| `--signer.tls.key` | tls key | `"tls/tls.key"` | `OP_BATCHER_SIGNER_TLS_KEY` | +| `--stopped` | Initialize the batcher in a stopped state. The batcher can be started using the admin_startBatcher RPC | `false` | `OP_BATCHER_STOPPED` | +| `--sub-safety-margin` | The batcher tx submission safety margin (in #L1-blocks) to subtract from a channel's timeout and sequencing window, to guarantee safe inclusion of a channel on L1. | `10` | `OP_BATCHER_SUB_SAFETY_MARGIN` | +| `--target-num-frames` | The target number of frames to create per channel. Controls number of blobs per blob tx, if using Blob DA. | `1` | `OP_BATCHER_TARGET_NUM_FRAMES` | +| `--throttle.additional-endpoints` | Comma-separated list of endpoints to distribute throttling configuration to (in addition to the L2 endpoints specified with --l2-eth-rpc). | — | `OP_BATCHER_THROTTLE_ADDITIONAL_ENDPOINTS` | +| `--throttle.block-size-lower-limit` | The limit on the DA size of blocks when we are at maximum throttle intensity (linear and quadratic controllers only). 0 means no limits will ever be applied, so consider 1 the smallest effective limit. | `2000` | `OP_BATCHER_THROTTLE_BLOCK_SIZE_LOWER_LIMIT` | +| `--throttle.block-size-upper-limit` | The limit on the DA size of blocks when we are at 0 throttle intensity (applied when throttling is inactive) | `130000` | `OP_BATCHER_THROTTLE_BLOCK_SIZE_UPPER_LIMIT` | +| `--throttle.controller-type` | Type of throttle controller to use: 'step', 'linear', 'quadratic' (default) or 'pid' (EXPERIMENTAL - use with caution) | `"quadratic"` | `OP_BATCHER_THROTTLE_CONTROLLER_TYPE` | +| `--throttle.pid-integral-max` | EXPERIMENTAL: PID controller maximum integral windup. Only relevant if --throttle-controller-type is set to 'pid' | `1000` | `OP_BATCHER_THROTTLE_PID_INTEGRAL_MAX` | +| `--throttle.pid-kd` | EXPERIMENTAL: PID controller derivative gain. Only relevant if --throttle-controller-type is set to 'pid' | `0.05` | `OP_BATCHER_THROTTLE_PID_KD` | +| `--throttle.pid-ki` | EXPERIMENTAL: PID controller integral gain. Only relevant if --throttle-controller-type is set to 'pid' | `0.01` | `OP_BATCHER_THROTTLE_PID_KI` | +| `--throttle.pid-kp` | EXPERIMENTAL: PID controller proportional gain. Only relevant if --throttle-controller-type is set to 'pid' | `0.33` | `OP_BATCHER_THROTTLE_PID_KP` | +| `--throttle.pid-output-max` | EXPERIMENTAL: PID controller maximum output. Only relevant if --throttle-controller-type is set to 'pid' | `1` | `OP_BATCHER_THROTTLE_PID_OUTPUT_MAX` | +| `--throttle.pid-sample-time` | EXPERIMENTAL: PID controller sample time interval, default is 2s | `2s` | `OP_BATCHER_THROTTLE_PID_SAMPLE_TIME` | +| `--throttle.tx-size-lower-limit` | The limit on the DA size of transactions when we are at maximum throttle intensity. 0 means no limits will ever be applied, so consider 1 the smallest effective limit. | `150` | `OP_BATCHER_THROTTLE_TX_SIZE_LOWER_LIMIT` | +| `--throttle.tx-size-upper-limit` | The limit on the DA size of transactions when we are at 0+ throttle intensity (limit of the intensity as it approaches 0 from positive values). Not applied when throttling is inactive. | `20000` | `OP_BATCHER_THROTTLE_TX_SIZE_UPPER_LIMIT` | +| `--throttle.unsafe-da-bytes-lower-threshold` | The threshold on unsafe_da_bytes beyond which the batcher will start to throttle the block builder. Zero disables throttling. | `3200000` | `OP_BATCHER_THROTTLE_UNSAFE_DA_BYTES_LOWER_THRESHOLD` | +| `--throttle.unsafe-da-bytes-upper-threshold` | Threshold on unsafe_da_bytes at which throttling has the maximum intensity (linear and quadratic controllers only) | `12800000` | `OP_BATCHER_THROTTLE_UNSAFE_DA_BYTES_UPPER_THRESHOLD` | +| `--txmgr.already-published-custom-errs` | List of custom RPC error messages that indicate that a transaction has already been published. | — | `OP_BATCHER_TXMGR_ALREADY_PUBLISHED_CUSTOM_ERRS` | +| `--txmgr.blob-tip-cap-dynamic` | Use dynamic blob tip cap from the blob tip oracle instead of static tip cap for blob transactions. Regular transactions still use min-tip-cap/max-tip-cap. | `false` | `OP_BATCHER_TXMGR_BLOB_TIP_CAP_DYNAMIC` | +| `--txmgr.blob-tip-cap-percentile` | Percentile of recent blob tx tips to use for suggestion (1-100). Only used when blob-tip-cap-dynamic is enabled. | `60` | `OP_BATCHER_TXMGR_BLOB_TIP_CAP_PERCENTILE` | +| `--txmgr.blob-tip-cap-range` | Number of recent blocks to analyze for blob tip cap distribution. Only used when blob-tip-cap-dynamic is enabled. | `20` | `OP_BATCHER_TXMGR_BLOB_TIP_CAP_RANGE` | +| `--txmgr.cell-proof-time` | Enables cell proofs in blob transactions for Fusaka (EIP-7742) compatibility from the provided unix timestamp. Should be set to the L1 Fusaka time. May be left blank for Ethereum Mainnet, Sepolia, Holesky, or Hoodi L1s. | `18446744073709551615` | `OP_BATCHER_TXMGR_CELL_PROOF_TIME` | +| `--txmgr.fee-limit-threshold` | The minimum threshold (in GWei) at which fee bumping starts to be capped. Allows arbitrary fee bumps below this threshold. | `100` | `OP_BATCHER_TXMGR_FEE_LIMIT_THRESHOLD` | +| `--txmgr.max-basefee` | Enforces a maximum base fee (in GWei) to assume when determining tx fees, `TxMgr` returns an error when exceeded. Disabled by default. | `0` | `OP_BATCHER_TXMGR_MAX_BASEFEE` | +| `--txmgr.max-retries` | Maximum number of times to resubmit a transaction to L1 on a transient error. Set to 0 to disable retries. | `10` | `OP_BATCHER_TXMGR_MAX_RETRIES` | +| `--txmgr.max-tip-cap` | Enforces a maximum tip cap (in GWei) to use when determining tx fees, `TxMgr` returns an error when exceeded. Disabled by default. | `0` | `OP_BATCHER_TXMGR_MAX_TIP_CAP` | +| `--txmgr.min-basefee` | Enforces a minimum base fee (in GWei) to assume when determining tx fees. 1 GWei by default. | `1` | `OP_BATCHER_TXMGR_MIN_BASEFEE` | +| `--txmgr.min-tip-cap` | Enforces a minimum tip cap (in GWei) to use when determining tx fees. 1 GWei by default. | `1` | `OP_BATCHER_TXMGR_MIN_TIP_CAP` | +| `--txmgr.not-in-mempool-timeout` | Timeout for aborting a tx send if the tx does not make it to the mempool. | `2m0s` | `OP_BATCHER_TXMGR_TX_NOT_IN_MEMPOOL_TIMEOUT` | +| `--txmgr.rebroadcast-interval` | Interval at which a published transaction will be rebroadcasted if it has not yet been mined. Should be less than ResubmissionTimeout to have an effect. | `12s` | `OP_BATCHER_TXMGR_REBROADCAST_INTERVAL` | +| `--txmgr.receipt-query-interval` | Frequency to poll for receipts | `12s` | `OP_BATCHER_TXMGR_RECEIPT_QUERY_INTERVAL` | +| `--txmgr.retry-interval` | Duration we will wait before resubmitting a transaction to L1 on a transient error. Values \<= 0 will result in retrying immediately. Should be less than ResubmissionTimeout to have an effect. | `1s` | `OP_BATCHER_TXMGR_RETRY_INTERVAL` | +| `--txmgr.send-timeout` | Timeout for sending transactions. If 0 it is disabled. | `0s` | `OP_BATCHER_TXMGR_TX_SEND_TIMEOUT` | +| `--wait-node-sync` | Indicates if, during startup, the batcher should wait for a recent batcher tx on L1 to finalize (via more block confirmations). This should help avoid duplicate batcher txs. | `false` | `OP_BATCHER_WAIT_NODE_SYNC` |