@blinklabs/dingo 0.36.1 → 0.37.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,29 @@
1
1
  # Release Notes
2
2
 
3
3
 
4
+ ## v0.36.1 (April 21, 2026)
5
+
6
+ **Title:** Steadier catch-up sync and refreshed integrations
7
+
8
+ **Date:** April 21, 2026
9
+
10
+ **Version:** v0.36.1
11
+
12
+ Hi folks! Here’s what we shipped in v0.36.1.
13
+
14
+ ### 💪 Improvements
15
+
16
+ * 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.
17
+ * Updated **AWS integration currency:** AWS backed integrations stay current because the AWS SDK config package and related AWS modules were refreshed.
18
+ * Refreshed **core AWS compatibility:** AWS integrated behavior stays aligned with upstream fixes because the core AWS SDK and `aws/smithy-go` were updated.
19
+ * Modernized **Google API client support:** Google API client support stays current because `google.golang.org/api` now uses a newer release.
20
+
21
+ ### 🙏 Thank You
22
+
23
+ Thank you for trying!
24
+
25
+ ---
26
+
4
27
  ## v0.36.0 (April 20, 2026)
5
28
 
6
29
  **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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blinklabs/dingo",
3
- "version": "0.36.1",
3
+ "version": "0.37.0",
4
4
  "description": "Dingo is a Cardano blockchain data node",
5
5
  "main": "index.js",
6
6
  "bin": {