@blinklabs/dingo 0.36.1 → 0.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -1,115 +1,51 @@
1
1
  # AGENTS.md
2
2
 
3
- Concise guide for AI agents working with Dingo. For full details, see `ARCHITECTURE.md`.
3
+ Go Cardano node (Ouroboros). See `CLAUDE.md` for detailed rules; this file has additional content (Build/test section, `make golines` in pre-commit, Key events table) and a different structure — the two are related but not exact copies. Package layout, targets, and flags are derivable from `Makefile`, `go.mod`, `node.go`.
4
4
 
5
- ## Quick Reference
5
+ ## Build / test
6
6
 
7
- **Dingo**: Go-based Cardano blockchain node by Blink Labs (Ouroboros protocol, UTxO tracking, pluggable storage).
8
-
9
- ```bash
10
- make # Format, test, build
11
- make test # Tests with race detection
12
- make bench # Run benchmarks
13
- go run ./cmd/dingo/ # Run without building
14
- go test -v -race -run TestName ./path/to/package/ # Single test
15
7
  ```
16
-
17
- ## Key Packages
18
-
19
- | Package | Purpose |
20
- |---------|---------|
21
- | `chain/` | Blockchain state, fork detection, rollback |
22
- | `chainselection/` | Multi-peer chain comparison (Ouroboros Praos) |
23
- | `chainsync/` | Block sync state tracking |
24
- | `connmanager/` | Network connection lifecycle |
25
- | `database/` | Storage plugins (badger, sqlite, postgres, mysql, gcs, s3) |
26
- | `event/` | Event bus (async pub/sub, 4 workers) |
27
- | `ledger/` | UTxO state, protocol params, Plutus execution |
28
- | `mempool/` | Transaction pool & validation |
29
- | `ouroboros/` | Protocol handlers (N2N, N2C) |
30
- | `peergov/` | Peer governance, churn, quotas |
31
- | `utxorpc/` | UTxO RPC gRPC server |
32
-
33
- ## Code Quality (Run Before Committing)
34
-
35
- ```bash
36
- golangci-lint run ./... # Linters (39 via .golangci.yml)
37
- nilaway ./... # Nil-safety analyzer
38
- modernize ./... # Modern Go idioms
39
- make golines # 80 char line limit
8
+ make # fmt, test, build
9
+ make test # tests with -race
10
+ go test -v -race -run TestName ./path/to/pkg/
40
11
  ```
41
12
 
42
- ## Essential Patterns
43
-
44
- ### Error Handling
45
- ```go
46
- // Wrap errors with context
47
- return fmt.Errorf("failed to process block: %w", err)
48
- ```
13
+ ## Pre-commit
49
14
 
50
- ### Event-Driven Communication
51
- ```go
52
- // Subscribe to events (never call components directly)
53
- eventBus.SubscribeFunc(chain.ChainForkEventType, handler)
54
15
  ```
55
-
56
- ### Database Queries
57
- ```go
58
- // GOOD: Batch fetch (single query)
59
- db.Where("id IN ?", ids).Find(&records)
60
-
61
- // BAD: N+1 queries
62
- for _, id := range ids {
63
- db.Where("id = ?", id).First(&record)
64
- }
65
-
66
- // Certificate ordering: use cert_index as tie-breaker
67
- Order("added_slot DESC, cert_index DESC")
16
+ golangci-lint run ./...
17
+ nilaway ./...
18
+ modernize ./...
19
+ make golines
68
20
  ```
69
21
 
70
- ### Rollback Handling
71
- - `Chain.Rollback(point)` emits `ChainRollbackEvent`
72
- - State restoration in `database/plugin/metadata/sqlite/`
73
- - Use `TransactionEvent.Rollback` field to detect undo operations
74
-
75
- ### CBOR Storage
76
- - UTxOs/TXs stored as 52-byte `CborOffset` (magic "DOFF" + slot + hash + offset + length)
77
- - `TieredCborCache` resolves: hot cache → block LRU → cold extraction
78
-
79
- ### Stake Snapshots
80
- - Mark/Set/Go rotation at epoch boundaries (Ouroboros Praos)
81
- - `LedgerView.GetStakeDistribution(epoch)` for leader election queries
82
- - `PoolStakeSnapshot` model stores per-pool stake
83
- - `EpochSummary` stores network aggregates
84
-
85
- ## Key Event Types
86
-
87
- | Event | Purpose |
88
- |-------|---------|
89
- | `chain.update` | Block added to chain |
90
- | `chain.fork-detected` | Fork detected |
91
- | `chainselection.chain_switch` | Active peer changed |
92
- | `epoch.transition` | Epoch boundary crossed (triggers stake snapshot) |
93
- | `mempool.add_tx` / `mempool.remove_tx` | Transaction lifecycle |
94
- | `connmanager.conn-closed` | Connection lifecycle |
95
- | `peergov.peer-churn` | Peer rotation |
22
+ ## Testing rules
96
23
 
