Skip to content
Open
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
38 changes: 37 additions & 1 deletion containers/op-rbuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,40 @@ function resolvedPorts(def: ContainerDef | ProcessDef): Ports {
return { ...ports, ...((def.config?.ports as Ports | undefined) ?? {}) };
}

type FlashblocksConfig = {
blockTimeMs?: number; // --flashblocks.block-time
endBufferMs?: number; // --flashblocks.end-buffer-ms
sendOffsetMs?: number; // --flashblocks.send-offset-ms (negative sends early)
continuousBuild?: boolean; // --flashblocks.continuous-build
};

const FLASHBLOCKS_DEFAULTS: Required<FlashblocksConfig> = {
blockTimeMs: 200,
endBufferMs: 75,
sendOffsetMs: -30,
continuousBuild: true,
};

// op-rbuilder default for --flashblocks.port
const FLASHBLOCKS_WS_PORT = 1111;

function flashblocksArgs(opt: boolean | FlashblocksConfig | undefined, wsPort: number): string[] {
if (!opt) return [];
const cfg = { ...FLASHBLOCKS_DEFAULTS, ...(typeof opt === "object" ? opt : {}) };
return [
"--flashblocks.addr", "0.0.0.0",
"--flashblocks.port", String(wsPort),
"--flashblocks.block-time", String(cfg.blockTimeMs),
"--flashblocks.end-buffer-ms", String(cfg.endBufferMs),
"--flashblocks.send-offset-ms", String(cfg.sendOffsetMs),
...(cfg.continuousBuild ? ["--flashblocks.continuous-build"] : []),
];
}

export function buildContainer(def: ContainerDef, _ctx: Ctx): ContainerResult {
const ps = resolvedPorts(def);
const flashblocks = def.config?.flashblocks as boolean | FlashblocksConfig | undefined;
const fbPort = portNum(ps.flashblocks ?? FLASHBLOCKS_WS_PORT);
return {
container: {
image: "ghcr.io/flashbots/op-rbuilder:v0.4.9",
Expand All @@ -55,8 +87,9 @@ export function buildContainer(def: ContainerDef, _ctx: Ctx): ContainerResult {
"--bootnodes", `enode://${BOOTNODE_ID}@bootnode:30303`,
"--nat", "none",
"--rollup.discovery.v4",
...flashblocksArgs(flashblocks, fbPort),
],
ports: ps,
ports: flashblocks ? { ...ps, flashblocks: ps.flashblocks ?? FLASHBLOCKS_WS_PORT } : ps,
volumeMounts: [
{ name: "artifacts", mountPath: "/artifacts", readOnly: true },
{ name: "data", mountPath: "/data_op_rbuilder" },
Expand Down Expand Up @@ -94,6 +127,8 @@ export function buildProcess(def: ProcessDef, ctx: HostCtx): ProcessResult {
const dataDir = ctx.dataPath(def.name, "data");
// The sequencer EL only publishes its p2p port to the host in this mode.
const elP2pPort = new URL(ctx.url(l2, "p2p")).port;
const flashblocks = def.config?.flashblocks as boolean | FlashblocksConfig | undefined;
const fbPort = portNum(ps.flashblocks ?? FLASHBLOCKS_WS_PORT);

return {
process: {
Expand All @@ -119,6 +154,7 @@ export function buildProcess(def: ProcessDef, ctx: HostCtx): ProcessResult {
// don't rely on discovery at all: dial EL directly by its fixed enode
"--trusted-peers", `enode://${EL_P2P_ID}@127.0.0.1:${elP2pPort}`,
"--disable-discovery",
...flashblocksArgs(flashblocks, fbPort),
],
},
binaryBuild: def.binary ? undefined : BUILD,
Expand Down
3 changes: 3 additions & 0 deletions decker.example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ export const project: DeckerProject = {
// externalBuilder: "op-rbuilder",
// // Run op-rbuilder as a host process instead of the pinned container
// builderBinary: "../op-rbuilder/target/profiling/op-rbuilder",
// // Enable op-rbuilder's Flashblocks websocket stream (ws://<host>:1111);
// // pass an object instead of `true` to override individual fields.
// flashblocks: true,
// },
//
// Add or override the prototypes the recipe resolves by name — tweak a
Expand Down
20 changes: 19 additions & 1 deletion recipes/opstack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ export type OpstackOptions = {
// op-rbuilder can trusted-peer-dial it directly instead of going through the
// container-mode bootnode, which the host can't reach. (default off)
builderBinary?: string | boolean;
// Enable or tune op-rbuilder flashblocks websocket streaming
flashblocks?: boolean | string | {
blockTimeMs?: number;
endBufferMs?: number;
sendOffsetMs?: number;
continuousBuild?: boolean;
};
};

export function recipe(o: OpstackOptions = {}): Recipe {
Expand All @@ -44,6 +51,16 @@ export function recipe(o: OpstackOptions = {}): Recipe {
throw new Error(`opstack: builderBinary requires externalBuilder="op-rbuilder" (got ${externalBuilder || "false"})`);
}

// Same true/"true" vs. false/"false"/undefined as builderBinary
const flashblocksOpt = o.flashblocks;
const flashblocksEnabled = flashblocksOpt !== undefined && flashblocksOpt !== false && flashblocksOpt !== "false";
const flashblocks = flashblocksEnabled
? (flashblocksOpt === true || flashblocksOpt === "true" ? true : flashblocksOpt)
: undefined;
// Same value forwarded to both possible op-rbuilder placements below, so
// container mode and host-process mode can't tune Flashblocks differently.
const builderConfig = flashblocks !== undefined ? { flashblocks } : undefined;

// L2 execution client selection. Karst (OP Upgrade 19) ends op-geth support, so
// from Karst on the L2 EL is op-reth and op-node needs a newer release. Forks
// up to jovian keep the op-geth client set they were verified with.
Expand All @@ -70,7 +87,7 @@ export function recipe(o: OpstackOptions = {}): Recipe {
// peering; a host-process op-rbuilder dials the EL directly (see above).
...(builderHostProcess ? [] : [
{ name: "bootnode", containers: [{ name: "bootnode", prototype: "bootnode" }] },
{ name: "op-rbuilder", containers: [{ name: "op-rbuilder", prototype: "op-rbuilder" }] },
{ name: "op-rbuilder", containers: [{ name: "op-rbuilder", prototype: "op-rbuilder", config: builderConfig }] },
]),
{
name: "rollup-boost",
Expand All @@ -86,6 +103,7 @@ export function recipe(o: OpstackOptions = {}): Recipe {
name: "op-rbuilder",
prototype: "op-rbuilder",
refs: { l2: l2El },
config: builderConfig,
...(builderBinaryPath ? { binary: builderBinaryPath } : {}),
},
]
Expand Down
Loading