upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/net.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/net.cpp')
-rw-r--r--src/net.cpp93
1 files changed, 92 insertions, 1 deletions
diff --git a/src/net.cpp b/src/net.cpp
index 1d552cf..08a3348 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -414,6 +414,93 @@ static void RememberBtfPeer(const string& strBtfAddr, const string& strMeeting,
414 } 414 }
415} 415}
416 416
417//
418// Compiled-in bootstrap seeds.
419//
420// A node with no cache has nothing but the Nostr relays, and if those are down,
421// blocked or simply slow, a first run has no way into the network at all. Seeds
422// are the floor under that: a handful of long-lived peers baked into the binary.
423//
424// A seed entry is deliberately just an address and an encryption key -- no
425// meeting node. The rendezvous relay pairs on the service's public key, and a
426// `.btf` address *is* that key, so a client can find a seed by trying the known
427// relays in turn. Recording which relay a seed was on would rot the moment it
428// failed over, which is the exact failure this project spent a long time
429// chasing: advertising a rendezvous somebody is not registered at.
430//
431// Seeds are ordinary nodes with no special authority. They hand out signed,
432// self-certifying descriptors like any peer, so a hostile seed can stall a
433// bootstrap but cannot forge a peer or feed a false chain.
434//
435struct BtfSeed
436{
437 const char* btfAddr;
438 const char* encHex; // 64 hex chars, the peer's x25519 public key
439};
440
441static const BtfSeed pszBtfSeeds[] =
442{
443 // Dedicated bootstrap node, Almaty. Runs beside a rendezvous relay on the
444 // same host, holds no wallet balance and does not mine -- it exists only to
445 // answer a first dial. It is trusted for nothing: it serves the same signed
446 // descriptors any peer does.
447 { "ygffz37jczlmrkzicxok6chobauyratdexc7hfgwzjdabzvb2nkngqy.btf",
448 "de8284b9d4effa2132e7981b566c1a297c39c1857d9c128e8ae093ef511d3200" },
449};
450static const size_t nBtfSeeds = ARRAYLEN(pszBtfSeeds);
451
452// Extra seeds from the command line (/btfseed=ADDRESS:ENCHEX, repeatable).
453vector<pair<string, string> > vBtfExtraSeeds;
454
455static int TryBtfSeeds()
456{
457 vector<pair<string, string> > seeds;
458 for (size_t i = 0; i < nBtfSeeds; i++)
459 seeds.push_back(make_pair(string(pszBtfSeeds[i].btfAddr),
460 string(pszBtfSeeds[i].encHex)));
461 foreach(const PAIRTYPE(string, string)& s, vBtfExtraSeeds)
462 seeds.push_back(s);
463
464 if (seeds.empty())
465 return 0;
466
467 vector<string> relays = BtfAllRelays();
468 if (relays.empty())
469 return 0;
470
471 LogPrint("net", "btfseed: trying %zu seed(s) across %zu relay(s)\n",
472 seeds.size(), relays.size());
473
474 int nConnected = 0;
475 foreach(const PAIRTYPE(string, string)& s, seeds)
476 {
477 if (fShutdown) return nConnected;
478 unsigned char enc[32];
479 if (!HexToBytes(s.second, enc, 32))
480 {
481 LogPrint("net", "btfseed: %s has a malformed encryption key, skipped\n",
482 s.first.c_str());
483 continue;
484 }
485 // We do not know which relay this seed is registered at, so walk them.
486 foreach(const string& strRelay, relays)
487 {
488 if (fShutdown) return nConnected;
489 if (ConnectNodeBtfResolved(s.first, strRelay, enc))
490 {
491 LogPrint("net", "btfseed: reached %s via %s\n",
492 s.first.c_str(), strRelay.c_str());
493 nConnected++;
494 break; // found it; no need to try this seed's other relays
495 }
496 }
497 if (nConnected >= 4)
498 break; // enough of a foothold; the rest comes from discovery
499 }
500 LogPrint("net", "btfseed: %d seed(s) answered\n", nConnected);
501 return nConnected;
502}
503
417// Dial everything we reached last time, before the relays have said anything. 504// Dial everything we reached last time, before the relays have said anything.
418void ThreadReconnectCachedBtfPeers(void* parg) 505void ThreadReconnectCachedBtfPeers(void* parg)
419{ 506{
@@ -421,7 +508,11 @@ void ThreadReconnectCachedBtfPeers(void* parg)
421 LoadCachedBtfPeers(peers); 508 LoadCachedBtfPeers(peers);
422 if (peers.empty()) 509 if (peers.empty())
423 { 510 {
424 LogPrint("net", "btfpeers: no cache yet, waiting on relay discovery\n"); 511 // First run, or the cache aged out. Seeds are the only way in that does
512 // not depend on a relay answering.
513 LogPrint("net", "btfpeers: no cache yet, falling back to seeds\n");
514 if (TryBtfSeeds() == 0)
515 LogPrint("net", "btfpeers: no seed answered, waiting on relay discovery\n");
425 return; 516 return;
426 } 517 }
427 LogPrint("net", "btfpeers: trying %zu remembered peer(s) before discovery\n", 518 LogPrint("net", "btfpeers: trying %zu remembered peer(s) before discovery\n",