97
- ## Configuration
24
+ - No `time.Sleep()` for sync — use `internal/test/testutil/` (`WaitForCondition`, `RequireReceive`, `context.WithTimeout`).
25
+ - Integration tests: `internal/integration/` + `database/immutable/testdata/` (real blocks, slots 0–1.3M).
26
+ - Mock fixtures come from `github.com/blinklabs-io/ouroboros-mock` (`fixtures/`, `ledger/`, `conformance/`). Never duplicate mocks inside dingo — extend the shared library so every Blink Labs app (dingo, gouroboros, adder, ...) reuses the same test surface.
98
27
 
99
- Priority: CLI flags > Env vars > YAML config > Defaults
28
+ ## Non-obvious invariants
100
29
 
101
- Key env vars: `CARDANO_NETWORK`, `CARDANO_DATABASE_PATH`, `DINGO_DATABASE_BLOB_PLUGIN`, `DINGO_DATABASE_METADATA_PLUGIN`
30
+ - EventBus for async cross-component notifications: use `event.EventBus.SubscribeFunc()` for block/chain/mempool/peer events. Synchronous state queries between components still use direct method calls.
31
+ - CBOR offsets: UTxOs/txs stored as 52-byte refs (magic `"DOFF"` + slot + hash + offset + length), resolved by `TieredCborCache` (hot → block LRU → cold extract). See `database/cbor_offset.go`.
32
+ - Cert ordering: `Order("added_slot DESC, block_index DESC, cert_index DESC")` — `cert_index` resets per tx, so `block_index` is required to disambiguate across txs in the same block.
33
+ - Rollbacks: delivered on `chain.update` as a `chain.ChainRollbackEvent` payload (no separate `chain.rollback` topic); also subscribe to `chain.fork_detected` for fork metrics. Check `TransactionEvent.Rollback` for undo.
34
+ - Stake snapshots: mark/set/go rotation at epoch boundaries (Praos). `LedgerView.GetStakeDistribution(epoch)` for leader election. Per-pool stake in `PoolStakeSnapshot`; aggregates in `EpochSummary`.
35
+ - Plugins (`database/plugin/`): blob = `badger` | `gcs` | `s3`; metadata = `sqlite` | `mysql` | `postgres`.
102
36
 
103
- ## Critical Anti-Patterns
37
+ ## Key events
104
38
 
105
- 1. **Don't bypass EventBus** - Components communicate via events, not direct calls
106
- 2. **Don't use N+1 queries** - Batch fetch with `WHERE id IN ?`
107
- 3. **Don't forget cert_index** - Multiple certs in same slot need ordering
108
- 4. **Don't ignore rollbacks** - Check `TransactionEvent.Rollback` field
109
- 5. **Don't skip linting** - Run `golangci-lint`, `nilaway`, `modernize` before commits
39
+ | Event | Meaning |
40
+ |---|---|
41
+ | `chain.update` | block added |
42
+ | `chain.fork_detected` | fork |
43
+ | `chainselection.chain_switch` | active peer changed |
44
+ | `epoch.transition` | epoch boundary — triggers stake snapshot |
45
+ | `mempool.add_tx` / `mempool.remove_tx` | tx lifecycle |
46
+ | `connmanager.conn_closed` | connection closed |
47
+ | `peergov.peer_churn` | peer rotation |
110
48
 
111
- ## Testing
49
+ ## Config
112
50
 
113
- - Integration tests: `internal/integration/`
114
- - Test data: `database/immutable/testdata/` (real blocks slots 0-1.3M)
115
- - Benchmarks: `make bench` (28+ benchmarks)
51
+ Priority: CLI > env > YAML > defaults. Key env vars: `CARDANO_NETWORK`, `CARDANO_DATABASE_PATH`, `DINGO_DATABASE_BLOB_PLUGIN`, `DINGO_DATABASE_METADATA_PLUGIN`.
package/CLAUDE.md CHANGED
@@ -1,33 +1,37 @@
1
1
  # CLAUDE.md
2
2
 
3
- Go-based Cardano node implementing Ouroboros. Most of what you need is derivable from code (`Makefile`, `go.mod`, `node.go`, `dingo.yaml.example`). Below is what isn't.
3
+ Go Cardano node (Ouroboros). Derivable info (build targets, flags, package layout) lives in `Makefile`, `go.mod`, `node.go`, `dingo.yaml.example`. This file is only what isn't derivable.
4
4
 
5
- ## Testing rules
5
+ ## Testing
6
6
 
7
- - **Never use `time.Sleep()` for synchronization.** Use helpers in `internal/test/testutil/`:
8
- - `WaitForCondition` / `require.Eventually` for polling (2–5s timeout, 5–10ms interval, lock shared state inside the condition fn)
7
+ - No `time.Sleep()` for sync. Use `internal/test/testutil/`:
8
+ - `WaitForCondition` / `require.Eventually` — 2–5s timeout, 5–10ms interval, lock shared state inside the condition fn
9
9
  - `RequireReceive` / `RequireNoReceive` for channel assertions
