cbcl on nostr
|
Anuna 02
170557e513
feat: add WASM compilation support
Replace secp256k1 (C FFI) with k256 (pure Rust) for cross-platform crypto. Replace rand::thread_rng() with getrandom crate for WASM-compatible randomness. Gate relay pool (tokio/WebSocket) behind optional `relay` feature. Add `wasm` feature flag with web-time for Instant and getrandom/js for browser entropy. Native: cargo build (default features, unchanged) WASM: cargo build --target wasm32-unknown-unknown \ --no-default-features --features std,wasm Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .hence | Initial commit: cbcl-nostr library with clean repo structure | |
| crates/cbcl-nostr | feat: add WASM compilation support | |
| plans | Initial commit: cbcl-nostr library with clean repo structure | |
| specs | Initial commit: cbcl-nostr library with clean repo structure | |
| .gitignore | Initial commit: cbcl-nostr library with clean repo structure | |
| README.md | Initial commit: cbcl-nostr library with clean repo structure | |
cbcl-nostr
A Rust library implementing NIP-XX — structured agent-to-agent communication over Nostr using CBCL S-expressions.
What is this?
Nostr provides signed events, relay-based delivery, and public key identity. CBCL provides formally specified message semantics with 8 core performatives (tell, ask, reply, ok, error, cancel, hello, bye) and safe runtime dialect extension.
This crate combines both: agents get a global, censorship-resistant communication network with unambiguous, machine-parseable messages.
Event kinds
| Kind | Description |
|---|---|
| 21111 | Agent message (regular) |
| 31111 | Agent dialect (addressable) |
Features
- S-expression codec — parse and serialize CBCL in Nostr event
contentfields - Typed event wrappers —
AgentMessage(kind 21111) andAgentDialect(kind 31111) with strongly-typed tags - Event signing — secp256k1 Schnorr signatures per NIP-01
- Gift wrap encryption — NIP-59 two-layer encrypted envelopes for private agent messaging
- Relay pool — async WebSocket connections to multiple Nostr relays
- Dialect negotiation — runtime extension of performatives with safety verification
- Agent discovery — find agents by capability via hello/bye broadcast protocol
- Commerce dialects — task market, bounties, and zap integration
- Spam prevention — proof-of-work and reputation-based filtering
- Payment safety — escrow patterns and payment verification
Usage
Building messages
usecbcl_core::sexpr::{Atom,SExpr};usecbcl_nostr::message_builder::MessageBuilder;// Send a directed message
letevent=MessageBuilder::new("tell").recipient("abc123...")// recipient's hex pubkey
.body(vec![SExpr::Atom(Atom::Symbol("@abc123...".into())),SExpr::Atom(Atom::Str("Deploy the frontend to staging".into())),]).thread("conv-17").build()?;// event.content == r#"(tell @abc123... "Deploy the frontend to staging")"#
// Ask a question with a dialect
letevent=MessageBuilder::new("ask").recipient("def456...").body(vec![SExpr::Atom(Atom::Symbol("@def456...".into())),SExpr::Atom(Atom::Str("What's the price?".into())),]).dialect("commerce").build()?;// Broadcast presence
letevent=MessageBuilder::new("hello").build()?;// event.content == "(hello)"
Signing and verifying events
usecbcl_nostr::event_signing::{sign_event,verify_event};letmutevent=MessageBuilder::new("tell").recipient("abc123...").body(vec![SExpr::Atom(Atom::Str("hello".into()))]).build()?;// Sign with your secret key and current timestamp
sign_event(&mutevent,"your_secret_key_hex",1700000000)?;// Verify a received event's ID and Schnorr signature
verify_event(&event)?;Parsing S-expressions from events
usecbcl_nostr::sexpr_codec::{decode,encode};// Parse a CBCL message from a Nostr event content field
letexpr=decode(r#"(tell @bob "Deploy to staging" :thread "conv-17")"#)?;// Serialize back to a string
letcontent=encode(&expr);Agent discovery
usecbcl_nostr::agent_discovery::{build_hello,build_bye,AgentRegistry};// Announce your agent's presence
lethello_event=build_hello("assistant",&["chat","code-review"])?;// Track discovered agents
letmutregistry=AgentRegistry::new();registry.process_event(&incoming_event)?;// Find agents by iterating
foragentinregistry.agents(){println!("{}: {:?}",agent.pubkey,agent.capabilities);}// Clean up stale agents (older than cutoff timestamp)
registry.evict_stale(cutoff_timestamp);// Depart gracefully
letbye_event=build_bye()?;Private messaging with gift wrap (NIP-59)
usecbcl_nostr::gift_wrap::{gift_wrap,unwrap_gift};// Wrap a message in a two-layer encrypted envelope
// (rumor → seal → gift wrap with ephemeral key)
letrumor=MessageBuilder::new("tell").recipient(&recipient_pk).body(vec![SExpr::Atom(Atom::Str("secret task".into()))]).build()?;letwrapped=gift_wrap(rumor,&sender_sk,&recipient_pk,now)?;// wrapped.kind == 1059, sender identity hidden behind ephemeral key
// Recipient unwraps to get the original message + verified sender
letresult=unwrap_gift(&wrapped,&recipient_sk)?;assert_eq!(result.rumor.content,r#"(tell "secret task")"#);assert_eq!(result.sender_pubkey,sender_pk);NIP-44 encryption primitives
usecbcl_nostr::event_signing::{conversation_key,nip44_encrypt,nip44_decrypt};// Derive a shared conversation key via ECDH + HKDF
letck=conversation_key(&my_secret_key_hex,&their_pubkey_hex)?;// Encrypt/decrypt with ChaCha20-Poly1305 + HMAC
letciphertext=nip44_encrypt(&ck,"hello, agent!")?;letplaintext=nip44_decrypt(&ck,&ciphertext)?;Project layout
crates/cbcl-nostr/ Rust library
src/
lib.rs Crate root — re-exports all modules
sexpr_codec.rs Parse/serialize CBCL S-expressions
event_types.rs Kind 21111/31111 event structs and typed tags
event_signing.rs NIP-01 signing, verification, NIP-44 encryption
message_builder.rs Builder API for agent messages
gift_wrap.rs NIP-59 two-layer encrypted envelopes
agent_discovery.rs Hello/bye broadcast and agent registry
dialect_negotiation.rs Runtime dialect extension
relay_pool/ Async WebSocket relay connections
...
tests/ Integration and property-based tests
specs/ Protocol specifications (NIP-XX)
plans/ Implementation plans (SPL)
Requirements
- Rust 1.75+
- Depends on
cbcl-coreandcbcl-parserfrom cbcl-rs
License
Apache-2.0