1
0
forked from GRIN/grim
2ro dfbd85c7b3 nostr: keep contact @usernames fresh; clear released/reassigned names
Cached names were verified once and never re-checked, so a contact who
released or changed their username kept showing the stale name forever.
Re-validate names on a 78s sweep (capped per tick to bound mixnet lookups):

- nip05::check — tri-state Verified/Mismatch/Unreachable, so we only clear on
  a definitive server answer (released, or reassigned to a different key),
  never on a network blip.
- resolve_contact_identity now re-checks names older than the freshness window
  and clears nip05 + nip05_verified_at on Mismatch (a user petname is kept);
  display falls back to the npub automatically.
- A periodic sweep in run_service re-verifies the stalest due contacts.

Tests for the tri-state parsing and the clear-keeps-petname logic.
2026-06-16 01:39:54 -04:00
2026-05-03 10:05:03 +03:00
2024-04-14 14:04:34 +03:00

Goblin

Goblin

Goblin is a private, pay-by-username wallet for GRIN ツ — confidential digital cash on Mimblewimble, with no amounts or addresses on the chain.

Instead of passing slatepack files back and forth, you pay a username (or an npub) and the payment is delivered for you as an end-to-end encrypted message over nostr, routed through the Nym mixnet. Relays only ever see ciphertext — never the amount, the sender, or the recipient — and the mixnet hides who is talking to whom at the network layer.

Goblin is a fork of the Grim egui GRIN wallet: it keeps Grim's full GRIN node/wallet engine and layers a Nostr-native, mobile-first payments experience on top.

What it does

  • Send to people — pay a username or npub; the GRIN slatepack travels as a NIP-17 gift-wrapped DM (kind 1059) over the Nym mixnet and is applied automatically by the recipient's wallet. No files to swap, no need to both be online at once.
  • Manual slatepacks too — when you need to pay or get paid without a handle, Settings → Wallet → Slatepacks exposes the classic by-hand flow: create a slatepack to send, or paste one to receive, finalize, or pay.
  • In-app identity — a nostr payment key that is deliberately not part of your seed, so you can rotate it any time to stay unlinkable without touching your funds. An optional human-readable name comes from the goblin.st identity service.
  • Private by construction — GRIN's address-less, confidential chain; your payments and identity (nostr relays, NIP-05 lookups, price) are routed through the Nym mixnet, so who-pays-whom never touches the clear net. The GRIN node connection — block sync and broadcasting your transaction — is direct: public chain data, the same for everyone, and not tied to your identity. Keys, names and history stay on your device.
  • Configurable amount pairing — show balances against a world currency, Bitcoin, or sats (rates fetched over the mixnet), or turn the preview off.
  • Cross-platform — Linux, macOS, Windows, Android, built in pure Rust on egui.

How a payment travels

   you ──slatepack──▶ NIP-17 gift wrap (kind 1059, NIP-44 encrypted)
                          │
                   Nym mixnet (5-hop)
                          │
            ┌─────────────┴─────────────┐
        your relays              recipient's DM relays (kind 10050)
            └─────────────┬─────────────┘
                          ▼
   recipient ◀──unwrap, verify seal author, apply slatepack

The wrap is NIP-44-encrypted, and delivery uses the recipient's DM relay list (kind 10050).

Both parties only need one relay in common. The default set is the Goblin relay plus large public relays (relay.damus.io, nos.lol), and the set is editable in Settings → Relays.

Build

Desktop (Linux / macOS / Windows)

Goblin links the Nym mixnet SDK in-process — the wallet is a single self-contained binary, no sidecar. The SDK builds from a sibling ../nym checkout (a pinned nym tree with a small Android TLS patch):

git clone --branch goblin https://git.us-ea.st/GRIN/nym ../nym
git submodule update --init --recursive
cargo build --release
./target/release/goblin

Goblin's identity and payment traffic — nostr relays, NIP-05 lookups, price and avatar fetches — is routed over the mixnet through a network requester (the default is baked into NETWORK_REQUESTER in src/nym/sidecar.rs); the SDK's SOCKS5 listener is run in-process on 127.0.0.1:1080. If something is already listening there, Goblin reuses it. The GRIN node connection (block sync and transaction broadcast) is not mixed — it connects directly, as it carries only public chain data that isn't linked to your wallet.

Android

Install the Android SDK / NDK, then from the repo root:

./scripts/android.sh build|release v7|v8|x86

v7/v8/x86 is the device CPU architecture for build; for release pass a version in major.minor.patch form.

Identity service (goblin-nip05d)

The optional name + avatar service lives in goblin-nip05d/ (axum + SQLite) and is deployed at goblin.st. It implements NIP-05 resolution, NIP-98-authenticated registration/transfer/release, and a hardened avatar pipeline (magic-byte sniffing, bounded decode, full re-encode to a clean 256×256 PNG). The wallet is fully usable — and fully anonymous — without it.

License

Apache License v2.0.

Credits

🤖 Built with AI pair-programming assistance (Claude)

The underlying cross-platform GRIN wallet engine is the upstream Grim project.

S
Description
No description provided
Readme Apache-2.0 26 MiB
Languages
Rust 95.9%
Java 2.7%
Shell 1.3%
Python 0.1%