Before you can write Go code that talks to a Cardano node, you need a working example to stand on. The gOuroboros Starter Kit gives you exactly that: a single Go module containing seven small programs, each demonstrating one Ouroboros mini-protocol against a real node. In this lesson, you clone it, wire it up to your Dolos instance, and confirm one of the programs runs end-to-end.
Once this is working, the rest of Module 101 is just picking the right program for the question you want to answer.
What the Starter Kit Gives You
The repository is a normal Go module with one binary per cmd/ subdirectory. Each one is a single main.go you can read top-to-bottom in a few minutes:
Command
Ouroboros mini-protocol
What it answers
chain-tip
ChainSync (NtC)
Where is the chain right now?
chain-sync
ChainSync + BlockFetch
Stream blocks forward from a point
block-fetch
BlockFetch (NtN)
Give me this specific block
tx-monitor
LocalTxMonitor (NtC)
What's in the mempool?
tx-submission
LocalTxSubmission (NtC)
Submit this signed transaction
state-query
LocalStateQuery (NtC)
Query current ledger state
ping
Handshake
How long does a round-trip take?
peer-sharing
PeerSharing (NtN)
What peers does this node know?
All of them import github.com/blinklabs-io/gouroboros. You will use four of these in Module 101 (chain-tip, chain-sync, block-fetch, tx-monitor) and a fifth in Module 102 (tx-submission).
What You're Connecting To
The starter-kit needs a Cardano node to talk to. You have three options, each speaking the same Ouroboros protocol family:
Option
What it is
When to use it
Dolos (Rust)
Lightweight data node by TxPipe — maintains a local chain copy and serves Ouroboros over a Unix socket
The course default, set up in 099 — fastest path to a working local node
Dingo (Go)
All-Go Cardano data node by Blink Labs, built on top of gOuroboros itself
When you want a pure-Go stack; note it is still under active development, with Plutus V1/V2 validation not yet complete
Public relay (TCP)
Any community-run Cardano relay on the internet
When you want to skip local infrastructure entirely — works for NtN programs like block-fetch and peer-sharing
This lesson targets Dolos because it's already in your stack from 099. Everything below works the same way if you swap in Dingo (same Ouroboros socket, same protocols) — just point CARDANO_NODE_SOCKET_PATH at Dingo's socket instead. The public-relay path shows up naturally in 101.2 when we reach block-fetch.
Prerequisites
- Go 1.24+ installed (
go versionto check) - Git
- A running Dolos instance on preprod (see 099 — Setting Up Dolos). If you're running Dingo instead, the same instructions apply — substitute its socket path.
- Your socket path and
network_magicfromdolos.toml(or Dingo's equivalent config)
Step 1: Clone the Repository
git clone https://github.com/blinklabs-io/gouroboros-starter-kit
cd gouroboros-starter-kit
go mod download
Look at the layout:
cmd/
block-fetch/main.go
chain-sync/main.go
chain-tip/main.go
peer-sharing/main.go
ping/main.go
state-query/main.go
tx-monitor/main.go
tx-submission/main.go
go.mod
go.sum
Each directory is a self-contained program. You run any of them with go run ./cmd/<name>.
Step 2: Understand How the Programs Read Configuration
All NtC programs in the kit read the node connection from environment variables using github.com/kelseyhightower/envconfig. The pattern is the same across commands — here's the relevant block from cmd/chain-tip/main.go:
type Config struct {
Magic uint32
SocketPath string `split_words:"true"`
Address string
}
func main() {
cfg := Config{
Magic: 764824073, // mainnet
SocketPath: "/ipc/node.socket",
}
if err := envconfig.Process("cardano_node", &cfg); err != nil {
panic(err)
}
// ...
}
envconfig.Process("cardano_node", &cfg) reads environment variables prefixed with CARDANO_NODE_. So:
CARDANO_NODE_MAGIC=1→cfg.Magic = 1CARDANO_NODE_SOCKET_PATH=/path/to/dolos.socket→cfg.SocketPathCARDANO_NODE_ADDRESS=host:port→cfg.Address(used for NtN)
That means you never need to edit source files. You export two variables and the whole kit points at your Dolos instance.
Step 3: Point the Kit at Dolos
Find your values in dolos.toml:
[serve.ouroboros]
listen_path = "dolos.socket"
[upstream]
network_magic = 1
Then in the terminal where you'll run the starter-kit:
export CARDANO_NODE_SOCKET_PATH=/absolute/path/to/your/dolos/dolos.socket
export CARDANO_NODE_MAGIC=1
Verify the socket file actually exists (Dolos must be running — dolos daemon in a separate terminal):
ls -l "$CARDANO_NODE_SOCKET_PATH"
You should see a srw- permission string indicating a Unix socket.
Step 4: Run chain-tip
The simplest program. It opens a connection, asks the node for the current chain tip, prints it, and exits.
go run ./cmd/chain-tip
Expected output:
Chain Tip:
Slot: 56123456 Block Hash: e3f1a2...
If you see numbers that keep matching whatever Cardanoscan preprod shows, your Dolos + gOuroboros loop is working end-to-end.
What Just Happened (Under the Hood)
your Go program Dolos Cardano network
───────────────── ───── ────────────────
ouroboros.NewConnection
│
│ Dial("unix", socketPath)
├─────────────────────────────>│
│ handshake (NtC) │ (already connected via NtN)
│<─────────────────────────────┤
│ │
│ ChainSync.GetCurrentTip() │
├─────────────────────────────>│
│ │ local query, no network hop
│<─────── Point{slot, hash} ───┤
│
fmt.Printf(...)
Two things worth noticing:
- NtC vs NtN.
chain-tipuses Node-to-Client over a Unix socket (Dolos is the "node" here). Other programs likeblock-fetchandpeer-sharinguse Node-to-Node over TCP and connect to a public relay directly. Both modes are gOuroboros features. - Nothing is long-running.
chain-tipprints once and exits.chain-syncstreams. Each program picks the right lifetime for its mini-protocol.
Common Issues
dial unix ...: connect: no such file or directory
Dolos isn't running, or CARDANO_NODE_SOCKET_PATH is wrong. ls the path literally to confirm.
handshake failed: refused, reason: ...
Usually a network-magic mismatch. Check CARDANO_NODE_MAGIC=1 (for preprod) matches [upstream] network_magic in dolos.toml.
go: cannot find main module
You ran go run from the wrong directory. All go run ./cmd/<name> invocations assume you're at the root of the starter-kit repo (the directory containing go.mod).
Tip prints but is hours behind
Dolos is still syncing. Run dolos daemon in the foreground and watch its log — the slot number should advance quickly until it reaches the live chain.
You'll Know You're Successful When
go run ./cmd/chain-tipprints a recent slot and block hash- The slot number matches the current preprod tip (within a few blocks) on Cardanoscan
- You can re-run the command and see the slot advance
Practice Tasks
- Run
chain-tipthree times with a few seconds between each. Note how the slot advances — this is the chain in motion. - Try overriding one variable on a single command:
CARDANO_NODE_MAGIC=2 go run ./cmd/chain-tip. Observe the handshake error. This is the guardrail working. - Read
cmd/chain-tip/main.gotop-to-bottom (~100 lines). Identify the two mini-protocol calls:NewConnectionandGetCurrentTip.
What's Next
- 101.2 — fetch a specific historical block with
block-fetch - 101.3 — check node sync progress with
chain-tipandchain-sync -tip - 101.4 — inspect the mempool with
tx-monitor
Each of the remaining Module 101 lessons uses the same starter-kit you just set up. No more cloning needed.