@decentnetwork/peer 0.1.9 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/peer.d.ts CHANGED
@@ -37,6 +37,17 @@ export declare class Peer {
37
37
  selfAnnounceStoredOn: number;
38
38
  udpLocalPort: number | null;
39
39
  tcpRelayConnected: number;
40
+ /** The specific relay endpoints this peer has live connections to.
41
+ * Lets us compare two peers' relay sets — if there's NO overlap,
42
+ * net_crypto handshake packets between them have nowhere to route
43
+ * via the TCP fallback path. This is the most common "session
44
+ * established=False forever on the WAN" failure mode after
45
+ * restart waves: peers picked different relays from the bootstrap
46
+ * pool. Surfacing this lets diag pinpoint it. */
47
+ tcpRelayEndpoints: Array<{
48
+ host: string;
49
+ port: number;
50
+ }>;
40
51
  };
41
52
  addKnownNodes(nodes: NetworkNode[]): void;
42
53
  knownNodes(): NetworkNode[];
package/dist/peer.js CHANGED
@@ -452,13 +452,15 @@ export class Peer {
452
452
  * through even when DHT is dead.
453
453
  */
454
454
  dhtHealth() {
455
+ const relays = this.#tcpRelays?.connectedRelays(99) ?? [];
455
456
  return {
456
457
  bootstrapsConfigured: this.#opts.bootstrapNodes.length,
457
458
  knownNodesCount: this.#knownNodes.length,
458
459
  lastSelfAnnounceMs: this.#lastSelfAnnounceMs,
459
460
  selfAnnounceStoredOn: this.#lastSelfAnnounceStoredCount,
460
461
  udpLocalPort: this.#udp?.localPort() ?? null,
461
- tcpRelayConnected: this.#tcpRelays?.connectedRelays(99).length ?? 0,
462
+ tcpRelayConnected: relays.length,
463
+ tcpRelayEndpoints: relays.map((r) => ({ host: r.host, port: r.port })),
462
464
  };
463
465
  }
464
466
  addKnownNodes(nodes) {
@@ -1915,27 +1917,6 @@ export class Peer {
1915
1917
  .sort((a, b) => this.#nodeScore(`${b.host}:${b.port}`) - this.#nodeScore(`${a.host}:${a.port}`))
1916
1918
  .slice(0, MAX_SELF_ANNOUNCE_TARGETS);
1917
1919
  const zeroPing = new Uint8Array(32);
1918
- // Fresh ephemeral keypair for THIS announce sweep. Matches toxcore
1919
- // onion_client.c::do_announce which uses Onion_Client.temp_*_key
1920
- // — a per-client ephemeral pair regenerated on each round — as the
1921
- // announce sender, NOT the real identity key.
1922
- //
1923
- // The bug we just hit: before this fix, runSelfAnnounce used
1924
- // this.#keyPair (real identity) as both senderPublicKey AND
1925
- // searchPublicKey. Bootstrap nodes reject `isStored=2` when
1926
- // sender == search because the protocol's slot-allocation assumes
1927
- // the announcing party can be revoked by knowing the secret of
1928
- // the sender pubkey; if that's our long-lived identity, every
1929
- // bootstrap conservatively refuses. Observed in the wild as
1930
- // selfAnnounceStoredOn=0 across 9 bootstrap nodes on both a
1931
- // public-IP VPS and a NAT'd Mac — identical zero, not an
1932
- // environmental issue.
1933
- //
1934
- // searchPublicKey stays as our real identity (so peers querying
1935
- // for our pubkey find this slot). dataPublicKey also stays as
1936
- // #announceDataKey.publicKey (so peers can encrypt onion-data
1937
- // requests to us). Only the sender envelope rotates.
1938
- const announceSender = createEphemeralKeyPair();
1939
1920
  const candidates = [];
1940
1921
  for (const node of targets) {
1941
1922
  if (!node.pk)
@@ -1975,8 +1956,8 @@ export class Peer {
1975
1956
  const step1Settled = await Promise.allSettled(wave.map((c) => this.#sendAnnounceAndWait({
1976
1957
  node: c.node,
1977
1958
  nodePublicKey: c.nodePk,
1978
- senderPublicKey: announceSender.publicKey,
1979
- senderSecretKey: announceSender.secretKey,
1959
+ senderPublicKey: this.#keyPair.publicKey,
1960
+ senderSecretKey: this.#keyPair.secretKey,
1980
1961
  pingId: zeroPing,
1981
1962
  searchPublicKey: this.#keyPair.publicKey,
1982
1963
  dataPublicKey: this.#announceDataKey.publicKey,
@@ -1999,12 +1980,8 @@ export class Peer {
1999
1980
  const step2Settled = await Promise.allSettled(step1Hits.map(({ c, resp1 }) => this.#sendAnnounceAndWait({
2000
1981
  node: c.node,
2001
1982
  nodePublicKey: c.nodePk,
2002
- // Step2 MUST be re-encrypted to the bootstrap by the SAME
2003
- // ephemeral sender that step1 used — bootstrap matches the
2004
- // ping_id against the sender envelope of the request that
2005
- // issued it. Use the same announceSender as step1.
2006
- senderPublicKey: announceSender.publicKey,
2007
- senderSecretKey: announceSender.secretKey,
1983
+ senderPublicKey: this.#keyPair.publicKey,
1984
+ senderSecretKey: this.#keyPair.secretKey,
2008
1985
  pingId: resp1.pingOrDataPublicKey,
2009
1986
  searchPublicKey: this.#keyPair.publicKey,
2010
1987
  dataPublicKey: this.#announceDataKey.publicKey,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/peer",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "Pure TypeScript port of Elastos Carrier (toxcore-derived) P2P messaging. DHT, onion routing, TCP relay, FlatBuffers app payloads, Express offline relay. Wire-compatible with iOS Beagle and the Carrier C SDK.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",