a70e68c7bd
* Smolmix documentation * Add smolmix docs: landing page, tutorials, and developer page links * Add Exit Gateway services page (NR vs IPR) and link from existing docs * Update auto-generated command and API outputs * Reorg of tutorials and architecture pages * License information + remove TODO from docs.rs visibile comment + reorg readme * Add versions file for doc-wide versioning * Relative -> absolute links * Relative -> absolute links * Update license + add old tutorial code as examples * Streamline smolmix docs * Clippy * Clean up doc comments * Last pass * Add larger file download to list * set new versions * Clippy * Remove blake pin from docs + add version range to root Cargo.toml * Format example logging * Remove crate blocked component * Loose whitespace * Add doc verification script for inline mdx * Formatting * Components regen * Reorg + tighten text * Voicing cohesion pass + remove bloated examples * Voicing cont. * Reduce max download size * Small suggested clarifications * Max/docs voicing consistency (#6769) * Reduce max download size * voicing consistency across docs * New landing order w smolmix * Tweaks * Final tweaks
85 lines
3.0 KiB
Rust
85 lines
3.0 KiB
Rust
//! Anonymous replies using SURBs (Single Use Reply Blocks).
|
|
//!
|
|
//! Sends a message to self, extracts the `AnonymousSenderTag` from the
|
|
//! incoming message, and replies using `send_reply()` without knowing
|
|
//! the sender's Nym address. The SDK bundles SURBs with every outgoing
|
|
//! message by default, so the recipient can always reply anonymously.
|
|
//!
|
|
//! ## What this demonstrates
|
|
//!
|
|
//! - Every incoming message carries a `sender_tag`, an opaque
|
|
//! [`AnonymousSenderTag`] that enables replies without revealing the
|
|
//! sender's address
|
|
//! - `send_reply()` consumes a SURB to route the reply back through the
|
|
//! mixnet. Each SURB is single-use; the SDK replenishes them automatically
|
|
//! - This is the foundation for anonymous communication: the server never
|
|
//! learns who is talking to it
|
|
//!
|
|
//! ```sh
|
|
//! cargo run --example surb_reply
|
|
//! ```
|
|
|
|
use nym_sdk::mixnet::{
|
|
AnonymousSenderTag, MixnetClientBuilder, MixnetMessageSender, ReconstructedMessage,
|
|
StoragePaths,
|
|
};
|
|
use std::path::PathBuf;
|
|
use tempfile::TempDir;
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
nym_bin_common::logging::setup_tracing_logger();
|
|
|
|
// Build a client with persistent key storage.
|
|
// Keys are generated on first run, then loaded from disk on subsequent runs.
|
|
let config_dir: PathBuf = TempDir::new().unwrap().path().to_path_buf();
|
|
let storage_paths = StoragePaths::new_from_dir(&config_dir).unwrap();
|
|
let client = MixnetClientBuilder::new_with_default_storage(storage_paths)
|
|
.await
|
|
.unwrap()
|
|
.build()
|
|
.unwrap();
|
|
let mut client = client.connect_to_mixnet().await.unwrap();
|
|
let our_address = client.nym_address();
|
|
println!("\nOur client nym address is: {our_address}");
|
|
|
|
// Send a message to ourselves.
|
|
client
|
|
.send_plain_message(*our_address, "hello there")
|
|
.await
|
|
.unwrap();
|
|
|
|
// Receive the message.
|
|
println!("Waiting for message\n");
|
|
let mut message: Vec<ReconstructedMessage> = Vec::new();
|
|
// Filter empty messages: these are SURB replenishment requests.
|
|
while let Some(new_message) = client.wait_for_messages().await {
|
|
if new_message.is_empty() {
|
|
continue;
|
|
}
|
|
message = new_message;
|
|
break;
|
|
}
|
|
|
|
let parsed = String::from_utf8(message[0].message.clone()).unwrap();
|
|
|
|
// Extract the AnonymousSenderTag from the incoming message.
|
|
// This opaque token lets you reply without knowing the sender's address.
|
|
// The SDK includes SURBs with every message by default.
|
|
let return_recipient: AnonymousSenderTag = message[0].sender_tag.unwrap();
|
|
println!("Received: {parsed}\nSender tag: {return_recipient}");
|
|
|
|
// Reply anonymously using send_reply() instead of send_plain_message().
|
|
println!("Replying using SURBs...");
|
|
client
|
|
.send_reply(return_recipient, "hi an0n!")
|
|
.await
|
|
.unwrap();
|
|
|
|
// Receive the reply.
|
|
println!("Waiting for reply (ctrl-c to exit)\n");
|
|
client
|
|
.on_messages(|msg| println!("Received: {}", String::from_utf8_lossy(&msg.message)))
|
|
.await;
|
|
}
|