Skip to main content
pipeline is a Go library, not a standalone process. It is compiled into the execution client, collects block execution data through EVM tracing hooks, serializes it and writes it to S3, and publishes block change notifications to Kafka.

Modules

Two integration modes

The tracer is embedded in the block execution flow and collects and uploads in real time. Zero extra latency, but it requires changes to the execution client’s core code.

Collection mechanics

CallTracer

Maintains the call stack and builds the call tree. OnEnter pushes a frame; OnExit pops it and attaches it under the parent frame.
  • Storage change marking: recognizes the SSTORE instruction and propagates StorageChange up to ancestor calls
  • Failure isolation: when a call fails, marks itself and all sub-calls with ParentFailed; after flattening they go into ErrorTraces / ErrorEvents
  • ID generation: the trace ID is hash(tx_id, parent_trace_id, position) and the event ID is hash(parent_trace_id, position), which guarantees reproducibility across blocks

Two paths to StateDiff

The second is for clients without a commit hook. No diff object is generated when originRoot == root.

Upload and publish

OnCommit runs four uploads concurrently:
The encoding is chosen per consumer:
  • StateDiff uses RLP: it is consumed only by internal components, and is much smaller than JSON.
  • BlockFile uses JSON: external consumers need to parse it directly.
Configuring s3_temp_dir enables a local cache: data is written to disk first and uploaded asynchronously; the local file is deleted after a successful upload. When S3 returns 5xx, the upload is retried with backoff; the retry count goes into pipeline/s3_upload_retry.

Leader election

Multiple write nodes can run pipeline at the same time, but only the Leader publishes notifications to Kafka; all instances upload to S3. S3 objects are keyed by hash and state root, so duplicate uploads are idempotent.
Configure etcd_endpoints and leave is_backup empty.
  • Acquire the key when it does not exist; watch it when it does.
  • After the key is deleted, back off randomly before acquiring again, to avoid a thundering herd.
  • Wait grace_period (default 10 seconds) before becoming Leader, so the previous Leader can finish up.
When etcd is configured, write node registration is also enabled: the node writes {chainID}[/{version}]/writers/{nodeID} with a lease, which is cleaned up automatically when the node fails. This is the data that nodex-proxy’s /{chainId}/writers admin endpoint reads.

Configuration

The JSON passed to NewPipelineTracer (that is, geth’s --vmtrace.jsonconfig):

Metrics

Exposed through go-ethereum’s metrics system.

Development

The repository has three more detailed documents:

Interface contracts

The exact format of Kafka messages and S3 keys.

Adding a new chain

Adapt pipeline to Geth, legacy Geth, or Reth forks.