mirror of
https://github.com/logos-co/logos-libp2p-module.git
synced 2026-08-27 22:41:09 +00:00
255 lines
8.4 KiB
C++
255 lines
8.4 KiB
C++
/// # Tutorial 10: Peer Store Management
|
|
///
|
|
/// The **peer store** is libp2p's database of known peers. It maps peer IDs
|
|
/// to their known addresses, protocols, public keys, and metadata.
|
|
///
|
|
/// A well-maintained peer store helps:
|
|
/// - Reconnect to known peers without re-discovery
|
|
/// - Track protocol capabilities of known peers
|
|
/// - Maintain a persistent view of the network
|
|
///
|
|
/// In this tutorial we'll:
|
|
/// - List known peers
|
|
/// - Get detailed peer info
|
|
/// - Manually add peers to the store
|
|
/// - Update addresses and protocols
|
|
/// - Delete peers from the store
|
|
///
|
|
/// -----------
|
|
|
|
#include <cstdio>
|
|
#include <string>
|
|
#include <vector>
|
|
#include "plugin.h"
|
|
|
|
int main()
|
|
{
|
|
printf("=== Tutorial 10: Peer Store Management ===\n\n");
|
|
|
|
setLogLevel(LogLevel::Fatal);
|
|
|
|
/// ## Step 1: Create two nodes
|
|
///
|
|
/// The peer store is automatically available on any started node.
|
|
/// We use one main node and one remote peer so the main node's peerstore
|
|
/// contains real peer data after a connection is established.
|
|
Libp2pModuleOptions opts;
|
|
opts.addrs = {"/ip4/127.0.0.1/tcp/9790"};
|
|
|
|
Libp2pModuleOptions remoteOpts;
|
|
remoteOpts.addrs = {"/ip4/127.0.0.1/tcp/9791"};
|
|
|
|
Libp2pModuleImpl node(opts);
|
|
Libp2pModuleImpl remote(remoteOpts);
|
|
|
|
StdLogosResult startRes = node.start();
|
|
if (!startRes.success) {
|
|
fprintf(stderr, "Node failed to start: %s\n",
|
|
startRes.error.c_str());
|
|
return 1;
|
|
}
|
|
StdLogosResult remoteStartRes = remote.start();
|
|
if (!remoteStartRes.success) {
|
|
fprintf(stderr, "Remote node failed to start: %s\n",
|
|
remoteStartRes.error.c_str());
|
|
return 1;
|
|
}
|
|
|
|
StdLogosResult infoRes = node.peerInfo();
|
|
if (!infoRes.success) {
|
|
fprintf(stderr, "Failed to get node info: %s\n",
|
|
infoRes.error.c_str());
|
|
return 1;
|
|
}
|
|
auto info = infoRes.value;
|
|
std::string nodePeerId = info["peerId"].get<std::string>();
|
|
printf("Node started, peer ID: %s\n", nodePeerId.c_str());
|
|
|
|
StdLogosResult remoteInfoRes = remote.peerInfo();
|
|
if (!remoteInfoRes.success) {
|
|
fprintf(stderr, "Failed to get remote node info: %s\n",
|
|
remoteInfoRes.error.c_str());
|
|
return 1;
|
|
}
|
|
auto remoteInfo = remoteInfoRes.value;
|
|
std::string remotePeerId = remoteInfo["peerId"].get<std::string>();
|
|
std::vector<std::string> remoteAddrs;
|
|
for (const auto& a : remoteInfo["addrs"]) {
|
|
remoteAddrs.push_back(a.get<std::string>());
|
|
}
|
|
printf("Remote node started, peer ID: %s\n", remotePeerId.c_str());
|
|
|
|
/// ## Step 2: List known peers
|
|
///
|
|
/// Initially, the peer store may be empty because no remote peers have
|
|
/// been discovered or added yet.
|
|
/// `peerstoreGetPeers()` returns a JSON array of peer IDs.
|
|
printf("\nListing known peers...\n");
|
|
StdLogosResult peersRes = node.peerstoreGetPeers();
|
|
if (!peersRes.success) {
|
|
fprintf(stderr, "Failed to list peers: %s\n",
|
|
peersRes.error.c_str());
|
|
return 1;
|
|
}
|
|
printf("Found %zu known peer(s):\n", peersRes.value.size());
|
|
for (const auto& p : peersRes.value) {
|
|
printf(" %s\n", p.get<std::string>().c_str());
|
|
}
|
|
|
|
/// ## Step 3: Connect a remote peer and get detailed peer info
|
|
///
|
|
/// `peerstoreGetPeerInfo()` returns a rich JSON object with addresses,
|
|
/// protocols, and the public key.
|
|
printf("\nConnecting to remote peer...\n");
|
|
StdLogosResult connectRes = node.connectPeer(remotePeerId, remoteAddrs, 5000);
|
|
if (!connectRes.success) {
|
|
fprintf(stderr, "Failed to connect to remote peer: %s\n",
|
|
connectRes.error.c_str());
|
|
return 1;
|
|
}
|
|
printf("Connected to remote peer\n");
|
|
|
|
printf("\nGetting remote peer info from the store:\n");
|
|
StdLogosResult remoteStoreInfo = node.peerstoreGetPeerInfo(remotePeerId);
|
|
if (!remoteStoreInfo.success) {
|
|
fprintf(stderr, "Failed to get remote peer info: %s\n",
|
|
remoteStoreInfo.error.c_str());
|
|
return 1;
|
|
}
|
|
|
|
printf(" Peer ID: %s\n",
|
|
remoteStoreInfo.value["peerId"].get<std::string>().c_str());
|
|
printf(" Public key: %s\n",
|
|
remoteStoreInfo.value["publicKey"].get<std::string>().c_str());
|
|
|
|
printf(" Addresses:\n");
|
|
for (const auto& a : remoteStoreInfo.value["addrs"]) {
|
|
printf(" %s\n", a.get<std::string>().c_str());
|
|
}
|
|
|
|
printf(" Protocols:\n");
|
|
for (const auto& p : remoteStoreInfo.value["protocols"]) {
|
|
printf(" %s\n", p.get<std::string>().c_str());
|
|
}
|
|
|
|
/// ## Step 4: Manually add a peer to the store
|
|
///
|
|
/// You can manually register peers in the store. This is useful for
|
|
/// peers discovered through out-of-band methods (e.g. a config file,
|
|
/// QR code, or DNS).
|
|
printf("\nManually adding a peer to the store...\n");
|
|
|
|
std::string manualPeerId =
|
|
"16Uiu2HAkzM1nzU99VxRqzF9CjZAqjF3MZHQ2oRENL7SNgP1d8pRy";
|
|
std::vector<std::string> manualAddrs = {
|
|
"/ip4/192.168.1.100/tcp/9000",
|
|
"/ip4/10.0.0.50/tcp/9001",
|
|
};
|
|
std::vector<std::string> manualProtos = {
|
|
"/ipfs/ping/1.0.0",
|
|
"/examples/echo/1.0.0",
|
|
};
|
|
|
|
StdLogosResult addPeerRes =
|
|
node.peerstoreAddPeer(manualPeerId, manualAddrs, manualProtos);
|
|
if (!addPeerRes.success) {
|
|
fprintf(stderr, "Failed to add peer: %s\n",
|
|
addPeerRes.error.c_str());
|
|
return 1;
|
|
}
|
|
printf("Peer added: %s\n", manualPeerId.c_str());
|
|
|
|
/// Verify it was added:
|
|
printf("\nVerifying: listing peers again...\n");
|
|
StdLogosResult peersAfter = node.peerstoreGetPeers();
|
|
if (!peersAfter.success) {
|
|
fprintf(stderr, "Failed to list peers after add: %s\n",
|
|
peersAfter.error.c_str());
|
|
return 1;
|
|
}
|
|
printf("Now have %zu known peer(s)\n", peersAfter.value.size());
|
|
if (peersAfter.value.size() != 2) {
|
|
fprintf(stderr, "Expected to have 2 peers in the peer store after manually adding one");
|
|
return 1;
|
|
}
|
|
|
|
/// ## Step 5: Update peer info
|
|
///
|
|
/// `peerstoreSetPeerAddresses()` to update a peer's stored data.
|
|
printf("\nUpdating peer addresses...\n");
|
|
std::vector<std::string> updatedAddrs = {
|
|
"/ip4/192.168.1.100/tcp/9002",
|
|
"/dns4/peer.example.com/tcp/9000",
|
|
};
|
|
StdLogosResult updateAddrsRes =
|
|
node.peerstoreSetPeerAddresses(manualPeerId, updatedAddrs);
|
|
if (!updateAddrsRes.success) {
|
|
fprintf(stderr, "Failed to update addresses: %s\n",
|
|
updateAddrsRes.error.c_str());
|
|
return 1;
|
|
}
|
|
printf("Addresses updated\n");
|
|
|
|
// Check the updated info:
|
|
StdLogosResult updatedInfo = node.peerstoreGetPeerInfo(manualPeerId);
|
|
if (!updatedInfo.success) {
|
|
fprintf(stderr, "Failed to get updated peer info: %s\n",
|
|
updatedInfo.error.c_str());
|
|
return 1;
|
|
}
|
|
printf("Updated addresses:\n");
|
|
for (const auto& a : updatedInfo.value["addrs"]) {
|
|
printf(" %s\n", a.get<std::string>().c_str());
|
|
}
|
|
|
|
/// ## Step 6: Delete a peer from the store
|
|
///
|
|
/// `peerstoreDeletePeer()` removes a peer and all its metadata.
|
|
printf("\nDeleting peer from store...\n");
|
|
StdLogosResult deletePeerRes = node.peerstoreDeletePeer(manualPeerId);
|
|
if (!deletePeerRes.success) {
|
|
fprintf(stderr, "Failed to delete peer: %s\n",
|
|
deletePeerRes.error.c_str());
|
|
return 1;
|
|
}
|
|
printf("Peer deleted\n");
|
|
|
|
/// Verify deletion:
|
|
StdLogosResult peersFinal = node.peerstoreGetPeers();
|
|
if (!peersFinal.success) {
|
|
fprintf(stderr, "Failed to list peers after delete: %s\n",
|
|
peersFinal.error.c_str());
|
|
return 1;
|
|
}
|
|
printf("Now have %zu known peer(s)\n",
|
|
peersFinal.value.size());
|
|
for (const auto& p : peersFinal.value) {
|
|
printf(" %s\n", p.get<std::string>().c_str());
|
|
}
|
|
|
|
/// ## Step 7: Clean up
|
|
node.stop();
|
|
remote.stop();
|
|
|
|
printf("\n=== Tutorial 10 Complete ===\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
/// ## Key Takeaways
|
|
///
|
|
/// - The peer store is a built-in database of known peers
|
|
/// - `peerstoreGetPeers()` lists all known peer IDs
|
|
/// - `peerstoreGetPeerInfo()` returns detailed peer metadata
|
|
/// - `peerstoreAddPeer()` adds peers manually (with addresses + protocols)
|
|
/// - `peerstoreSetPeerAddresses()` update existing entries
|
|
/// - `peerstoreDeletePeer()` removes peers
|
|
/// - A populated peer store speeds up reconnection and reduces
|
|
/// network overhead
|
|
|
|
/// ## Run tutorial
|
|
///
|
|
/// ```bash
|
|
/// ./build/tutorial/tutorial_10_peerstore
|
|
/// ```
|