upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/main_gui.cpp
diff options
context:
space:
mode:
authorBitflash <btf01@proton.me>2026-07-29 16:01:43 -0300
committerGitHub <noreply@github.com>2026-07-29 16:01:43 -0300
commitab24958f1470cb62a4637126345fdf14c2ec0bd4 (patch)
treede3c1ca3888a531fef6240b14eca79655e226907 /src/main_gui.cpp
parentf9d839e4e53ba5e4ca4829e52ef9470fd116d784 (diff)
net: compiled-in bootstrap seeds, so a first run does not need a relay (#36)
* net: compiled-in bootstrap seeds, so a first run does not need a relay A node with no cache has only the Nostr relays. If they are down, blocked or slow, a first run has no way into the network at all -- and that is the one moment a user has no patience for. Seeds are the floor under that. A seed entry is an address and an encryption key. Deliberately no meeting node: the rendezvous relay pairs on the service's public key, and a `.btf` address is that key, so a client can find a seed by trying the known relays in turn. Recording which relay a seed was on would rot the moment it failed over, which is exactly the failure this project spent weeks chasing -- advertising a rendezvous somebody is not registered at. Seeds carry no authority. They serve the same signed, self-certifying descriptors as any peer, so a hostile seed can stall a bootstrap but cannot forge a peer or feed a false chain. The compiled list is empty. Which nodes become permanent public bootstrap targets is a decision for whoever runs the network, not a default, and it is close to irreversible once binaries are distributed. Empty is valid: discovery falls back to Nostr exactly as before. /btfseed=ADDRESS:ENCHEX (repeatable) appends at runtime, for testing and for private networks. Tested against the live network, clean datadir, no cache, three seeds carrying no meeting node: btfpeers: no cache yet, falling back to seeds btfseed: trying 3 seed(s) across 3 relay(s) btfseed: reached q5jxyzn...btf via 90.156.222.107:8434 btfseed: 3 seed(s) answered * net: add the Almaty bootstrap node to the seed list Dedicated node, no wallet balance, no mining, running beside the rendezvous relay on the same host. It exists only to answer a first dial. Fresh datadir, no flags, compiled list only: btfpeers: no cache yet, falling back to seeds btfseed: trying 1 seed(s) across 3 relay(s) btfseed: reached ygffz37...btf via 90.156.222.107:8434 btfseed: 1 seed(s) answered btfpeers: kept 2 of 2 descriptor(s) 5.2 seconds from nothing to a peer, against 36s for a cold start that had to go through the relays. The seed then handed over two more peers by exchange, which the cache keeps for next time.
Diffstat (limited to 'src/main_gui.cpp')
-rw-r--r--src/main_gui.cpp20
1 files changed, 20 insertions, 0 deletions
diff --git a/src/main_gui.cpp b/src/main_gui.cpp
index 63bdbb7..9f7e34e 100644
--- a/src/main_gui.cpp
+++ b/src/main_gui.cpp
@@ -61,6 +61,7 @@ static void PrintUsage()
61 printf("\n"); 61 printf("\n");
62 printf("Network:\n"); 62 printf("Network:\n");
63 printf(" /port=N (P2P listen port, default 8433)\n"); 63 printf(" /port=N (P2P listen port, default 8433)\n");
64 printf(" /btfseed=ADDRESS:ENCHEX (extra bootstrap peer, repeatable)\n");
64 printf("\n"); 65 printf("\n");
65 printf("Each option also accepts '-' instead of '/'.\n"); 66 printf("Each option also accepts '-' instead of '/'.\n");
66} 67}
@@ -117,6 +118,25 @@ static void ParseStartupArguments(int argc, char* argv[])
117 if (!announceRelay.empty()) 118 if (!announceRelay.empty())
118 strBtfAnnounceRelay = announceRelay; 119 strBtfAnnounceRelay = announceRelay;
119 120
121 // /btfseed=ADDRESS:ENCHEX -- extra bootstrap peers, repeatable. Useful for
122 // testing the seed path and for private networks that ship no compiled list.
123 for (int i = 1; i < argc; i++)
124 {
125 string s = argv[i];
126 size_t eq = s.find('=');
127 if (eq == string::npos) continue;
128 string key = s.substr(0, eq);
129 if (key != "/btfseed" && key != "-btfseed") continue;
130 string val = s.substr(eq + 1);
131 size_t colon = val.rfind(':');
132 if (colon == string::npos || colon + 1 >= val.size())
133 {
134 fprintf(stderr, "Ignoring %s: expected ADDRESS:ENCHEX\n", s.c_str());
135 continue;
136 }
137 vBtfExtraSeeds.push_back(make_pair(val.substr(0, colon), val.substr(colon + 1)));
138 }
139
120 // net.cpp has described nListenPort as "tunable via /port" since it was 140 // net.cpp has described nListenPort as "tunable via /port" since it was
121 // written, but nothing ever read the option, so the port was fixed at 8433 141 // written, but nothing ever read the option, so the port was fixed at 8433
122 // and a second node could not start on a machine already running one. 142 // and a second node could not start on a machine already running one.