10
- - `context.WithTimeout` for graceful shutdown — not sleep
11
- - Race detection is on by default in `make test`.
10
+ - `context.WithTimeout` for graceful shutdown
11
+ - `make test` runs with `-race`.
12
12
  - Integration tests in `internal/integration/` load real blocks from `database/immutable/testdata/`.
13
+ - Mock fixtures come from `github.com/blinklabs-io/ouroboros-mock` (`fixtures/`, `ledger/`, `conformance/`). Never add local ledger/consensus/network mocks — extend the shared library.
13
14
 
14
- ## Before committing
15
+ ## Pre-commit
15
16
 
16
- ```bash
17
- golangci-lint run ./... # .golangci.yml configured
17
+ ```shell
18
+ golangci-lint run ./...
18
19
  nilaway ./...
19
- modernize ./... # --fix to auto-apply
20
+ modernize ./... # --fix to auto-apply
20
21
  ```
21
22
 
22
- ## Non-obvious architecture
23
+ ## Non-obvious invariants
23
24
 
24
- - **CBOR offset storage**: UTxOs/txs store 52-byte `CborOffset` refs (magic `"DOFF"`, slot, hash, offset, length), not full CBOR. Resolved via `TieredCborCache` (hot → block LRU → cold extract from blob store). See `database/cbor_offset.go`, `database/cbor_cache.go`, `database/block_indexer.go`.
25
- - **Plugins** (`database/plugin/`): blob = `badger` (default) / `gcs` / `s3`; metadata = `sqlite` (default) / `mysql` / `postgres`.
26
- - **Event bus**: components communicate via `event.EventBus.SubscribeFunc()`, not direct calls.
25
+ - CBOR offsets: UTxOs/txs store 52-byte `CborOffset` refs (magic `"DOFF"` + slot + hash + offset + length), not full CBOR. Resolved via `TieredCborCache` (hot → block LRU → cold blob extract). See `database/cbor_offset.go`, `database/cbor_cache.go`, `database/block_indexer.go`.
26
+ - EventBus for async cross-component notifications: block/chain/mempool/peer events go through `event.EventBus.SubscribeFunc()`. Synchronous state queries between components still use direct method calls.
27
+ - Cert ordering: multiple certs per slot — tie-break with `Order("added_slot DESC, block_index DESC, cert_index DESC")` (`cert_index` resets per tx, so `block_index` is required to disambiguate across txs in the same block).
28
+ - Rollbacks: `Chain.Rollback(point)` emits `ChainRollbackEvent`; check `TransactionEvent.Rollback` for undo.
29
+ - Plugins (`database/plugin/`): blob = `badger` (default) | `gcs` | `s3`; metadata = `sqlite` (default) | `mysql` | `postgres`.
30
+ - Config priority: CLI > env > YAML > defaults.
27
31
 
28
32
  ## Profiling
29
33
 
30
- ```bash
34
+ ```shell
31
35
  ./dingo --cpuprofile=cpu.prof --memprofile=mem.prof load database/immutable/testdata
32
36
  go tool pprof cpu.prof
33
37
  ```
package/RELEASE_NOTES.md CHANGED
@@ -1,6 +1,81 @@
1
1
  # Release Notes
2
2
 
3
3
 
4
+ ## v0.37.0 (April 27, 2026)
5
+
6
+ **Title:** Genesis bootstrap, governance, and steadier Mithril recovery
7
+
8
+ **Date:** April 27, 2026
9
+
10
+ **Version:** v0.37.0
11
+
12
+ Hi folks! Here’s what we shipped in v0.37.0.
13
+
14
+ ### ✨ What's New
15
+
16
+ * Added **Ouroboros Genesis bootstrap support:** Operators can now start from Genesis bootstrap flows, which gives early sync a clearer path before the node reaches the current chain tip.
17
+ * Expanded **Genesis mode chain selection:** Nodes can now choose the chain more safely during Genesis mode, which keeps early sync aligned with the right history.
18
+ * Introduced **bootstrap aware peer promotion:** Peer promotion now accounts for bootstrap state, which helps early sync keep useful peers active while the node is still catching up.
19
+ * Delivered **Conway governance ratification support:** Governance aware services can now track ratified actions more completely as Conway governance advances.
20
+ * Enabled **Conway governance enactment handling:** Governance state now follows enacted actions more accurately, which gives operators and integrators a clearer view of active governance outcomes.
21
+ * Preserved **committee quorum persistence:** Committee quorum information now persists across restarts, which keeps governance state steadier after interruptions.
22
+ * Opened **broader governance state handling:** Governance aware integrations can now read and handle more of the Conway governance state without losing important context.
23
+ * Unlocked **new Blockfrost compatible block endpoints:** Blockfrost compatible users can now retrieve additional block details through new block endpoints.
24
+ * Extended **new Blockfrost compatible network endpoints:** Network status integrations can now access new network endpoints in a Blockfrost compatible shape.
25
+ * Introduced **new Blockfrost compatible era endpoints:** Era aware clients can now request era information through new Blockfrost compatible endpoints.
26
+ * Added **new Blockfrost compatible genesis endpoints:** Genesis data is now available through new Blockfrost compatible endpoints for services that need network bootstrap details.
27
+
28
+ ### 💪 Improvements
29
+
30
+ * Improved **newer Mithril snapshot compatibility:** Bootstrap runs now accept newer snapshot shapes more reliably, which makes setup and recovery smoother across current Mithril data.
31
+ * Refined **interrupted Mithril resume safety:** Resuming after an interrupted Mithril run now behaves more safely, which reduces the chance of a broken recovery path.
32
+ * Enhanced **bootstrap aware peer governance:** Peer promotion and selection now align more closely with bootstrap state, which helps early sync keep useful peers active.
33
+ * Modernized **bootstrap and governance observability:** Operators can now see more metrics and event signals around bootstrap and governance behavior.
34
+ * Updated **operator and integrator guidance:** Documentation and workflow refreshes make recent bootstrap, governance, and API behavior easier to follow.
35
+
36
+ ### 🔧 Fixes
37
+
38
+ * Fixed **Mithril bootstrap resume reliability:** Mithril bootstrap and resume handling now recover more reliably when a previous run stopped before completion.
39
+ * Corrected **snapshot bootstrap handling:** Snapshot based bootstrap flows now handle current snapshot layouts correctly, which reduces failed setup paths.
40
+ * Hardened **early sync recovery behavior:** Recovery during early sync now follows Genesis mode chain selection and bootstrap aware promotion more safely after interruptions.
41
+ * Stabilized **governance state continuity:** Governance state now keeps ratification, enactment, and committee quorum handling steadier across restarts and replay.
42
+
43
+ ### 📋 What You Need to Know
44
+
45
+ * Clarified **Genesis bootstrap rollout:** Ouroboros Genesis bootstrap changes early sync behavior, including Genesis mode chain selection and bootstrap aware peer promotion.
46
+ * Highlighted **governance support growth:** Conway governance coverage now reaches ratification, enactment, committee quorum persistence, and broader governance state handling.
47
+ * Emphasized **steadier Mithril recovery:** Mithril bootstrap and resume handling now work more reliably with newer snapshot shapes and safer interrupted resume behavior.
48
+ * Summarized **expanded Blockfrost compatibility:** Blockfrost compatible users can now use new block, network, era, and genesis endpoints.
49
+
50
+ ### 🙏 Thank You
51
+
52
+ Thank you for trying!
53
+
54
+ ---
55
+
56
+ ## v0.36.1 (April 21, 2026)
57
+
58
+ **Title:** Steadier catch-up sync and refreshed integrations
59
+
60
+ **Date:** April 21, 2026
61
+
62
+ **Version:** v0.36.1
63
+
64
+ Hi folks! Here’s what we shipped in v0.36.1.
65
+
66
+ ### 💪 Improvements
67
+
68
+ * Improved **catch-up sync stability:** Nodes now stay steadier while catching up because stall checks wait longer, plateau recovery allows more time, and recycle cooldowns stay longer until the node reaches tip, which reduces unnecessary connection recycling and socket churn during large syncs.
69
+ * Updated **AWS integration currency:** AWS backed integrations stay current because the AWS SDK config package and related AWS modules were refreshed.
70
+ * Refreshed **core AWS compatibility:** AWS integrated behavior stays aligned with upstream fixes because the core AWS SDK and `aws/smithy-go` were updated.
71
+ * Modernized **Google API client support:** Google API client support stays current because `google.golang.org/api` now uses a newer release.
72
+
73
+ ### 🙏 Thank You
74
+
75
+ Thank you for trying!
76
+
77
+ ---
78
+
4
79
  ## v0.36.0 (April 20, 2026)
5
80
 
6
81
  **Title:** Asset endpoints and steadier chain operations
@@ -4,11 +4,13 @@
4
4
  # runtime default.
5
5
 
6
6
  # Public bind address for the Dingo server
7
+ # CLI: --bind-addr
7
8
  bindAddr: "0.0.0.0"
8
9
 
9
10
  # Path to the Cardano node configuration file
10
11
  #
11
12
  # Can be overridden with the config environment variable
13
+ # CLI: --cardano-config
12
14
  cardanoConfig: "./config/cardano/preview/config.json"
13
15
 
14
16
  # Global data directory for both blob and metadata storage plugins.
@@ -110,9 +112,11 @@ database:
110
112
  dsn: ""
111
113
 
112
114
  # Path to the UNIX domain socket file used by the server
115
+ # CLI: --socket-path
113
116
  socketPath: "dingo.socket"
114
117
 
115
118
  # Name of the Cardano network
119
+ # CLI: --network
116
120
  network: "preview"
117
121
 
118
122
  # TLS certificate file path (for HTTPS)
@@ -129,17 +133,20 @@ tlsKeyFilePath: ""
129
133
  topology: ""
130
134
 
131
135
  # TCP port to bind for Prometheus metrics endpoint
136
+ # CLI: --metrics-port
132
137
  metricsPort: 12798
133
138
 
134
139
  # Internal/private address to bind for listening for Ouroboros NtC
135
140
  privateBindAddr: "127.0.0.1"
136
141
 
137
142
  # TCP port to bind for listening for Ouroboros NtC
