9db748e8dd
* Improve SDK rustdoc and add ARCHITECTURE.md files - Rewrite lib.rs module docs with quick-start example and module overview - Add stream example and include_str! ARCHITECTURE.md to mixnet module - Add ARCHITECTURE.md for mixnet, client_pool, and stream modules - Add rustdoc to MixnetClientBuilder, MixnetClientSender, MixnetMessageSender - Add cancel safety and drop behavior annotations to async methods - Add TcpProxy deprecation notice pointing to stream module * Fix rustdoc errors and add stepwise comments to remaining examples Rustdoc fixes: - Add missing .unwrap() on connect_new example - Replace broken turbofish intra-doc link in MixnetClientBuilder - Fix NymProxyServer::new args in tcp_proxy example - Wrap BandwidthImporter example in scoped block to fix borrow-then-move - Change misleading "5-hop routing" to "multi-hop routing" - Fix copy-paste "forget me" in send_remember_me error message - Fix wrong cargo run command in stream_simple_read_write - Fix DecayWrapper description * Cut down doc comment length * Trimmed down SDK ARCHITECTURE files * Slim Rust SDK docs and rename opener to dialer - Merge tour page into SDK landing page, delete tour.mdx - Trim all three tutorials: cut boilerplate, duplicated code, and misplaced content - Make FFI page evergreen with Go and C++ snippets, link to repo examples - Rename "opener" to "dialer" in stream docs, source ARCHITECTURE.md, and rustdoc - Add reply-to-open arrow in stream mermaid diagram - Replace remaining Unicode dashes in mermaid flowchart * - elevate streams in rustdoc: examples on lib.rs, MixnetClient, open_stream, listener - add stream quick reference to mixnet ARCHITECTURE.md - add stream types to key types list in ARCHITECTURE.md - add docs.rs links for AsyncRead/AsyncWrite and stream submodule - tcp_proxy: replace bold deprecation with warning box * - replace individual example doc pages with GitHub-linked tables - add step-by-step inline comments to all SDK example source files - add doc comments to examples missing them (simple, surb_reply, builder, etc.) - expand mixnet tutorial with persistent identity and split_sender sections - add tcpproxy tutorial - rename "API Reference" to "TypeDoc Reference" in TS SDK sidebar - rename "Misc" to "Extras" in developer sidebar, move VPN CLI up - remove echo server from tools - update message-queue callout to reference actual modules - fix mixnet/examples redirect collision * Add missing mut to example code * Update ARCHITECTURE.md with LP Framing + stream examples with sequencing * Update doc comment in utils.rs * Standardise commenting style across Rust SDK examples * Fix inline doc examples and trim re-export boilerplate * Update sdk/rust/nym-sdk/examples/bandwidth.rs Co-authored-by: Simon Wicky <simon@nymtech.net> * Fix review comments --------- Co-authored-by: Simon Wicky <simon@nymtech.net>
73 lines
2.6 KiB
Rust
73 lines
2.6 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 includes SURBs with every message
|
|
//! by default, so the recipient can always reply anonymously.
|
|
//!
|
|
//! Run with: 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;
|
|
}
|