
⚠️ WARNING: Dingo is under heavy active development and is not yet ready for production use. It should only be used on testnets (preview, preprod) and devnets. Do not use Dingo on mainnet with real funds.
A high-performance Cardano blockchain node implementation in Go by Blink Labs. Dingo provides: - Full chain synchronization and validation via Ouroboros consensus protocol - UTxO tracking with 41 UTXO validation rules and Plutus V1/V2/V3 smart contract execution - Block production with VRF leader election and stake snapshots - Multi-peer chain selection with density comparison and VRF tie-breaking - Client connectivity for wallets and applications - Pluggable storage backends (Badger, SQLite, PostgreSQL, MySQL, GCS, S3) - Tiered storage modes ("core" for consensus, "api" for full indexing) - Peer governance with dynamic peer selection, ledger peers, and topology support - Chain rollback support for handling forks with automatic state restoration - Fast bootstrapping via built-in Mithril client - Multiple external interfaces: general-purpose APIs (UTxO RPC, Blockfrost-compatible REST, Mesh/Rosetta) plus Bark for Dingo-to-Dingo C2 and archive services
Note: On Windows systems, named pipes are used instead of Unix sockets for node-to-client communication.

Dingo supports configuration via a YAML config file (dingo.yaml), environment variables, and command-line flags. Priority: CLI flags > environment variables > YAML config > defaults.
A sample configuration file is provided at dingo.yaml.example. You can copy and edit this file to configure Dingo for your local or production environment.
The following environment variables modify Dingo's behavior:
CARDANO_BIND_ADDR0.0.0.0)CARDANO_CONFIG./config/cardano/preview/config.json)CARDANO_DATABASE_PATH.dingo)CARDANO_INTERSECT_TIPfalse)CARDANO_METRICS_PORT12798)CARDANO_NETWORKpreview)CARDANO_PRIVATE_BIND_ADDR127.0.0.1)CARDANO_PRIVATE_PORT3002)CARDANO_RELAY_PORT3001)CARDANO_SOCKET_PATHdingo.socket)CARDANO_TOPOLOGYDINGO_UTXORPC_PORT0, disabled)DINGO_BLOCKFROST_PORT0, disabled)DINGO_MESH_PORT0, disabled)DINGO_BARK_PORT0, disabled)DINGO_BARK_BASE_URLDINGO_BARK_BLOCK_DOWNLOAD_HOSTSDINGO_BARK_BASE_URL hostname.DINGO_HISTORY_EXPIRY_ENABLEDfalse)DINGO_HISTORY_EXPIRY_FREQUENCY1h)DINGO_STORAGE_MODEcore (default) or apicore stores only consensus data (UTxOs, certs, pools, protocol params)api additionally stores witnesses, scripts, datums, redeemers, and tx metadataapi modeDINGO_RUN_MODEserve (full node, default), load (batch import), dev (development mode), or leios (experimental Leios/Dijkstra protocol support)DINGO_START_ERAdijkstra only for Dijkstra/Leios test networks; leave empty to follow genesis protocol version.DINGO_LOGGING_FORMATtext (default, human-readable) or json (machine-parseable, for ELK/Loki ingestion)DINGO_LOGGING_LEVELdebug, info (default), warn, or error (the --debug flag overrides this to debug)TLS_CERT_FILE_PATH - SSL certificate to use, requires TLS_KEY_FILE_PATH
(default: empty)TLS_KEY_FILE_PATH - SSL certificate key to use (default: empty)To run Dingo as a stake pool operator producing blocks:
CARDANO_BLOCK_PRODUCER - Enable block production (default: false)CARDANO_SHELLEY_VRF_KEY - Path to VRF signing key fileCARDANO_SHELLEY_KES_KEY - Path to KES signing key fileCARDANO_SHELLEY_OPERATIONAL_CERTIFICATE - Path to operational certificate file# Preview network (default)
./dingo
# Mainnet
CARDANO_NETWORK=mainnet ./dingo
# Or with explicit config path
CARDANO_NETWORK=mainnet CARDANO_CONFIG=path/to/mainnet/config.json ./dingo
Dingo creates a dingo.socket file that speaks Ouroboros node-to-client and is compatible with cardano-cli, adder, kupo, and other Cardano client tools.
Cardano configuration files are bundled in the Docker image. For local builds, you can find them at docker-cardano-configs.
# Run on preview (default)
docker run -p 3001:3001 ghcr.io/blinklabs-io/dingo
# Run on mainnet with persistent storage
docker run -p 3001:3001 \
-e CARDANO_NETWORK=mainnet \
-v dingo-data:/data/db \
-v dingo-ipc:/ipc \
ghcr.io/blinklabs-io/dingo
The image is based on Debian bookworm-slim and includes cardano-cli, nview, and txtop. Mithril snapshot support is built into dingo natively (dingo mithril sync). The Dockerfile sets CARDANO_DATABASE_PATH=/data/db and CARDANO_SOCKET_PATH=/ipc/dingo.socket, overriding the local defaults of .dingo and dingo.socket — the volume mounts above map to these container paths.
| Port | Service | Default |
|---|---|---|
| 3001 | Ouroboros NtN (node-to-node) | Enabled |
| 3002 | Ouroboros NtC over TCP | Enabled |
| 12798 | Prometheus metrics | Enabled |
| 3000 | Blockfrost REST API | Disabled |
| 8080 | Mesh (Rosetta) REST API | Disabled |
| 9090 | UTxO RPC (gRPC) | Disabled |
| — | Bark archive (gRPC) | Disabled (example when enabled: 9091) |
Dingo has two storage modes that control how much data is persisted:
| Mode | What's Stored | Use Case |
|---|---|---|
core (default) |
UTxOs, certificates, pools, protocol parameters | Relays, block producers |
api |
Core data + witnesses, scripts, datums, redeemers, tx metadata | Nodes serving API queries |
# Relay or block producer (default)
./dingo
# API node
DINGO_STORAGE_MODE=api ./dingo
Or in dingo.yaml:
storageMode: "api"
Dingo includes three general-purpose external APIs plus Bark. UTxO RPC, Blockfrost, and Mesh are client-facing APIs and require storageMode: "api". Bark is different: it is Dingo's own protocol for Dingo-to-Dingo C2/archive services, not a general-purpose application API. Set an individual port to 0 to disable a specific interface. The Blockfrost server currently exposes the latest, epoch, network, and pool subset.
| Interface | Port Env Var | Default | Protocol | Role |
|---|---|---|---|---|
| UTxO RPC | DINGO_UTXORPC_PORT |
disabled | gRPC | General-purpose client API |
| Blockfrost | DINGO_BLOCKFROST_PORT |
disabled | REST | General-purpose client API |
| Mesh (Rosetta) | DINGO_MESH_PORT |
disabled | REST | General-purpose client API |
| Bark | DINGO_BARK_PORT |
disabled | Connect/gRPC | Dingo-to-Dingo C2/archive protocol |
# Enable Blockfrost API on port 3100 and UTxO RPC on port 9090
DINGO_STORAGE_MODE=api \
DINGO_BLOCKFROST_PORT=3100 \
DINGO_UTXORPC_PORT=9090 \
./dingo
Or in dingo.yaml:
storageMode: "api"
blockfrostPort: 3100
utxorpcPort: 9090
Dingo can expire immutable block CBOR from a local blob store once blocks are older than the ledger-derived stability window. This History Expiry mode is a valid standalone operational mode: without an archive fallback, reads for expired blocks return a clear history-expired error. When paired with Bark, expired or missing historical block reads can be transparently served from a remote archive node.
An archive node uses a signed-URL-capable blob plugin (s3 or gcs) and
enables Bark with barkPort. Bark answers Dingo-to-Dingo archive requests by
returning a signed object-storage URL plus block metadata. Badger is valid for a
normal local blob store, but it does not provide signed URLs and should not be
used as the Bark archive backend.
For local source builds, the s3 and gcs blob plugins require
-tags dingo_extra_plugins or make build. Official release binaries include
the extra plugin tag.
storageMode: "core"
database:
blob:
plugin: "s3"
s3:
bucket: "dingo-archive"
region: "us-east-1"
prefix: "preview"
barkPort: 9091
A history-expiry node keeps its normal local blob store and enables
historyExpiry. Dingo expires blocks older than the ledger-derived stability
window while keeping local indexes and metadata, so reads fail explicitly as
expired history unless an archive wrapper can serve them.
storageMode: "core"
database:
blob:
plugin: "badger"
historyExpiry:
enabled: true
frequency: 1h
Add barkBaseUrl when expired historical reads should fall back to a Bark
archive:
barkBaseUrl: "http://archive.example.internal:9091"
barkBlockDownloadHosts:
- "dingo-archive.s3.us-east-1.amazonaws.com"
Bark archive RPC may use the configured barkBaseUrl, but the block download
URLs returned by that service must be HTTPS, must not contain credentials, and
must match either the barkBaseUrl hostname or barkBlockDownloadHosts.
The runnable demonstration in internal/test/archive-demo/ brings up an S3
compatible Minio archive node, a local Badger history-expiry node, and an end-to-end
BlockFetch check through Bark.
Relay node (consensus only, no APIs):
./dingo
API / data node (full indexing, one or more APIs):
DINGO_STORAGE_MODE=api DINGO_BLOCKFROST_PORT=3100 ./dingo
Archive node (cloud object storage plus Bark archive service):
DINGO_DATABASE_BLOB_PLUGIN=s3 DINGO_BARK_PORT=9091 ./dingo
History-expiry node (local storage plus a remote Bark archive):
DINGO_HISTORY_EXPIRY_ENABLED=true \
DINGO_BARK_BASE_URL=http://archive.example.internal:9091 ./dingo
Block producer (consensus only, with SPO keys):
CARDANO_BLOCK_PRODUCER=true \
CARDANO_SHELLEY_VRF_KEY=/keys/vrf.skey \
CARDANO_SHELLEY_KES_KEY=/keys/kes.skey \
CARDANO_SHELLEY_OPERATIONAL_CERTIFICATE=/keys/opcert.cert \
./dingo
When storageMode=core, the Badger blob store defaults to mmap-only settings: block-cache-size=0, index-cache-size=0, and compression=false. When storageMode=api, the default Badger profile is block-cache-size=268435456, index-cache-size=0, and compression=true. YAML, environment variable, and CLI Badger options override those defaults only when explicitly set.
See dingo.yaml.example for the full set of configuration options.
Instead of syncing from genesis (which can take days on mainnet), you can bootstrap Dingo using a Mithril snapshot. Dingo has a built-in Mithril client that handles download, extraction, and import automatically. This is the fastest way to get a node running.
# Bootstrap from Mithril and start syncing
./dingo -n preview sync --mithril
# Then start the node
./dingo -n preview serve
Or use the subcommand form for more control:
# List available snapshots
./dingo -n preview mithril list
# Show snapshot details
./dingo -n preview mithril show <hash>
# Download and import
./dingo -n preview mithril sync
Two Mithril artifact backends are supported via mithril.backend (or
--mithril-backend): v2 (default) restores from incremental per-immutable-file
archives verified against the certified merkle root, while v1 uses the legac
$ claude mcp add dingo \
-- python -m otcore.mcp_server <graph>