143
+ # CLI: --private-port
138
144
  privatePort: 3002
139
145
 
140
146
  # TCP port to bind for listening for Ouroboros NtN
141
147
  #
142
148
  # Can be overridden with the port environment variable
149
+ # CLI: --port
143
150
  relayPort: 3001
144
151
 
145
152
  # Storage mode controls how much data is persisted.
@@ -149,6 +156,7 @@ relayPort: 3001
149
156
  # redeemers). All APIs start automatically on their default ports.
150
157
  #
151
158
  # Can be overridden with DINGO_STORAGE_MODE
159
+ # CLI: --storage-mode
152
160
  storageMode: "core"
153
161
 
154
162
  # API ports — only used when storageMode is "api".
@@ -157,15 +165,19 @@ storageMode: "core"
157
165
  #
158
166
  # UTxO RPC gRPC API port (default: 9090)
159
167
  # Can be overridden with DINGO_UTXORPC_PORT
168
+ # CLI: --utxorpc-port
160
169
  utxorpcPort: 9090
161
170
  # Blockfrost-compatible REST API port (default: 3000)
162
171
  # Can be overridden with DINGO_BLOCKFROST_PORT
172
+ # CLI: --blockfrost-port
163
173
  blockfrostPort: 3000
164
174
  # Mesh (Coinbase Rosetta) REST API port (default: 8080)
165
175
  # Can be overridden with DINGO_MESH_PORT
176
+ # CLI: --mesh-port
166
177
  meshPort: 8080
167
178
 
168
179
  # base url of bark archive server
180
+ # CLI: --bark-url
169
181
  barkBaseUrl: ""
170
182
 
171
183
  # number of slots from tip within which blocks
@@ -173,6 +185,7 @@ barkBaseUrl: ""
173
185
  barkSecurityWindow: 10000
174
186
 
175
187
  # TCP port bind for listening for bark RPC calls
188
+ # CLI: --bark-port
176
189
  barkPort: 0
177
190
 
178
191
  # ---
@@ -218,6 +231,7 @@ intersectTip: false
218
231
  # Maximum total size (in bytes) of all transactions allowed in the mempool.
219
232
  # Transactions exceeding this limit will be rejected.
220
233
  # Default: 1048576 (1 MB)
234
+ # CLI: --mempool-capacity
221
235
  mempoolCapacity: 1048576
222
236
 
223
237
  # Forging tolerances (0 = defaults)
@@ -234,12 +248,14 @@ forgeStaleGapThresholdSlots: 0
234
248
  # Note: CLI commands (serve, load) take priority over this setting
235
249
  #
236
250
  # Can be overridden with the DINGO_RUN_MODE environment variable
251
+ # CLI: --run-mode
237
252
  runMode: "serve"
238
253
 
239
254
  # Path to ImmutableDB for batch import (used when runMode is "load")
240
255
  # Can also be provided as argument to 'dingo load' command
241
256
  #
242
257
  # Can be overridden with the DINGO_IMMUTABLE_DB_PATH environment variable
258
+ # CLI: --immutable-db-path
243
259
  immutableDbPath: ""
244
260
 
245
261
  # Validate historical blocks during ledger processing (default: false)
@@ -251,10 +267,13 @@ validateHistorical: false
251
267
  # Default: known=150, established=50, active=20
252
268
  #
253
269
  # Target number of known (cold) peers
270
+ # CLI: --target-known-peers
254
271
  targetNumberOfKnownPeers: 0
255
272
  # Target number of established (warm) peers
273
+ # CLI: --target-established-peers
256
274
  targetNumberOfEstablishedPeers: 0
257
275
  # Target number of active (hot) peers
276
+ # CLI: --target-active-peers
258
277
  targetNumberOfActivePeers: 0
259
278
 
260
279
  # Per-source quotas for active peers
@@ -269,11 +288,52 @@ activePeersGossipQuota: 0
269
288
  # Active peer slots for ledger sources
270
289
  activePeersLedgerQuota: 0
271
290
 
291
+ # Inbound peer governance budget (phase 1)
292
+ # These define explicit operator intent for inbound peers as a governed source.
293
+ # Current behavior remains conservative; these values are surfaced in metrics and
294
+ # quota/status output to make inbound policy visible.
295
+ #
296
+ # Target number of inbound peers to keep in warm state.
297
+ # CLI: --inbound-warm-target
298
+ inboundWarmTarget: 0
299
+ # Quota for inbound peers in hot state.
300
+ # CLI: --inbound-hot-quota
301
+ inboundHotQuota: 0
302
+ # Minimum tenure before inbound peers are eligible for hot promotion.
303
+ # CLI: --inbound-min-tenure
304
+ inboundMinTenure: 0s
305
+ # Minimum score threshold for inbound hot promotion.
306
+ # CLI: --inbound-hot-score-threshold
307
+ inboundHotScoreThreshold: 0
308
+ # Future prune grace window for inbound peers.
309
+ # CLI: --inbound-prune-after
310
+ inboundPruneAfter: 0s
311
+ # Future duplex policy knob for inbound peers.
312
+ # CLI: --inbound-duplex-only-for-hot
313
+ inboundDuplexOnlyForHot: false
314
+ # Future cooldown knob for inbound peer governance actions.
315
+ # CLI: --inbound-cooldown
316
+ inboundCooldown: 0s
317
+
318
+ # Genesis bootstrap configuration
319
+ # Used only for from-origin sync. Default behavior keeps this enabled and
320
+ # exits Genesis mode automatically near the best known peer tip.
321
+ genesisBootstrap:
322
+ # Enable/disable Genesis bootstrap mode (default: true).
323
+ enabled: true
324
+ # Override the Genesis comparison window in slots.
325
+ # 0 auto-derives the window from genesis params (3k/f).
326
+ windowSlots: 0
327
+ # Minimum diversity groups to prefer while promoting peers during bootstrap.
328
+ # 0 uses the peer-governor default.
329
+ promotionMinDiversityGroups: 0
330
+
272
331
  # Cache configuration for tiered CBOR cache system
