This is a docs-only seed. Tomorrow's session will add the actual Go source: main.go, internal/rpc/client.go (JSON-RPC + cookie auth), internal/chain/, internal/explorer/ (handlers), and internal/view/ (templates + static assets, embed.FS). Until then this commit gives the repo its shape: README with the full design, config example with all knobs, MIT license to match the chain, and a .gitignore for Go build artifacts.
5.8 KiB
CAC3 Explorer
A Go single-binary block explorer for CAC3 (Californiacoin3).
Reads from a running cac3d node over its JSON-RPC interface (Bitcoin Core 0.18 style — cookie auth).
What it shows
- Home / chain tip — current height, best block hash, difficulty, network hashrate, mempool size, last 10 blocks
- Block detail — by height or hash; full header, transactions, next/prev navigation
- Transaction detail — by txid; inputs/outputs with script-decoded addresses, value, confirmations
- Address detail — balance, total received/sent, UTXO list, recent tx history
- Mempool — current tx pool with fee/sat-per-byte sort
Why Go
- One statically-linked binary — no runtime, no node_modules, no Python deps
- Cold start ~30ms, idle RSS ~15MB
- Embeds templates + static assets via
embed.FS— single artifact deploy - Native HTTP/2, easy
systemdintegration, fits the same deployment shape as DashCaddy / Triangles
Quick start
1. Build
go build -ldflags="-s -w" -o cac3-explorer .
# or with a version stamp
go build -ldflags="-s -w -X main.Version=$(git describe --tags --always)" -o cac3-explorer .
Static binary, no glibc dep, runs anywhere.
2. Configure
The explorer reads config from (in priority order):
- Flags (
--rpc-url,--cookie-path,--listen, etc.) - Env vars (
CAC3_RPC_URL,CAC3_COOKIE_PATH,CAC3_LISTEN, …) config.yamlin the working directory
Example config.yaml:
listen: "0.0.0.0:8080"
rpc:
url: "http://127.0.0.1:8332"
cookie_path: "/var/lib/cac3/.cookie"
# OR static creds (less secure, but useful for testing):
# user: "cac3rpc"
# pass: "changeme"
timeout: "10s"
chain:
name: "CAC3 Mainnet"
ticker: "CAC3"
# site URL used in <link rel="canonical"> / OG tags
site_url: "https://explorer.cac3.example"
# Address-link overrides — point these at your public node, block explorers, etc.
links:
# tx / address / block pages can deep-link to external tools if set
# wallet: "https://wallet.cac3.example"
3. Run
./cac3-explorer --config config.yaml
# or fully env-var driven
CAC3_RPC_URL=http://127.0.0.1:8332 \
CAC3_COOKIE_PATH=/var/lib/cac3/.cookie \
CAC3_LISTEN=0.0.0.0:8080 \
./cac3-explorer
Open http://localhost:8080.
4. systemd (optional)
# /etc/systemd/system/cac3-explorer.service
[Unit]
Description=CAC3 Block Explorer
After=network.target cac3d.service
Wants=cac3d.service
[Service]
Type=simple
User=cac3-explorer
Group=cac3-explorer
WorkingDirectory=/opt/cac3-explorer
ExecStart=/opt/cac3-explorer/cac3-explorer --config /etc/cac3-explorer/config.yaml
Restart=on-failure
RestartSec=5s
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=/var/log/cac3-explorer
[Install]
WantedBy=multi-user.target
RPC surface used
The explorer only needs a non-wallet cac3d node (no wallet.dat required, no signing keys).
Methods called:
| Method | Used for |
|---|---|
getblockchaininfo |
tip, difficulty, chainwork |
getnetworkinfo |
protocol version, connections |
getmininginfo |
hashrate, blocks |
getmempoolinfo |
mempool size, bytes |
getrawmempool |
mempool txid list |
getblockhash |
height → hash |
getblock |
block header + tx list (verbose=1) |
getblockheader |
header only |
getrawtransaction |
tx hex by txid |
decoderawtransaction |
decode inputs/outputs |
gettxoutsetinfo |
total supply stats |
getconnectioncount |
peer count |
getdifficulty |
current difficulty (decimal) |
listsinceblock |
recent wallet-scoped activity (only if --show-wallet enabled) |
No sendtoaddress, no signing, no key access. Safe to expose the RPC port on a private interface (or behind SSH tunnel) — the explorer's only attack surface is the read path.
Repo layout
.
├── main.go # entrypoint, config, signal handling
├── internal/
│ ├── rpc/ # cac3d JSON-RPC client + cookie auth
│ │ ├── client.go
│ │ ├── auth.go # cookie + userpass
│ │ └── types.go # raw RPC types
│ ├── chain/ # domain types (Block, Tx, Address, …)
│ │ └── types.go
│ ├── explorer/ # handlers
│ │ ├── home.go
│ │ ├── block.go
│ │ ├── tx.go
│ │ ├── address.go
│ │ └── mempool.go
│ └── view/ # templates + render
│ ├── templates/ # html/template files (embed.FS)
│ └── static/ # css, js, favicon (embed.FS)
├── config.example.yaml
├── go.mod
├── go.sum
├── LICENSE # MIT, matches the chain license
└── README.md
Security notes
- Cookie auth is preferred —
cac3drotates.cookieon every restart. Re-read on every request (cheap, file is ~1KB). - The explorer is read-only. It never sends
sendtoaddress/signrawtransaction/walletlock. To prove this, search the source for those method names — they should not appear. - Do not expose
cac3d's RPC port to the public internet. Bind it to127.0.0.1or a tailnet IP and let the explorer be the only public entry point. - The explorer binds to whatever
--listensays. Use a reverse proxy (Caddy / nginx) for TLS, rate limiting, and a real domain.
Development
# run with hot-reload (needs `air` or similar; not required)
go run .
# test
go test ./...
# vet / lint
go vet ./...
staticcheck ./... # if installed
The first request after cac3d start will be slow (RPC cold cache). Subsequent requests are <50ms for blocks, <200ms for address histories.
License
MIT — see LICENSE. This explorer is a separate project from the CAC3 chain code; it only depends on cac3d's documented JSON-RPC interface.