Skip to content

zig-nostr/nostr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

45 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

nostr

The Nostr protocol, natively in Zig.

CI License: MIT

nostr is a foundational Nostr protocol library for Zig β€” keys and signatures, events, relay transport with the outbox model, a zero-copy local-first event store, and the NIP-46 remote-signing protocol. It's the base layer a fast, native Nostr app is built on: no browser, no Electron, the protocol running close to the metal.

It's also the core of a small ecosystem β€” the library, plus native apps built on it like Signet, a remote signer that keeps your key off every client. Full docs, benchmarks, and the ecosystem overview live at zignostr.com.

Status: pre-alpha (v0.3.5). The library core, transport, local-first store, and signer protocol have shipped and are covered by tests. APIs may still change before 1.0.

Highlights

  • πŸ”‘ Credible crypto core β€” secp256k1 keys and BIP-340 Schnorr signatures via bitcoin-core's libsecp256k1, passing the full official test-vector suite (19/19).
  • ⚑ Local-first store β€” a zero-copy, memory-mapped LMDB event store with a bounded, newest-first query planner: sub-millisecond feeds that stay flat as the store grows.
  • 🧭 Outbox model β€” NIP-65 relay lists with read/write routing and zero hardcoded relays; events go where they belong.
  • πŸ”’ Encrypted payloads β€” NIP-44 v2 authenticated encryption (ChaCha20 + HMAC-SHA256), verified against the official vectors.
  • πŸ›‘οΈ Remote signing β€” the NIP-46 "bunker" protocol plus NIP-42 relay auth, so a key can sign for any client without ever entering it.
  • πŸ” Portable keys β€” NIP-06 mnemonic derivation and NIP-49 (ncryptsec) encrypted key storage, NFKC-normalized for cross-app interop.

Performance

Performance is a design goal, not an afterthought. These are the library's own numbers β€” measured with the in-repo benchmark and reproducible on your machine (Apple Silicon, ReleaseFast, warm cache, best of 50; events spread across 100 authors; a 20-author kind:1 feed returning 500 notes):

Store size Feed query (500 notes) Profile query Ingest
20,000 events 0.26 ms 0.09 ms ~135k events/s
100,000 events 0.28 ms 0.25 ms ~135k events/s

The headline isn't the ~0.28 ms feed query β€” it's that 5Γ— more stored events barely moves it. The bounded query planner walks the indexes newest-first and stops at limit, so latency tracks the page size you ask for, not the size of the store.

BENCH_N=100000 zig build bench -Doptimize=ReleaseFast

Methodology and the full write-up are on the benchmarks page.

Quickstart

Add the library to your build.zig.zon:

zig fetch --save https://github.com/zig-nostr/nostr/archive/refs/tags/v0.3.5.tar.gz

Wire the module in build.zig:

const nostr = b.dependency("nostr", .{ .target = target, .optimize = optimize });
your_module.addImport("nostr", nostr.module("nostr"));

Sign and verify an event:

const std = @import("std");
const nostr = @import("nostr");

pub fn main() !void {
    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena.deinit();
    const allocator = arena.allocator();

    // A Signer wraps the libsecp256k1 context; deinit it when done.
    var signer = nostr.keys.Signer.init();
    defer signer.deinit();

    // Load a keypair from a 32-byte secret key.
    const secret: nostr.keys.SecretKey = your_secret_key; // 32 bytes
    const keypair = try signer.keyPairFromSecretKey(secret);

    // Build and sign a kind:1 text note.
    const note = try nostr.event.create(
        allocator, signer, keypair,
        std.time.timestamp(), 1, &.{}, "hello from zig-nostr", null,
    );

    // Verify: recompute the canonical id, then check the Schnorr signature.
    std.debug.assert(try nostr.event.verify(allocator, signer, note));

    // Serialize to the wire JSON form.
    const json = try nostr.event.toJson(allocator, note);
    std.debug.print("{s}\n", .{json});
}

The nostr module re-exports focused namespaces: keys, event, nip19/bech32, nip06/bip39, nip49, nip44, nip46, nip42, relay/websocket/message/filter, nip65, and store. See the getting-started guide for more.

NIP support

Every "done" NIP is covered by tests; the cryptographic ones are verified against their official specification vectors.

NIP Title Status
01 Basic protocol: events, signatures, subscriptions βœ…
06 Key derivation from mnemonic seed βœ…
09 Event deletion (ingestion) βœ…
19 bech32-encoded entities βœ…
21 nostr: URI scheme βœ…
42 Client-to-relay authentication βœ…
44 Encrypted payloads (v2) βœ…
46 Nostr Connect β€” remote signing βœ…
49 Private key encryption (ncryptsec) βœ…
65 Relay list metadata (outbox) βœ…
17 Private direct messages 🚧 planned
59 Gift wrap 🚧 planned
10 Reply threading 🚧 planned

Planned NIPs arrive with the showcase apps below.

Built with it

The library is proven by native apps built on it β€” the ecosystem forming around one core:

  • Signet β€” shipped. A native macOS remote signer (NIP-46 bunker): your key lives in a local daemon, every signing request waits for your approval, and the nsec never enters a client.
  • Plaza β€” in progress. The flagship: a fast, local-first client organized around community "places," where you browse and post within two minutes and the feed renders from disk.
  • Messenger β€” planned. Private NIP-17 direct messages, signing through Signet.

Roadmap

The library foundation has shipped β€” keys, transport, the local-first store, and the signer protocol. The flagship client is in progress, followed by a one-year roadmap of more NIPs, utility libraries, additional apps, and more platforms (desktop and mobile).

See CURRENT_STATE.md for exactly what's in progress, the roadmap for the sequence, and the project board for the milestone tracker.

Development

zig build          # build the library
zig build test     # run the test suite
zig fmt --check .  # verify formatting

The Zig version is pinned in .zigversion. The library vendors and compiles libsecp256k1 and LMDB from source, so no system packages are required.

Contributing

See CONTRIBUTING.md for the branch/PR/commit workflow and AGENTS.md for a contributor- and agent-facing tour of the codebase.

License

MIT β€” see LICENSE.

About

The Nostr protocol library for Zig

Topics

Resources

License

Contributing

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors