diff --git a/docs/plans/cloud-devnet.md b/docs/plans/cloud-devnet.md index 2287e920..c0b62b15 100644 --- a/docs/plans/cloud-devnet.md +++ b/docs/plans/cloud-devnet.md @@ -22,9 +22,9 @@ What it proves: What it does not prove: nothing about GPU hash rates (CPU miners), nothing at 1,000 miners, one evening of data. -Cost (Hetzner API prices of 3 Oct 2026, net): EUR 0.76 per hour for the 20 nodes at 4 per location (EUR 476 per -month if left running), or EUR 0.47 per hour EU-heavy; the builder VM about EUR 0.03 per hour for one hour. An evening -of six hours: about EUR 5. DigitalOcean variant: USD 0.71 per hour. Time to first block after "yes": about 25 minutes +Cost (Hetzner API prices of 3 Oct 2026, net): USD 0.76 per hour for the 20 nodes at 4 per location (USD 476 per +month if left running), or USD 0.47 per hour EU-heavy; the builder VM USD 0.0296 per hour for one hour. An evening +of six hours: about USD 5. DigitalOcean variant: USD 0.71 per hour. Time to first block after "yes": about 25 minutes (VM creation, a 10 to 25 minute build, install). Command sequence: `infra/cloud-devnet/README.md`, section "The command sequence". In short: `create.sh`, @@ -62,9 +62,9 @@ template. ## The go/no-go question for the project lead -Spend about EUR 5 and USD 2 to 4 tonight-to-tomorrow for (a) the first reorg-depth, propagation and partition numbers +Spend about USD 5 (Hetzner, billed in USD) and USD 2 to 4 (RunPod) tonight-to-tomorrow for (a) the first reorg-depth, propagation and partition numbers from a real multi-region network, which gate 3 needs and the simulator cannot give, and (b) the per-card hash rates and the three ASIC-resistance measurements (L2 cliff, inline ratio, recompile time) on 3060, 3090 and 4090, closing the measurement half of ledger items M1, M11 and M16 for those cards? If yes: `cd infra/cloud-devnet && ./create.sh` and `cd infra/gpu-bench && ./make-bundle.sh` are the two starting commands. If no: the scripts keep, nothing bills, -and the seed node stays at EUR 6.49 per month. +and the seed node stays at USD 6.49 per month. diff --git a/docs/plans/seed-nodes.md b/docs/plans/seed-nodes.md index 98dae621..4c0c9b23 100644 --- a/docs/plans/seed-nodes.md +++ b/docs/plans/seed-nodes.md @@ -9,14 +9,26 @@ | 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 | EUR 6.49 per month net, EUR 7.79 gross, EUR 0.0104 per hour, 20 TB traffic included (Hetzner API, 3 Oct 2026); plus the primary IPv4, about EUR 0.50 per month (approximate) | +| 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 project lead'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: `infra/seed-nodes/addpeer-from-mac.sh 188.245.5.161` (the `addPeer` RPC through grpcurl, permanent, no restart). If the live node is ever restarted by hand: `--addpeer=188.245.5.161:26611` | +| 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 @@ -47,13 +59,13 @@ 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 | EUR 6.49 (live) | -| igneum-seed-2 | Hetzner | Ashburn (US east) | cpx11 (2 GB) or cpx21 (4 GB) | EUR 20.49 or 37.49 | +| 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 | EUR 6.49 | +| igneum-seed-5 (optional) | Hetzner | Helsinki | cx23 | USD 6.49 | -Three seeds: about EUR 50 per month; five: about EUR 80 (approximate, mixed currencies). The US seed is the expensive +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. @@ -63,7 +75,7 @@ variant reserves an IP in the same way) and provisioned with `provision-seed.sh` 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 EUR 1 per +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 diff --git a/infra/cloud-devnet/README.md b/infra/cloud-devnet/README.md index 67ac93a3..6658ac03 100644 --- a/infra/cloud-devnet/README.md +++ b/infra/cloud-devnet/README.md @@ -38,25 +38,25 @@ over `/live` on the site (stop the Mac's observer first). `site/api/live.mjs` re ## Cost -Hetzner API prices for this project on 3 Oct 2026, net EUR per month, hourly billing (the API's `price_hourly`): +Hetzner API prices for this project on 3 Oct 2026, net USD per month, hourly billing (the API's `price_hourly`): | Location | Type | vCPU | RAM | Per month | Per hour | Note | |---|---|---|---|---|---|---| | fsn1, nbg1, hel1 | cx23 | 2 Intel | 4 GB | 6.49 | 0.0104 | the cheapest x86 type the project can create | | sin | cpx22 | 2 AMD | 4 GB | 30.99 | 0.0497 | cx not sold outside the EU | | ash, hil | cpx21 | 3 AMD | 4 GB | 37.49 | 0.0601 | the old cpx line, only still sold in the US; cpx11 (2 GB) is 20.49 | -| builder, any EU | cx43 | 8 Intel | 16 GB | about 20 | about 0.03 | deleted after the build (approximate: cx33 is 9.99, cx43 not priced in the check) | +| builder, any EU | cx43 | 8 Intel | 16 GB | 18.49 | 0.0296 | deleted after the build | -Plus about EUR 0.50 per month per primary IPv4 (approximate, Hetzner list price). VAT is added for a private +Plus USD 0.60 per month net per primary IPv4 (pricing API). The account bills in USD (the pricing API reports currency USD, VAT 20%); VAT is added for a private customer; the API's gross column is net x 1.2. | Mix | Nodes | Per month net | Per hour | An evening (6 h) | |---|---|---|---|---| -| 4 per location (default `REGIONS`) | 8 EU, 4 sin, 4 ash, 4 hil | EUR 476 | EUR 0.76 | about EUR 5 | -| EU-heavy (`REGIONS=hel1,fsn1,nbg1,hel1,fsn1,nbg1,hel1,ash,hil,sin`) | 14 EU, 2 sin, 2 ash, 2 hil | EUR 303 | EUR 0.47 | about EUR 3 | +| 4 per location (default `REGIONS`) | 8 EU, 4 sin, 4 ash, 4 hil | USD 476 | USD 0.76 | about USD 5 | +| EU-heavy (`REGIONS=hel1,fsn1,nbg1,hel1,fsn1,nbg1,hel1,ash,hil,sin`) | 14 EU, 2 sin, 2 ash, 2 hil | USD 303 | USD 0.47 | about USD 3 | | DigitalOcean `s-2vcpu-4gb` in any region (DO pricing page, USD 24/mo, 0.036/h) | 20 | USD 480 | USD 0.71 | about USD 4.50 | -The run is meant to last one evening, so the hourly column is the one that matters: well under EUR 10 all in, with +The run is meant to last one evening, so the hourly column is the one that matters: well under USD 10 all in, with the builder. Leaving the network up costs the monthly column. ## What each script does diff --git a/infra/cloud-devnet/config.sh b/infra/cloud-devnet/config.sh index 34d6fb08..da1678c5 100755 --- a/infra/cloud-devnet/config.sh +++ b/infra/cloud-devnet/config.sh @@ -13,13 +13,13 @@ DO_REGIONS="${DO_REGIONS:-lon1,fra1,nyc3,sfo3,sgp1}" # Instance size per location. The node holds up to four 256 MiB lottery caches (M15 cap), rocksdb and the CPU # miner's own 256 MiB cache, so 2 GB plans are too small. What this Hetzner project can create (API, 3 Oct 2026, net -# EUR per month): cx23 (2 Intel vCPU, 4 GB) 6.49 in fsn1/nbg1/hel1 only; cpx22 (2 AMD vCPU, 4 GB) 22.99 EU, 30.99 sin; +# USD per month): cx23 (2 Intel vCPU, 4 GB) 6.49 in fsn1/nbg1/hel1 only; cpx22 (2 AMD vCPU, 4 GB) 22.99 EU, 30.99 sin; # cpx21 (3 vCPU, 4 GB) 37.49 in ash/hil only (the old cpx line is deprecated in the EU and Singapore since Dec 2025); # cpx11 (2 GB) 20.49 in ash/hil. So: cx23 in Europe, cpx22 in Singapore, cpx21 in the US. SERVER_TYPE overrides all. TYPE_BY_LOCATION="${TYPE_BY_LOCATION:-fsn1=cx23,nbg1=cx23,hel1=cx23,sin=cpx22,ash=cpx21,hil=cpx21}" SERVER_TYPE="${SERVER_TYPE:-}" # empty = pick from TYPE_BY_LOCATION DO_SIZE="${DO_SIZE:-s-2vcpu-4gb}" -BUILDER_TYPE="${BUILDER_TYPE:-cx43}" # 8 Intel vCPU, 16 GB, EUR 0.03/h approximate, for the one-off node build (deleted afterwards) +BUILDER_TYPE="${BUILDER_TYPE:-cx43}" # 8 Intel vCPU, 16 GB, USD 0.0296/h, for the one-off node build (deleted afterwards) DO_BUILDER_SIZE="${DO_BUILDER_SIZE:-c-8}" IMAGE="${IMAGE:-debian-12}" DO_IMAGE="${DO_IMAGE:-debian-12-x64}" diff --git a/infra/cloud-devnet/create.sh b/infra/cloud-devnet/create.sh index e48d0db5..79f8ab0c 100755 --- a/infra/cloud-devnet/create.sh +++ b/infra/cloud-devnet/create.sh @@ -40,7 +40,7 @@ hetzner_prepare() { } hetzner_price() { - log "live price list for $1 (per location, EUR, excl. VAT):" + log "live price list for $1 (per location, USD, excl. VAT):" hcloud server-type describe "$1" 2>/dev/null | sed -n '/Pricings/,$p' | head -40 || true } @@ -111,9 +111,9 @@ done if [ "$PROVIDER" = digitalocean ]; then do_price "$TYPE"; else for t in $(for i in $(seq 1 "$N"); do type_for_location "$(region_of "$i")"; done | sort -u); do hetzner_price "$t"; done fi -log "cost at the Hetzner API prices of 3 Oct 2026 (net EUR per month: cx23 6.49 EU, cpx22 30.99 sin, cpx21 37.49 ash/hil):" -log " 20 nodes as 4 per location = 8 x 6.49 + 4 x 30.99 + 8 x 37.49 = EUR 476/mo, EUR 0.76/h; an evening of 6 h about EUR 5 plus the builder (about EUR 0.03/h)" -log " EU-heavy alternative REGIONS=hel1,fsn1,nbg1,hel1,fsn1,nbg1,hel1,ash,hil,sin (14 EU, 2 each elsewhere): about EUR 303/mo, EUR 0.47/h" +log "cost at the Hetzner API prices of 3 Oct 2026 (net USD per month: cx23 6.49 EU, cpx22 30.99 sin, cpx21 37.49 ash/hil):" +log " 20 nodes as 4 per location = 8 x 6.49 + 4 x 30.99 + 8 x 37.49 = USD 476/mo, USD 0.76/h; an evening of 6 h about USD 5 plus the builder (about USD 0.03/h)" +log " EU-heavy alternative REGIONS=hel1,fsn1,nbg1,hel1,fsn1,nbg1,hel1,ash,hil,sin (14 EU, 2 each elsewhere): about USD 303/mo, USD 0.47/h" log " DigitalOcean s-2vcpu-4gb: USD 24 per node per month (USD 0.036/h, DO pricing page): 20 nodes USD 480/mo, USD 0.71/h" confirm "create $N servers now (hourly billing starts)?" diff --git a/infra/cloud-devnet/experiments/analyze.py b/infra/cloud-devnet/experiments/analyze.py index c1211738..dcd96651 100644 --- a/infra/cloud-devnet/experiments/analyze.py +++ b/infra/cloud-devnet/experiments/analyze.py @@ -277,7 +277,7 @@ def bench_entry(d, nodes_file): ver = " ".join(open(os.path.join(d, "version.txt")).read().split()) if os.path.exists(os.path.join(d, "version.txt")) else "" regions = ", ".join("%s x %d" % (r, sum(1 for n in nodes if n["region"] == r)) for r in sorted({n["region"] for n in nodes})) lines = [f"## {date_txt}, cloud devnet: {len(nodes)} igneumd nodes across regions, CPU trickle miners, latency, partition and hash-rate steps (consensus-engineer)", "", - f"Machines: {len(nodes)} Hetzner Cloud VMs ({regions}; type cpx21 unless noted), Debian 12, chrony. Node: {ver}, built on a builder VM from the source tarball in results/{day}/src.stamp. Network: igneum-devnet-, genesis bits , {len(nodes)} one-thread CPU miners (igneum-miner --engine igneum-pow), one BLS vote key per node, sparse --addpeer mesh (about 4 peers each).", "", + f"Machines: {len(nodes)} Hetzner Cloud VMs ({regions}; cx23 in the EU, cpx22 in Singapore, cpx21 in the US unless noted), Debian 12, chrony. Node: {ver}, built on a builder VM from the source tarball in results/{day}/src.stamp. Network: igneum-devnet-, genesis bits , {len(nodes)} one-thread CPU miners (igneum-miner --engine igneum-pow), one BLS vote key per node, sparse --addpeer mesh (about 4 peers each).", "", "Inter-region RTT (ms, median of pair averages): ", "", "Block propagation (arrival minus first arrival anywhere): p50 ms, p90 ms, p99 ms, max ms; per region .", "", "Partition , min: minority reorg depth max (getVirtualChainFromBlock from the minority sink at heal), majority ; converged s after heal; conflicting locks: .", "", diff --git a/infra/seed-nodes/README.md b/infra/seed-nodes/README.md index 3834e662..918275d7 100644 --- a/infra/seed-nodes/README.md +++ b/infra/seed-nodes/README.md @@ -5,7 +5,7 @@ serves peer exchange (the address manager stays on; `--connect` is never used). per seed and is the file the consensus engineer bakes into the network parameters and every package reads as `SEED_PEERS`. The plan, the client path and the rotation procedure are in `docs/plans/seed-nodes.md`. -The first seed, `igneum-seed-1`, was created on 3 Oct 2026 (Hetzner cx23, Falkenstein, EUR 6.49 per month net plus +The first seed, `igneum-seed-1`, was created on 3 Oct 2026 (Hetzner cx23, Falkenstein, USD 6.49 per month net plus the IPv4). It runs the shared devnet (`--devnet`, no suffix). ``` @@ -13,7 +13,8 @@ cd infra/seed-nodes ./create-seed.sh # one VM, persistent IPv4, firewall 22 + 26611 + icmp, appends seeds.tsv, rewrites seeds.txt ./provision-seed.sh igneum-seed-1 # source tarball -> build on the VM (about an hour on 2 vCPU) -> unit igneumd, started ./health.sh # one line per seed: p2p port, unit, RPC, synced, blocks, peers, known addresses -./addpeer-from-mac.sh 188.245.5.161 # the Mac's live node (NAT, gRPC only) dials the seed: addPeer over grpcurl, no restart +./addpeer-from-mac.sh relay start # a non-mining relay igneumd on the Mac peers with the live node (LAN) and the seed; the + # live node runs in safe RPC mode, so addPeer over grpcurl is refused (see the script) SEED_NAME=igneum-seed-2 SEED_LOCATION=ash SEED_TYPE=cpx11 ./create-seed.sh # the next seed; provision adds the first as --addpeer ``` diff --git a/infra/seed-nodes/addpeer-from-mac.sh b/infra/seed-nodes/addpeer-from-mac.sh index 7fd29403..9639b947 100755 --- a/infra/seed-nodes/addpeer-from-mac.sh +++ b/infra/seed-nodes/addpeer-from-mac.sh @@ -1,22 +1,53 @@ #!/usr/bin/env bash -# Make the Mac's live devnet node dial a seed (the Mac sits behind NAT on 192.168.68.64, so the seed cannot dial in). -# The live node (./target/release/kaspad --devnet ... --rpclisten=0.0.0.0:26610) serves gRPC only, no wRPC JSON, so -# this goes through grpcurl against the fork's own proto files. addPeer is an RPC call: the node is not restarted and -# nothing on the chain changes. isPermanent=true makes the node retry the seed after a disconnect (backoff up to 8 min). -# ./addpeer-from-mac.sh add (port defaults to 26611) -# ./addpeer-from-mac.sh --peers list the live node's connected peers -# ./addpeer-from-mac.sh --dag the live node's getBlockDagInfo (to compare block counts with the seed) -# If the live node is ever restarted by hand, the permanent alternative is the flag: --addpeer=:26611 +# Connect the Mac's live devnet to a seed. The Mac sits behind NAT (192.168.68.64), so the seed cannot dial in; the +# Mac side has to dial out. Two ways: +# +# ./addpeer-from-mac.sh relay start [ip] RELAY (the way that works, 3 Oct 2026): a second, non-mining igneumd on +# this Mac (appdir /tmp/igneum-seed-relay, RPC 127.0.0.1:26680, wRPC JSON +# 28680, p2p 127.0.0.1:26681) with --addpeer to the live node's LAN address +# 192.168.68.64:26611 and to the seed. It syncs from the live node and the +# seed syncs from it; from then on every block reaches the seed through the +# relay. The live node is not touched. +# ./addpeer-from-mac.sh relay stop|status +# ./addpeer-from-mac.sh ADDPEER RPC on the live node over grpcurl (gRPC only, no wRPC JSON on it). +# The live node runs in safe mode and answers "Method unavailable in safe +# mode. Run the node with --unsaferpc"; so this only works after the live +# node is restarted with --unsaferpc, and then the simpler restart flag is +# --addpeer=:26611 anyway. Kept for a node started with --unsaferpc. +# ./addpeer-from-mac.sh --peers | --dag the live node's connected peers / getBlockDagInfo (read-only) +# +# Why not --addpeer=127.0.0.1:26611 for the relay: the live node's p2p identity is then seen twice (loopback and LAN) +# and the second handshake fails with PeerAlreadyExists; use the LAN address. . "$(dirname "$0")/lib.sh" -need grpcurl "brew install grpcurl" RPC="${MAC_RPC:-127.0.0.1:26610}" +LIVE_P2P="${LIVE_P2P:-192.168.68.64:26611}" PROTO="$REPO/vendor/igneum-node/rpc/grpc/core/proto" -call() { grpcurl -plaintext -max-time 15 -import-path "$PROTO" -proto messages.proto -d "$1" "$RPC" protowire.RPC/MessageStream; } +RELAY_BIN="${RELAY_BIN:-$REPO/vendor/igneum-node/target-finality/release/igneumd}" +RELAY_DIR=/tmp/igneum-seed-relay +call() { need grpcurl "brew install grpcurl"; grpcurl -plaintext -max-time 15 -import-path "$PROTO" -proto messages.proto -d "$1" "$RPC" protowire.RPC/MessageStream; } case "${1:-}" in - "") die "usage: addpeer-from-mac.sh | --peers | --dag" ;; + "") die "usage: addpeer-from-mac.sh relay start|stop|status [ip] | | --peers | --dag" ;; --peers) call '{"getConnectedPeerInfoRequest":{}}' ;; --dag) call '{"getBlockDagInfoRequest":{}}' ;; + relay) + case "${2:-}" in + start) + ip="${3:-$(head -1 "$SEEDS_TXT" | cut -d: -f1)}"; [ -n "$ip" ] || die "no seed ip (seeds.txt empty)" + [ -x "$RELAY_BIN" ] || die "no $RELAY_BIN (RELAY_BIN=... a finality v2 igneumd built on this Mac)" + pgrep -f "appdir=$RELAY_DIR" >/dev/null && die "relay already running (relay status)" + mkdir -p "$RELAY_DIR" + nohup "$RELAY_BIN" --devnet --appdir="$RELAY_DIR" --rpclisten=127.0.0.1:26680 --rpclisten-json=127.0.0.1:28680 \ + --listen=127.0.0.1:26681 --addpeer="$LIVE_P2P" --addpeer="$ip:$P2P_PORT" --nodnsseed --disable-upnp --nologfiles --yes \ + --loglevel=info > "$RELAY_DIR/relay.log" 2>&1 & + log "relay started (pid $!), log $RELAY_DIR/relay.log; peers: live node $LIVE_P2P and seed $ip:$P2P_PORT" ;; + stop) pkill -f "appdir=$RELAY_DIR" && log "relay stopped" || log "no relay running" ;; + status) + pgrep -fl "appdir=$RELAY_DIR" >/dev/null && log "relay running" || log "relay not running" + IGNEUM_RPC=ws://127.0.0.1:28680 python3 "$REPO/infra/cloud-devnet/node/wrpc.py" sample 2>/dev/null || true + IGNEUM_RPC=ws://127.0.0.1:28680 python3 "$REPO/infra/cloud-devnet/node/wrpc.py" call getConnectedPeerInfo 2>/dev/null | cut -c1-300 || true ;; + *) die "usage: addpeer-from-mac.sh relay start|stop|status [ip]" ;; + esac ;; *) addr="$1"; case "$addr" in *:*) ;; *) addr="$addr:$P2P_PORT" ;; esac - log "addPeer $addr on the live node at $RPC" + log "addPeer $addr on the live node at $RPC (needs --unsaferpc on that node)" call "{\"addPeerRequest\":{\"address\":\"$addr\",\"isPermanent\":true}}" ;; esac diff --git a/infra/seed-nodes/config.sh b/infra/seed-nodes/config.sh index 2ba06034..eafbddfc 100755 --- a/infra/seed-nodes/config.sh +++ b/infra/seed-nodes/config.sh @@ -4,10 +4,10 @@ PROVIDER="${PROVIDER:-hetzner}" # hetzner (hcloud) or digitalocean (doctl) SEED_NAME="${SEED_NAME:-igneum-seed-1}" -SEED_TYPE="${SEED_TYPE:-cx23}" # 2 shared Intel vCPU, 4 GB, 40 GB: EUR 6.49/mo net, EUR 0.0104/h, in fsn1, nbg1, hel1 +SEED_TYPE="${SEED_TYPE:-cx23}" # 2 shared Intel vCPU, 4 GB, 40 GB: USD 6.49/mo net, USD 0.0104/h, in fsn1, nbg1, hel1 # (Hetzner API, 3 Oct 2026). It is the cheapest x86 type this project can create in the # EU: the old cpx11/cpx21 line is deprecated there since Dec 2025 (only ash and hil keep - # it, at EUR 20.49 and 37.49/mo), cpx12 (1 vCPU, 2 GB) costs 13.49. 4 GB is needed: the + # it, at USD 20.49 and 37.49/mo), cpx12 (1 vCPU, 2 GB) costs 13.49. 4 GB is needed: the # node keeps up to four 256 MiB lottery caches (M15 cap) beside rocksdb, and the on-VM # build wants 4 GB plus swap. US seeds: cpx11 (2 GB) or cpx21; Singapore: cpx22 (30.99). SEED_LOCATION="${SEED_LOCATION:-fsn1}" # fsn1 Falkenstein, nbg1 Nuremberg, hel1, ash, hil, sin diff --git a/infra/seed-nodes/create-seed.sh b/infra/seed-nodes/create-seed.sh index c2cdc1af..8cf85828 100755 --- a/infra/seed-nodes/create-seed.sh +++ b/infra/seed-nodes/create-seed.sh @@ -51,9 +51,9 @@ import json, sys j = json.load(sys.stdin); loc = sys.argv[1] for p in j["prices"]: if p["location"] == loc: - print(" %s in %s: EUR %.2f per month net (%.2f gross), EUR %.4f per hour net, %d TB traffic included (Hetzner API)" % ( + print(" %s in %s: USD %.2f per month net (%.2f gross), USD %.4f per hour net, %d TB traffic included (Hetzner API)" % ( j["name"], loc, float(p["price_monthly"]["net"]), float(p["price_monthly"]["gross"]), float(p["price_hourly"]["net"]), int(p.get("included_traffic", 0)) // (1 << 40)))' "$SEED_LOCATION" - log " plus the primary IPv4: about EUR 0.50 per month (approximate, Hetzner list price)" + log " plus the primary IPv4: USD 0.60 per month net, 0.72 gross (Hetzner pricing API)" [ "${YES:-0}" = 1 ] || { printf 'create it now (billing starts) [type yes]: '; read -r a; [ "$a" = yes ] || die "not confirmed"; } if hcloud server describe "$SEED_NAME" >/dev/null 2>&1; then log "$SEED_NAME exists, reusing it"; else hcloud server create --name "$SEED_NAME" --type "$SEED_TYPE" --image "$IMAGE" --location "$SEED_LOCATION" \