PoW and outbound Nostr events

June 20, 2026 · View on GitHub

This document describes how Mostrix applies NIP-13 proof-of-work to events it publishes toward Mostro and related flows. It is intended for contributors and AI-assisted codegen so outbound signing behavior stays consistent with the Mostro instance policy.

Source of difficulty

Cached instance info at runtime

At startup (and on reload/reconnect via dm_transport_for_mostro), instance info is fetched before the DM listener spawns when relays are reachable.

Protocol v2 (NIP-44 direct) — outbound

send_dm uses wrap_message_with from mostro-core:

  • v1 (GiftWrap): PoW on the outer kind-1059 envelope (via mostro-core nip59::wrap_message).
  • v2 (Nip44Direct): PoW on the signed kind-14 event (WrapOptions.pow).
  • NIP-40 expiration: default now + 30 days on v2 when the caller passes expiration: None (default_dm_expiration).

First-contact actions on strict v2 nodes may need higher PoW than instance pow (pow_first_contact on the daemon). Mostrix applies max(pow, pow_first_contact) on v2 for NewOrder, TakeBuy, and TakeSell via nostr_pow_for_protocol_dm. When the kind-38385 pow_first_contact tag is absent, the effective toll defaults to base pow (same as the daemon).

Chat vs protocol PoW

Call sites (high level)

Order flows under src/util/order_utils/, admin actions in src/ui/key_handler/admin_handlers.rs, and rating handlers in src/ui/key_handler/message_handlers.rs pass cached mostro_instance into send_dm.