273
332
  # This controls the in-memory caching of UTxO and transaction CBOR data
274
333
  cache:
275
334
  # Number of entries in the hot UTxO cache (LFU eviction)
276
335
  # Default: 50000
336
+ # CLI: --cache-hot-utxo-entries
277
337
  hotUtxoEntries: 50000
278
338
  # Number of entries in the hot transaction cache (LFU eviction)
279
339
  # Default: 10000
@@ -283,16 +343,19 @@ cache:
283
343
  hotTxMaxBytes: 268435456
284
344
  # Number of blocks to keep in the block LRU cache
285
345
  # Default: 500
346
+ # CLI: --cache-block-lru-entries
286
347
  blockLruEntries: 500
287
348
  # Number of recent blocks to warm up on startup
288
349
  # Default: 1000
289
350
  warmupBlocks: 1000
290
351
  # Wait for cache warmup to complete before serving requests
291
352
  # Default: true
353
+ # CLI: --cache-warmup-sync
292
354
  warmupSync: true
293
355
 
294
356
  # Mithril snapshot bootstrap configuration
295
357
  # Use 'dingo mithril sync' or 'dingo sync --mithril' to bootstrap from a snapshot
358
+ # CLI: --mithril-enabled, --mithril-verify-certs
296
359
  mithril:
297
360
  # Enable Mithril integration (default: true)
298
361
  enabled: true
@@ -0,0 +1,188 @@
1
+ # Dingo Grafana Dashboards
2
+
3
+ Monitoring dashboards for [Dingo](https://github.com/blinklabs-io/dingo), the Go Cardano node by Blink Labs.
4
+
5
+ ## Dashboards
6
+
7
+ | Dashboard | File | Description |
8
+ |-----------|------|-------------|
9
+ | **Node Overview** | `node-overview.json` | At-a-glance header (epoch, slot, tip gap, density, blockfetch, mempool, KES, peers, storage, runtime), block height, epoch progress, forging stats |
10
+ | **Block Production** | `block-production.json` | Forge latency heatmap, block delay CDFs, forge rates, KES lifecycle |
11
+ | **Peer Health** | `peer-health.json` | Hot/warm/cold peers, connection types, peer state timeseries, promotions/demotions, network I/O |
12
+ | **Mempool** | `mempool.json` | Pending TXs, mempool size, TX lifecycle, CBOR cache, event bus |
13
+ | **Resource Usage** | `resources.json` | CPU, memory, GC heatmap, disk I/O, IOPS, PSI pressure, Badger, file descriptors |
14
+
15
+ `full-panel.json` contains the standalone Business Text header panel for embedding into custom dashboards.
16
+
17
+ ## Prerequisites
18
+
19
+ Before you begin, make sure you have:
20
+
21
+ - **Grafana 12+** (tested on 12.4) — [install guide](https://grafana.com/docs/grafana/latest/setup-grafana/installation/)
22
+ - **Prometheus** scraping your Dingo node on port `12798` (configured in step 2 below)
23
+ - **Dingo** node with metrics enabled (default port `12798`)
24
+ - **[Business Text plugin](https://grafana.com/grafana/plugins/marcusolsson-dynamictext-panel/)** — required by all dashboards for the header panel
25
+ - **[prometheus-node-exporter](https://github.com/prometheus/node_exporter)** — required only by the Resource Usage dashboard for host-level CPU, memory, and disk metrics
26
+
27
+ ## Quick start
28
+
29
+ ### 1. Install the Business Text plugin
30
+
31
+ Open a terminal on the machine running Grafana and run:
32
+
33
+ ```bash
34
+ grafana-cli plugins install marcusolsson-dynamictext-panel
35
+ sudo systemctl restart grafana-server
36
+ ```
37
+
38
+ If you are running Grafana in Docker or Kubernetes, set the environment variable instead:
39
+
40
+ ```text
41
+ GF_INSTALL_PLUGINS=marcusolsson-dynamictext-panel
42
+ ```
43
+
44
+ ### 2. Configure Prometheus scrape targets
45
+
46
+ Prometheus needs to know where to find your Dingo node. Add the following to your `prometheus.yml` under `scrape_configs`:
47
+
48
+ ```yaml
49
+ - job_name: dingo
50
+ scrape_interval: 15s
51
+ static_configs:
52
+ - targets: ['localhost:12798']
53
+
54
+ # Optional: required for Resource Usage dashboard
55
+ - job_name: node
56
+ scrape_interval: 15s
57
+ static_configs:
58
+ - targets: ['localhost:9100']
59
+ ```
60
+
61
+ Then reload Prometheus to apply the change:
62
+
63
+ ```bash
64
+ sudo systemctl reload prometheus
65
+ ```
66
+
67
+ ### 3. Import dashboards
68
+
69
+ There are two ways to get the dashboards into Grafana.
70
+
71
+ **Option A: Provisioning (recommended)**
72
+
73
+ Provisioning automatically loads dashboards from files on disk. Grafana will pick them up on startup or within about 30 seconds if already running.
74
+
75
+ ```bash
76
+ sudo cp docs/dashboards/provisioning.yaml /etc/grafana/provisioning/dashboards/dingo.yaml
77
+ sudo mkdir -p /var/lib/grafana/dashboards/dingo
78
+ sudo cp docs/dashboards/*.json /var/lib/grafana/dashboards/dingo/
79
+ sudo chown -R grafana:grafana /var/lib/grafana/dashboards/dingo/
80
+ sudo systemctl restart grafana-server
81
+ ```
82
+
83
+ After restarting, go to **Dashboards → Browse** in the Grafana UI and search for "Dingo". All five dashboards appear in a **Dingo** folder automatically.
84
+
85
+ **Note:** `allowUiUpdates: true` lets you edit dashboards in the Grafana UI, but changes will be overwritten on the next provision cycle (every 30 seconds). To make permanent edits, modify the JSON files directly.
86
+
87
+ **Option B: Manual import**
88
+
89
+ 1. Open Grafana in your browser
90
+ 2. Go to **Dashboards → New → Import**
91
+ 3. Upload each JSON file
92
+ 4. Select your Prometheus datasource when prompted
93
+
94
+ ### 4. Alert rules (optional)
95
+
96
+ The alert rules file is ready to use as-is — no editing required.
97
+
98
+ Copy the file to your Prometheus rules directory:
99
+
100
+ ```bash
101
+ sudo cp docs/dashboards/alerts.yaml /etc/prometheus/rules/dingo.yaml
102
+ ```
103
+
104
+ Then add it to `prometheus.yml`:
105
+
106
+ ```yaml
107
+ rule_files:
108
+ - /etc/prometheus/rules/dingo.yaml
109
+ ```
110
+
111
+ Reload Prometheus:
112
+
113
+ ```bash
114
+ sudo systemctl reload prometheus
115
+ ```
116
+
117
+ ## Datasource
118
+
119
+ All dashboards expect a Prometheus datasource with UID `prometheus`. If your datasource has a different UID, update it before importing or recreate the datasource with UID `prometheus`.
120
+
121
+ ## Template variables
122
+
123
+ All dashboards include two template variables that auto-discover dingo instances:
124
+
125
+ | Variable | Query | Purpose |
126
+ |----------|-------|---------|
127
+ | `$network` | `label_values(dingo_build_info, network)` | Selects the Cardano network (`preview`, `preprod`, `mainnet`). |
128
+ | `$instance` | `label_values(dingo_build_info{network="$network"}, instance)` | Selects specific dingo instance(s). Multi-select with "All" default. |
129
+
130
+ `dingo_build_info` is a metric only dingo exposes (includes `network`, `version`, `commit` labels). This ensures dropdowns show only dingo targets, never Haskell cardano-node.
131
+
132
+ All panel queries use `{network="$network", instance=~"$instance"}` as their selector.
133
+
134
+ The **Resource Usage** dashboard adds a third variable:
135
+
136
+ | Variable | Query | Purpose |
137
+ |----------|-------|---------|
138
+ | `$node_instance` | `label_values(node_uname_info, instance)` | Selects the node_exporter target for host-level metrics (CPU, memory, disk, network). node_exporter runs on a different port (default `9100`) from the dingo metrics port, so it needs its own instance dropdown. |
139
+
140
+ Set `$node_instance` to the hostname/port reported by your node_exporter scrape target (typically `localhost:9100` or the host IP).
141
+
142
+ ## Navigation
143
+
144
+ Dashboard-level links at the top of each dashboard connect all 5 dashboards. Links preserve the selected time range and template variables.
145
+
146
+ ## Dormant metrics
147
+
148
+ Some metrics only emit when their feature is active. Panels display "No data" until activated:
149
+
150
+ | Metric | Activates when |
151
+ |--------|---------------|
152
+ | `cardano_node_metrics_Forge_node_is_leader_int` | Forging is enabled |
153
+ | `cardano_node_metrics_Forge_adopted_int` | Block is forged and adopted |
154
+ | `cardano_node_metrics_blockForgingLatency_seconds_bucket` | Block is forged |
155
+ | `cardano_node_metrics_remainingKESPeriods_int` | KES key is configured |
156
+ | `dingo_forge_tip_gap_slots` | Forging is enabled |
157
+ | `dingo_database_size_bytes` | Database stores are initialized |
158
+ | `database_blob_*` | Badger blob store is active |
159
+
160
+ ## File listing
161
+
162
+ ```text
163
+ docs/dashboards/
164
+ node-overview.json Node Overview dashboard
165
+ block-production.json Block Production dashboard
166
+ peer-health.json Peer Health dashboard
167
+ mempool.json Mempool dashboard
168
+ resources.json Resource Usage dashboard
169
+ full-panel.json Business Text header panel (standalone)
170
+ provisioning.yaml Grafana provisioning config
171
+ prometheus.yaml Prometheus scrape config snippet
172
+ alerts.yaml Prometheus alert rules
173
+ README.md This file
174
+ ```
175
+
176
+ ## Troubleshooting
177
+
178
+ **Business Text plugin not found / panels show "Panel plugin not found: marcusolsson-dynamictext-panel"**
179
+ Install the plugin (step 1 above) and restart Grafana. If running in a managed environment, add `marcusolsson-dynamictext-panel` to your `GF_INSTALL_PLUGINS` list.
180
+
181
+ **Panels show "No data"**
182
+ Check that Prometheus is scraping your Dingo node: open Prometheus in the browser, go to **Status → Targets**, and confirm the `dingo` job is up. Also verify the `$network` and `$instance` template variables at the top of the dashboard are set to the correct values.
183
+
184
+ **Datasource UID mismatch ("datasource not found")**
185
+ All JSON files use the datasource UID `prometheus`. If your Prometheus datasource has a different UID, either rename it to `prometheus` in **Connections → Data sources**, or do a find-and-replace of `"prometheus"` with your actual UID in the JSON files before importing.
186
+
187
+ **Dashboards not appearing after provisioning**
188
+ Confirm `/etc/grafana/provisioning/dashboards/dingo.yaml` references the correct path. Grafana auto-reloads provisioned dashboards every 30 seconds; if it hasn't appeared after a minute, check the Grafana log (`journalctl -u grafana-server`) for errors.
@@ -0,0 +1,29 @@
1
+ groups:
2
+ - name: dingo
3
+ rules:
4
+ - alert: DingoBlockStall
5
+ expr: changes(cardano_node_metrics_blockNum_int{network=~".+"}[5m]) == 0
6
+ for: 0m
7
+ labels:
8
+ severity: warning
9
+ annotations:
10
+ summary: "Dingo block height stalled on {{ $labels.network }}"
11
+ description: "Node {{ $labels.instance }} on {{ $labels.network }}: block height has not changed in 5 minutes."
12
+
13
+ - alert: DingoSlotDrift
14
+ expr: changes(cardano_node_metrics_slotNum_int{network=~".+"}[2m]) == 0
15
+ for: 0m
16
+ labels:
17
+ severity: warning
18
+ annotations:
19
+ summary: "Dingo slot counter stalled on {{ $labels.network }}"
20
+ description: "Node {{ $labels.instance }} on {{ $labels.network }}: slot counter has not advanced in 2 minutes."
21
+
22
+ - alert: DingoPeerLoss
23
+ expr: cardano_node_metrics_connectionManager_outgoingConns{network=~".+"} == 0
24
+ for: 5m
25
+ labels:
26
+ severity: critical
27
+ annotations:
28
+ summary: "Dingo has no outgoing peers on {{ $labels.network }}"
29
+ description: "Node {{ $labels.instance }} on {{ $labels.network }}: zero outgoing connections for 5+ minutes. Node cannot sync."
@@ -0,0 +1,16 @@
1
+ ## Prometheus scrape configuration for Dingo dashboards
2
+ ##
3
+ ## Add these jobs to your prometheus.yml under scrape_configs:
4
+
5
+ scrape_configs:
6
+ # Dingo node metrics (default port 12798)
7
+ - job_name: dingo
8
+ scrape_interval: 15s
9
+ static_configs:
10
+ - targets: ['localhost:12798']
11
+
12
+ # Node exporter for host-level metrics (required by Resource Usage dashboard)
13
+ - job_name: node
14
+ scrape_interval: 15s
15
+ static_configs:
16
+ - targets: ['localhost:9100']
@@ -0,0 +1,14 @@
1
+ apiVersion: 1
2
+
3
+ providers:
4
+ - name: dingo
5
+ orgId: 1
6
+ folder: Dingo
7
+ folderUid: dingo-dashboards
8
+ type: file
9
+ disableDeletion: false
10
+ updateIntervalSeconds: 30
11
+ allowUiUpdates: true
12
+ options:
13
+ path: /var/lib/grafana/dashboards/dingo
14
+ foldersFromFilesStructure: false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blinklabs/dingo",
3
- "version": "0.36.1",
3
+ "version": "0.38.0",
4
4
  "description": "Dingo is a Cardano blockchain data node",
5
5
  "main": "index.js",
6
6
  "bin": {