The sweep (main's item 1): 199 tracked text files, 783 lines. The founder's full name, first name and possessive become "the founder" (sentence starts capitalised); the lowercase operating-system user name in WSL paths and commands becomes <user>; the second owner login becomes "the second owner login"; the three earlier businesses and the two other brands become "the other business", "the earlier entity", "the earlier business" and "another brand"; the Chrome profile rule names the igneum.network profile, not the profile's label. The standing commit login igneum-labs is not a founder term here: the fresh-repository step renames it in the history (docs/plans/history-rewrite.md, tools/repo/fresh-repo.sh). The patterns never appear in plain text in the tree (a plaintext list would be the hit): tools/ci/founder-strings.b64 (perl regex, tab, a sample per row) is read by tools/ci/founder-strings-check.sh (every tracked text file, perl, known-failed first: the self-test plants each row's sample in a fixture and the hit must name the file), by tools/community/discord-hooks.mjs (the guard's founder and business rows; the test takes its fixtures from the samples) and by tools/repo/fresh-repo.sh (the business names of the rewrite rules). site/forbidden-strings.txt carries the same patterns as b64: lines, decoded case-insensitive by site/scrub.mjs and tools/ci/launch-gates-check.mjs (whose fixture now plants an encoded made-up name). The check runs in the gate's tree checks on every merge. Not in this commit, by main's word: the 105 commit messages and 40 personal-identity commits that need the history rewrite (listed, not run), and the secrets found by gitleaks over the history (reported with owners). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
96 lines
8 KiB
Markdown
96 lines
8 KiB
Markdown
# Seed nodes: plan
|
|
|
|
3 October 2026. Scripts in `infra/seed-nodes/`. The first seed is live.
|
|
|
|
## The first seed
|
|
|
|
| Item | Value |
|
|
|---|---|
|
|
| Name | igneum-seed-1 |
|
|
| Address | `188.245.5.161:26611` (Hetzner primary IPv4, auto-delete off, so a rebuilt server keeps it) |
|
|
| Provider, location, type | Hetzner Cloud, Falkenstein (fsn1), cx23 (2 Intel vCPU, 4 GB, 40 GB), Debian 12 |
|
|
| Cost | USD 6.49 per month net, USD 7.79 gross, USD 0.0104 per hour, 20 TB traffic included (Hetzner API, 3 Oct 2026); plus the primary IPv4, USD 0.60 per month net, 0.72 gross (pricing API). Total about USD 7.09 net, USD 8.51 gross per month. The account bills in USD: the pricing API reports `currency: USD`, VAT 20% |
|
|
| Firewall | inbound tcp 26611 from anywhere, tcp 22 from anywhere (the founder's instruction; `SSH_SOURCE=me` narrows it to this Mac's IP), icmp; RPC bound to 127.0.0.1 only |
|
|
| Network | the shared devnet (`--devnet`, no suffix), built from `vendor/igneum-node` HEAD d62708a8 plus the uncommitted finality v2 work and `igneum-pow` HEAD, with `--features igneum-pow` |
|
|
| Role | p2p open, no mining, address manager on (serves `RequestAddresses`), `--nodnsseed`, UPnP off, `--externalip` set |
|
|
| How the Mac reaches it | the Mac's live node sits behind NAT (192.168.68.64), so the seed cannot dial in; the Mac dials out. The `addPeer` RPC on the live node is refused ("Method unavailable in safe mode. Run the node with --unsaferpc"), so the working path is a relay: `infra/seed-nodes/addpeer-from-mac.sh relay start`, a second non-mining `igneumd` on the Mac (appdir /tmp/igneum-seed-relay, RPC 127.0.0.1:26680, wRPC 28680, p2p 127.0.0.1:26681) with `--addpeer=192.168.68.64:26611 --addpeer=188.245.5.161:26611`; it syncs from the live node and the seed syncs from it. The live node is untouched. When the live node is next restarted by hand, add `--addpeer=188.245.5.161:26611` to its flags and the relay is no longer needed |
|
|
|
|
`infra/seed-nodes/seeds.txt` holds exactly `188.245.5.161:26611`.
|
|
|
|
Verified 3 Oct 2026, 22:19 to 22:26 UTC: build on the VM 1,530 s (25.5 min, 2 vCPU, 2 jobs, 6 GB swap unused);
|
|
`igneumd/2.1.0` started with the finality v2 parameters, "External address is publicly routable 188.245.5.161:26611";
|
|
the relay on the Mac connected to it at once (protocol 12) and to the live node (protocol 11); the seed completed IBD
|
|
from the relay and reported `isSynced: true` at 22:25:39 UTC with 12,204 blocks and sink `a0a776bb129c...`, the same
|
|
block count and sink the live node reported in the same second. Peer exchange: without any configuration on their
|
|
side, the live node (`/kaspad:2.1.0/`, protocol 11) and the Windows PC's node (192.168.68.67, `/igneumd:2.1.0/`,
|
|
protocol 11) learned the seed's address from the relay and dialled it themselves; the live node's `getConnectedPeerInfo`
|
|
lists `188.245.5.161:26611` as an outbound peer, and the seed shows three inbound peers from the Mac's public IP.
|
|
`health.sh`: `OK igneum-seed-1 188.245.5.161 p2p=open unit=active rpc=yes synced=True blocks=12204 headers=12204 peers=3`.
|
|
The seed's own known-address table is empty because all three peers are behind NAT with no routable advertised address;
|
|
the first public node that connects will populate it.
|
|
|
|
## How the seed list reaches clients
|
|
|
|
1. Baked into the node. `vendor/igneum-node/consensus/core/src/config/params.rs` holds the per-network seed list as
|
|
`dns_seeders: &'static [&'static str]` on `Params`: `MAINNET_PARAMS` (line 617 on 3 Oct 2026), `TESTNET_PARAMS`
|
|
(670), `SIMNET_PARAMS` (721), `DEVNET_PARAMS` (785), all `&[]` since the rename commit emptied Kaspa's nine mainnet
|
|
and three testnet hostnames. The connection manager resolves each entry with `(seeder, default_p2p_port).to_socket_addrs()`
|
|
(`components/connectionmanager/src/lib.rs`, `dns_seed_single`), so a plain IPv4 literal works as an entry with no
|
|
DNS at all: `dns_seeders: &["188.245.5.161"]` on `DEVNET_PARAMS` is the whole change for the devnet, and the
|
|
testnet list is the same shape with the testnet seeds. The port is the network's default p2p port (devnet 26611;
|
|
the testnet port is still Kaspa's and must be set with the testnet genesis). The consensus engineer owns this edit.
|
|
Two consequences for packages: a client that passes `--nodnsseed` ignores the baked list (`kaspad/src/daemon.rs`
|
|
line 573: `dns_seeders` is emptied when `--nodnsseed` or `--connect` is given), so the Windows node package
|
|
(`proto-cuda/windows-node/start-node.ps1`) and the cloud scripts must drop `--nodnsseed` once the list is baked;
|
|
and the list is consulted only when the node is short of outbound peers, so a node with enough `--addpeer`
|
|
entries never asks a seed.
|
|
2. `SEED_PEERS` override in every package. Each launcher (Windows node, cloud devnet, seed nodes, the observer's
|
|
helper node) reads `SEED_PEERS` (comma-separated `ip:port`) and turns every entry into `--addpeer=<entry>`; the
|
|
baked list is the default when the variable is empty. This is what an operator uses when the baked list is stale
|
|
between releases.
|
|
3. DNS names only as a convenience. `seed1.igneum.network` and so on can point at the same addresses (the domains
|
|
are on Vercel nameservers, so a record each), and `dns_seeders` accepts a hostname too; but the IPs are the source
|
|
of truth because a DNS failure or a registrar problem must not stop bootstrapping, and because the public key of
|
|
nothing is involved: a seed only hands out addresses, it cannot forge blocks.
|
|
|
|
## Public testnet seed set
|
|
|
|
Three to five seeds across two providers and three regions. Proposed:
|
|
|
|
| Seed | Provider | Location | Type | Per month net |
|
|
|---|---|---|---|---|
|
|
| igneum-seed-1 | Hetzner | Falkenstein (EU) | cx23 | USD 6.49 (live) |
|
|
| igneum-seed-2 | Hetzner | Ashburn (US east) | cpx11 (2 GB) or cpx21 (4 GB) | USD 20.49 or 37.49 |
|
|
| igneum-seed-3 | DigitalOcean | Singapore (sgp1) | s-2vcpu-4gb | USD 24 (DO pricing page) |
|
|
| igneum-seed-4 (optional) | DigitalOcean | New York or Frankfurt | s-2vcpu-4gb | USD 24 |
|
|
| igneum-seed-5 (optional) | Hetzner | Helsinki | cx23 | USD 6.49 |
|
|
|
|
Three seeds: about USD 50 per month; five: about USD 80 (approximate, mixed currencies). The US seed is the expensive
|
|
one because Hetzner's current cx line is EU-only. Every seed is created with `create-seed.sh` (the DigitalOcean
|
|
variant reserves an IP in the same way) and provisioned with `provision-seed.sh`, which adds the seeds already in
|
|
`seeds.txt` as `--addpeer` entries so the seeds form a full mesh among themselves. `health.sh` checks them all.
|
|
|
|
## Rotation
|
|
|
|
1. Add before removing: create and provision the replacement, run `health.sh` until it is synced and has peers.
|
|
2. Bake the new list (`params.rs`) and release packages with it; keep the old address in the list for one release so
|
|
clients on the previous build still bootstrap.
|
|
3. Keep the old IP alive until the release after that (a Hetzner primary IP or a DO reserved IP costs under USD 1 per
|
|
month unattached, approximate), then delete the server and the IP, and remove the entry from `seeds.txt` and
|
|
`seeds.tsv`.
|
|
4. A compromised seed is the one case to remove first: delete the server, release the IP, bake and release the same
|
|
day. The damage a bad seed can do is bounded (it hands out addresses; the node's handshake and PoW checks are
|
|
unchanged), which is why the list may sit in a release rather than behind a signature.
|
|
|
|
## Health and operations
|
|
|
|
`health.sh` (one line per seed: p2p port reachable from the Mac, unit active, RPC answering, synced, blocks and
|
|
headers, connected peers, known and banned addresses, disk, memory, version); `--watch` repeats every minute. The
|
|
seed's journal: `ssh -i ~/.ssh/igneum_ed25519 root@188.245.5.161 journalctl -u igneumd -f`. Updating the binary:
|
|
`provision-seed.sh` again (it rebuilds on the VM) or `BUILD_WHERE=bin` to push a binary built by the cloud-devnet
|
|
builder. The database format changes with some fork commits; a seed that refuses to start after an update is wiped
|
|
(`rm -rf /var/lib/igneum/*`) and resyncs from its peers.
|
|
|
|
## No-spend rule
|
|
|
|
Only the first seed spends tonight (approved). The remaining seeds and the 20-node network wait for the morning.
|