feat(peer-discovery): implement global peer discovery and update peer profile handling
This commit is contained in:
parent
34cc1883f5
commit
b4f75cd995
|
|
@ -157,6 +157,16 @@ pub async fn start_node(app: tauri::AppHandle, state: State<'_, AppState>) -> Re
|
||||||
namespace: personal_ns,
|
namespace: personal_ns,
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
// register under the global "dusk/peers" namespace so any peer can
|
||||||
|
// discover us via the relay tracker, enabling global peer discovery
|
||||||
|
// without exposing ip addresses (all connections use relay circuit)
|
||||||
|
let _ = handle
|
||||||
|
.command_tx
|
||||||
|
.send(NodeCommand::RegisterRendezvous {
|
||||||
|
namespace: "dusk/peers".to_string(),
|
||||||
|
})
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -258,6 +258,22 @@ pub async fn remove_friend(state: State<'_, AppState>, peer_id: String) -> Resul
|
||||||
.map_err(|e| format!("failed to remove friend: {}", e))
|
.map_err(|e| format!("failed to remove friend: {}", e))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// discover online peers via the global relay tracker namespace
|
||||||
|
// this allows finding peers without sharing a community or knowing their peer_id
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn discover_global_peers(state: State<'_, AppState>) -> Result<(), String> {
|
||||||
|
let node_handle = state.node_handle.lock().await;
|
||||||
|
if let Some(ref handle) = *node_handle {
|
||||||
|
let _ = handle
|
||||||
|
.command_tx
|
||||||
|
.send(crate::node::NodeCommand::DiscoverRendezvous {
|
||||||
|
namespace: "dusk/peers".to_string(),
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// broadcast a revocation to all peers, stop the node, and wipe all local data
|
// broadcast a revocation to all peers, stop the node, and wipe all local data
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn reset_identity(state: State<'_, AppState>) -> Result<(), String> {
|
pub async fn reset_identity(state: State<'_, AppState>) -> Result<(), String> {
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ pub fn run() {
|
||||||
commands::identity::get_friends,
|
commands::identity::get_friends,
|
||||||
commands::identity::add_friend,
|
commands::identity::add_friend,
|
||||||
commands::identity::remove_friend,
|
commands::identity::remove_friend,
|
||||||
|
commands::identity::discover_global_peers,
|
||||||
commands::identity::reset_identity,
|
commands::identity::reset_identity,
|
||||||
commands::chat::send_message,
|
commands::chat::send_message,
|
||||||
commands::chat::get_messages,
|
commands::chat::get_messages,
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,7 @@ pub enum DuskEvent {
|
||||||
peer_id: String,
|
peer_id: String,
|
||||||
display_name: String,
|
display_name: String,
|
||||||
bio: String,
|
bio: String,
|
||||||
|
public_key: String,
|
||||||
},
|
},
|
||||||
#[serde(rename = "profile_revoked")]
|
#[serde(rename = "profile_revoked")]
|
||||||
ProfileRevoked { peer_id: String },
|
ProfileRevoked { peer_id: String },
|
||||||
|
|
@ -396,6 +397,7 @@ pub async fn start(
|
||||||
peer_id: profile.peer_id,
|
peer_id: profile.peer_id,
|
||||||
display_name: profile.display_name,
|
display_name: profile.display_name,
|
||||||
bio: profile.bio,
|
bio: profile.bio,
|
||||||
|
public_key: profile.public_key,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
crate::protocol::messages::GossipMessage::ProfileRevoke(revocation) => {
|
crate::protocol::messages::GossipMessage::ProfileRevoke(revocation) => {
|
||||||
|
|
|
||||||
|
|
@ -342,6 +342,7 @@ const App: Component = () => {
|
||||||
event.payload.peer_id,
|
event.payload.peer_id,
|
||||||
event.payload.display_name,
|
event.payload.display_name,
|
||||||
event.payload.bio,
|
event.payload.bio,
|
||||||
|
event.payload.public_key,
|
||||||
);
|
);
|
||||||
// keep dm conversation names in sync
|
// keep dm conversation names in sync
|
||||||
updateDMPeerDisplayName(
|
updateDMPeerDisplayName(
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,11 @@
|
||||||
import { Component, createSignal, createMemo, For, Show } from "solid-js";
|
import {
|
||||||
|
Component,
|
||||||
|
createSignal,
|
||||||
|
createMemo,
|
||||||
|
createEffect,
|
||||||
|
For,
|
||||||
|
Show,
|
||||||
|
} from "solid-js";
|
||||||
import { Portal } from "solid-js/web";
|
import { Portal } from "solid-js/web";
|
||||||
import {
|
import {
|
||||||
X,
|
X,
|
||||||
|
|
@ -34,6 +41,17 @@ const UserDirectoryModal: Component<UserDirectoryModalProps> = (props) => {
|
||||||
const [activeTab, setActiveTab] = createSignal<DirectoryTab>("all");
|
const [activeTab, setActiveTab] = createSignal<DirectoryTab>("all");
|
||||||
const [copiedId, setCopiedId] = createSignal<string | null>(null);
|
const [copiedId, setCopiedId] = createSignal<string | null>(null);
|
||||||
|
|
||||||
|
// trigger global peer discovery when modal opens
|
||||||
|
createEffect(() => {
|
||||||
|
if (props.isOpen) {
|
||||||
|
// discover peers registered on the relay's global "dusk/peers" namespace
|
||||||
|
// this allows finding online peers without sharing a community
|
||||||
|
tauri.discoverGlobalPeers().catch((e) => {
|
||||||
|
console.error("failed to discover global peers:", e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// filter out our own peer id from the directory
|
// filter out our own peer id from the directory
|
||||||
const filteredPeers = createMemo(() => {
|
const filteredPeers = createMemo(() => {
|
||||||
const myId = identity()?.peer_id;
|
const myId = identity()?.peer_id;
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,10 @@ export async function removeFriend(peerId: string): Promise<void> {
|
||||||
return invoke("remove_friend", { peerId });
|
return invoke("remove_friend", { peerId });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function discoverGlobalPeers(): Promise<void> {
|
||||||
|
return invoke("discover_global_peers");
|
||||||
|
}
|
||||||
|
|
||||||
export async function resetIdentity(): Promise<void> {
|
export async function resetIdentity(): Promise<void> {
|
||||||
return invoke("reset_identity");
|
return invoke("reset_identity");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,12 @@ export type DuskEvent =
|
||||||
| { kind: "sync_complete"; payload: { community_id: string } }
|
| { kind: "sync_complete"; payload: { community_id: string } }
|
||||||
| {
|
| {
|
||||||
kind: "profile_received";
|
kind: "profile_received";
|
||||||
payload: { peer_id: string; display_name: string; bio: string };
|
payload: {
|
||||||
|
peer_id: string;
|
||||||
|
display_name: string;
|
||||||
|
bio: string;
|
||||||
|
public_key: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
| { kind: "profile_revoked"; payload: { peer_id: string } }
|
| { kind: "profile_revoked"; payload: { peer_id: string } }
|
||||||
| { kind: "relay_status"; payload: { connected: boolean } }
|
| { kind: "relay_status"; payload: { connected: boolean } }
|
||||||
|
|
|
||||||
|
|
@ -21,17 +21,34 @@ export function updatePeerProfile(
|
||||||
peerId: string,
|
peerId: string,
|
||||||
displayName: string,
|
displayName: string,
|
||||||
bio: string,
|
bio: string,
|
||||||
|
publicKey: string,
|
||||||
) {
|
) {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
|
||||||
setKnownPeers((prev) =>
|
setKnownPeers((prev) => {
|
||||||
prev.map((p) =>
|
const existing = prev.find((p) => p.peer_id === peerId);
|
||||||
p.peer_id === peerId
|
if (existing) {
|
||||||
? { ...p, display_name: displayName, bio, last_seen: now }
|
// update existing peer
|
||||||
: p,
|
return prev.map((p) =>
|
||||||
),
|
p.peer_id === peerId
|
||||||
);
|
? { ...p, display_name: displayName, bio, last_seen: now }
|
||||||
|
: p,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// add new peer that just announced themselves
|
||||||
|
const newEntry: DirectoryEntry = {
|
||||||
|
peer_id: peerId,
|
||||||
|
display_name: displayName,
|
||||||
|
bio,
|
||||||
|
public_key: publicKey,
|
||||||
|
last_seen: now,
|
||||||
|
is_friend: false,
|
||||||
|
};
|
||||||
|
return [...prev, newEntry];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// update friends list if this peer is a friend
|
||||||
setFriends((prev) =>
|
setFriends((prev) =>
|
||||||
prev.map((p) =>
|
prev.map((p) =>
|
||||||
p.peer_id === peerId
|
p.peer_id === peerId
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue