diff options
| author | Bitflash <btf01@proton.me> | 2026-07-29 11:52:12 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-07-29 11:52:12 -0300 |
| commit | 96a8e42bbc313f96d54377ae5886da84298e61a3 (patch) | |
| tree | 36bcd61016ee03c90140b407d4e5863a282e78cf /src/main.cpp | |
| parent | 7f6fdbab6c90360ab3b2d391a7b5aedc6f9721ac (diff) | |
Remember .btf peers that answered, and dial them first on start (#25)
* net: remember .btf peers that answered, and dial them first on start
Discovery depends entirely on the Nostr relays. A node that has been up
for hours knows exactly which peers respond, and throws all of it away on
exit; the next start reaches for the relays again and walks the same
descriptor list, of which roughly 96% is dead. That is what makes a
restart take minutes before the first tunnel opens -- measured today at
about seven.
Every peer that completes a tunnel is now written to btfpeers.json with
its meeting node and encryption key, which is everything needed to redial
it. On start a thread tries those before the relays have answered
anything, stopping once eight are connected. Entries older than a week
are dropped, and the file holds at most fifty.
Cache only: nothing here changes how a first-ever run bootstraps, and a
missing or corrupt file just falls through to relay discovery.
* net: exchange signed .btf descriptors between peers
Discovery has depended entirely on the Nostr relays. Two connected nodes never
told each other who else existed, so a relay outage left a running network
unable to grow, and a node that found one stale peer had no way to learn there
was anything better. The old `addr` gossip went out with the IRC seed.
Peers now trade signed descriptors over a new "btfpeers" message: our own
first, then peers that actually answered us. The receiver checks each Schnorr
signature against the key the `.btf` address decodes to, so the sender is
trusted for nothing -- forging an entry needs somebody else's secret key. That
leaves flooding with self-generated keys, which the per-message caps and the
"peers that answered" ordering are there to blunt.
Unknown commands are ignored (main.cpp), so nodes without this just drop the
message; nothing here is a protocol break.
The cache from the peer-cache change now keeps each peer's descriptor verbatim
alongside the parsed fields, because that signature is what makes a peer
relayable. Entries without one -- resolved through Nostr, or written before
this -- stay dialable, just not passed on. A dial never clears a descriptor
already on file.
* main_gui: implement /port, which net.cpp already documented
net.cpp has said nListenPort is "tunable via /port" since it was written, but
nothing ever parsed the option. Two nodes could not share a machine, which is
exactly what testing peer exchange needs. Sets addrLocalHost.port too, so we
do not advertise a port we never bound.
Diffstat (limited to 'src/main.cpp')
| -rw-r--r-- | src/main.cpp | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp index a75bf54..bb317d2 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
| @@ -1877,6 +1877,14 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) | |||
| 1877 | pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), uint256(0)); | 1877 | pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), uint256(0)); |
| 1878 | } | 1878 | } |
| 1879 | 1879 | ||
| 1880 | // Introduce ourselves and hand over the .btf peers that answered us. | ||
| 1881 | // Everything in here is self-certifying, so this is safe to send to a | ||
| 1882 | // node we know nothing about, and safe for it to act on. | ||
| 1883 | vector<string> vPexOut; | ||
| 1884 | BtfPexCollect(vPexOut); | ||
| 1885 | if (!vPexOut.empty()) | ||
| 1886 | pfrom->PushMessage("btfpeers", vPexOut); | ||
| 1887 | |||
| 1880 | if (LogAcceptsCategory("net")) printf("version addrMe = %s\n", addrMe.ToString().c_str()); | 1888 | if (LogAcceptsCategory("net")) printf("version addrMe = %s\n", addrMe.ToString().c_str()); |
| 1881 | } | 1889 | } |
| 1882 | 1890 | ||
| @@ -1888,6 +1896,29 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) | |||
| 1888 | } | 1896 | } |
| 1889 | 1897 | ||
| 1890 | 1898 | ||
| 1899 | else if (strCommand == "btfpeers") | ||
| 1900 | { | ||
| 1901 | // Peer exchange. Nothing here is taken on trust: BtfPexAccept checks | ||
| 1902 | // every descriptor's signature against the key its .btf address | ||
| 1903 | // decodes to, and drops the rest. | ||
| 1904 | int64 nNow = GetTime(); | ||
| 1905 | if (nNow - pfrom->nLastPexRecv < PEX_MIN_INTERVAL) | ||
| 1906 | { | ||
| 1907 | if (LogAcceptsCategory("net")) | ||
| 1908 | printf("btfpeers: ignoring, %s is sending them too fast\n", | ||
| 1909 | pfrom->addr.ToString().c_str()); | ||
| 1910 | return true; | ||
| 1911 | } | ||
| 1912 | pfrom->nLastPexRecv = nNow; | ||
| 1913 | |||
| 1914 | vector<string> vDesc; | ||
| 1915 | vRecv >> vDesc; | ||
| 1916 | int nKept = BtfPexAccept(vDesc); | ||
| 1917 | LogPrint("net", "btfpeers: kept %d of %zu descriptor(s) from %s\n", | ||
| 1918 | nKept, vDesc.size(), pfrom->addr.ToString().c_str()); | ||
| 1919 | } | ||
| 1920 | |||
| 1921 | |||
| 1891 | else if (strCommand == "inv") | 1922 | else if (strCommand == "inv") |
| 1892 | { | 1923 | { |
| 1893 | vector<CInv> vInv; | 1924 | vector<CInv> vInv; |