灵符lingfu
L

ling-wallet

↓ 0 downloads

Ling Wallet: a post-quantum privacy-coin wallet, full node and HyperTorus miner for LNG

Windows · x86-64 ✕Linux · x86-64 ✕LingOS · x86-64LingOS · Pi 5 ARM64 ✕
Keywords wallet, cryptocurrency, lng, node, miner, ling
lingfu install ling-wallet
LicenseMIT
Authorsling-lin
READMECode / FilesVersionsDependency GraphDependentsSecurityBuildsSettings

Code / Files (116)

README.md
<div align="center">

# 🪙 Ling Wallet

### A post-quantum privacy wallet, full node and miner for **LNG** — in one app, written entirely in [Ling](https://ling-lang.org).

`post-quantum` · `private by default` · `no accounts, no KYC` · `wallet + node + miner` · `one language`

</div>

![Ling Wallet — balance and activity](ling/screenshots/wallet.png)

> [!WARNING]
> **LNG is a new, unaudited, experimental coin.** The cryptography is built on
> standard primitives, but the ring signature and proof-of-work are novel, the
> network is small, and nothing here has had an external security review. Read
> [`docs/THREAT_MODEL.md`](docs/THREAT_MODEL.md) before trusting it with anything
> you can't afford to lose.

---

## ✨ What makes it different

Most coins were designed before quantum computers were a planning concern, and
most wallets are a thin client that trusts someone else's node. Ling Wallet is
built the other way around:

| | |
|---|---|
| 🔐 **Post-quantum from day one** | Identities, key exchange and the wallet file use **ML-DSA-87**, **ML-KEM-1024** and **X25519** in hybrid — an attacker who records your traffic today still can't read it after quantum computers arrive. |
| 🥷 **Private by default** | Every payment uses a **fresh one-time address**, a **ring signature** over same-value decoys, and fixed denominations. There is no "transparent mode" to forget to turn on. |
| 🧅 **Network privacy built in** | **Dandelion++** hides which node made a transaction, frames are padded with cover traffic, and all outbound traffic can go over **Tor** with no DNS leaks. |
| 🏠 **You are the node** | The app *is* a full node. It validates the whole chain itself — it never asks a server for your balance, so no one learns your addresses by watching your queries. |
| ⛏️ **Mine from the same app** | A background miner runs on spare cores, visualized as a 4-D **HyperTorus** walk. No pool, no separate software. |
| 🧬 **One language, no C** | Node, wallet, miner, UI and tests are all **Ling**. The whole thing is readable top to bottom, with no foreign-function glue. |

---

## 🆚 How it compares

An honest comparison. Ling Wallet leads on *design* — post-quantum security and
privacy that's on by default — while established coins lead on *maturity*: they
are audited, have huge anonymity sets, and have survived years of attack.

| | **Bitcoin** | **Monero** | **Zcash** | **🪙 Ling Wallet / LNG** |
|---|:---:|:---:|:---:|:---:|
| **Private by default** | ❌ transparent | ✅ always | ⚠️ opt-in (shielded) | ✅ always |
| **Post-quantum** | ❌ ECDSA | ❌ Ed25519 | ❌ | ✅ **hybrid PQ** |
| **Hidden recipient** | ❌ | ✅ stealth addrs | ✅ shielded | ✅ one-time keys |
| **Hidden sender** | ❌ | ✅ ring sigs | ✅ zk-SNARKs | ✅ **lattice ring sigs** |
| **No trusted setup** | ✅ | ✅ | ⚠️ (historically) | ✅ |
| **Built-in full node** | ⚠️ separate | ⚠️ separate | ⚠️ separate | ✅ **in the app** |
| **Built-in miner** | ❌ (pools) | ⚠️ separate | ❌ | ✅ **in the app** |
| **Tor / Dandelion++** | ⚠️ add-on | ✅ | ⚠️ partial | ✅ built in |
| **Accounts / KYC** | none | none | none | **none** |
| **Supply cap** | 21 M | ∞ (tail) | 21 M | **21 M + tail** |
| **Maturity** | 🟢 battle-tested | 🟢 audited | 🟢 audited | 🔴 **experimental, unaudited** |
| **Anonymity set** | 🟢 huge | 🟢 huge | 🟡 medium | 🔴 **small (new)** |

**The honest summary:** if you need proven, audited money today, use an
established coin. If you want to see what a wallet looks like when **post-quantum
security and default privacy are the starting point, not a retrofit** — and you
treat it as the experiment it is — that's Ling Wallet.

---

## 🛡️ The security stack

Every layer, and whether it's a vetted standard or something new:

```
┌─────────────────────────────────────────────────────────────────────┐
│  🔑  IDENTITY & SIGNING      ML-DSA-87  (FIPS 204)          [standard]│
│  🤝  KEY EXCHANGE            X25519 + ML-KEM-1024 (FIPS 203)[standard]│
│  🔒  ENCRYPTION              XChaCha20-Poly1305             [standard]│
│  🧂  PASSWORD → KEY          Argon2id  256 MiB · 3 passes   [standard]│
│  #️⃣  HASHING                 SHAKE256 (SHA-3)               [standard]│
│  🥷  SENDER PRIVACY          LRS-87 lattice ring signatures [experimental]│
│  🧅  NETWORK PRIVACY         Dandelion++ · padded frames · Tor        │
│  ⛏️  PROOF OF WORK           HyperTorus memory-hard walk    [novel]   │
└─────────────────────────────────────────────────────────────────────┘
   standard     = NIST-standardized or widely vetted
   experimental = research-grade, flagged in the UI
   novel        = designed here; a flaw can at worst speed up mining
```

The **About** page inside the app lists every one of these with its status, and
[`docs/THREAT_MODEL.md`](docs/THREAT_MODEL.md) spells out exactly what each does
and does **not** protect — including a known sender-tracing leak and its
mitigation.

---

## 🏗️ How the app is built

The UI never touches keys or the network. Each job runs in its own **isolate**
(a sandboxed thread) with only the capabilities it needs, and they talk over
channels:

```mermaid
graph TD
    UI["🖥️  UI thread<br/>windows · input · drawing<br/><i>no capabilities to keys</i>"]
    W["🔑  walletd isolate<br/>keys · scanning · signing<br/><i>caps: keys, db, fs</i>"]
    N["🌐  node isolate<br/>chain · mempool · P2P<br/><i>caps: db, fs, p2p</i>"]
    M["⛏️  miner isolates ×N<br/>one per core<br/><i>no capabilities</i>"]
    NET(["🧅  LWP-1 network<br/>peers · Tor"])

    UI <-->|"requests<br/>(wiped channel)"| W
    UI <-->|status| N
    W <-->|"tip · submit · bundles"| N
    N <-->|templates| M
    M -->|solved blocks| N
    N <-->|encrypted frames| NET
```

- The **node** holds `p2p` but never `keys` — a network attacker who found a bug
  in it still can't reach your spending keys.
- The **wallet** holds `keys` but never `p2p` — it never talks to the internet.
- **Miners** get **no** capabilities at all.
- The UI asks the wallet for things over a **separate, wiped channel**, so
  passwords and seed words don't linger.

---

## 📸 A look inside

| | | |
|:---:|:---:|:---:|
| ![Wallet](ling/screenshots/wallet.png) **Balance & activity** | ![Send](ling/screenshots/send.png) **Send to a verified address** | ![Receive](ling/screenshots/receive.png) **Your address & QR** |
| ![Mining](ling/screenshots/mining.png) **HyperTorus miner** | ![Network](ling/screenshots/network.png) **Peers & supply audit** | ![Security](ling/screenshots/security.png) **Phrase & auto-lock** |

---

## 🚀 Quick start

Ling Wallet runs on the [Ling](https://ling-lang.org) runtime — one build gives
you both `ling` and the `lingfu` package tool.

```sh
cd ../ling && cargo build --features web          # once (builds ling and lingfu)
cd ../ling-wallet
lingfu run            # live node — connects to the network and syncs
lingfu run --mock     # simulated backend — no network, for a look around
```

`lingfu run` reads `entry` from [`Ling.toml`](Ling.toml) and runs
`ling/main.ling`. Any flags after `run` are passed through to the wallet:

| flag | default | meaning |
|---|---|---|
| `--data-dir D` | `%APPDATA%\LingWallet\mainnet` | wallet file, chain database, peer data |
| `--listen HOST:PORT` | `0.0.0.0:18780` (`none` with `--proxy`) | where this node accepts peers; `none` = outbound only |
| `--peer HOST:PORT` | — | a peer to connect to (repeatable) |
| `--proxy 127.0.0.1:9050` | — | send **all** connections through Tor / SOCKS5 |
| `--mock` | — | simulated backend (UI development, screenshots) |

Your 24-word recovery phrase **is** your wallet — write it on paper, store it
safely, and never photograph it. Keys never leave your computer.

---

## 🌐 Running on a real network

Nodes find each other through **seeds**: always-on nodes listed in a file signed
by the seed authority (`keys/seed-authority.key`, whose public key is compiled
into every wallet). A tampered list is ignored. Once connected, nodes gossip the
other reachable nodes they know, so a wallet needs only one working seed.

**1. Run a seed node** on a machine with a public IP or DNS name (a VPS, or a
home PC with TCP 18780 forwarded), and open TCP 18780 in its firewall:

```sh
ling run ling/seednode.ling --data-dir /srv/lng --mine 2 --pay-to @payout.txt
```

It writes its identity public key to `/srv/lng/node_identity.pub`. `--pay-to` is
where block rewards go — a wallet's key bundle (**Receive → Copy bundle**, the
`lngkey1…` text) or `@file` holding it. Without one, `--mine` does nothing. The
node remembers the address, so later starts can drop `--pay-to`.

**2. Sign a seed list** naming it (on the machine holding the authority key):

```sh
ling run ling/tools/seeds.ling sign --authority keys/seed-authority.key \
    --out ling/assets/seeds.lwseeds seed.example.org:18780=@node_identity.pub
ling run ling/tools/seeds.ling show ling/assets/seeds.lwseeds
```

**3. Ship it.** `ling/assets/seeds.lwseeds` goes out with the wallet, and every
wallet installs it into its data folder on start when it's newer. A wallet with
a seed list needs no `--peer`.

> 💡 A home IP can change — give the seed a **DNS name** and sign the list with
> that, so an IP change only needs a DNS update, not a new list in every wallet.
> Wallets behind a router need nothing forwarded (they connect out); forwarding
> the port only makes a node reachable so it can help relay.

---

## ⚠️ Honest limitations

This is where an experiment differs from money you'd rely on:

- **No external audit.** The code has had internal review (see
  [`docs/THREAT_MODEL.md`](docs/THREAT_MODEL.md)) and nothing more.
- **Novel crypto.** The LRS-87 ring signature is research-grade and has had no
  independent cryptanalysis. There is a known **sender-tracing** leak: whoever
  *paid you* can tell when you later spend those exact coins — churn coins from
  parties you don't trust.
- **Small anonymity set.** Ring signatures hide you among others holding the same
  denomination; while few people use LNG, there are few to hide among. The wallet
  flags "reduced ring" spends.
- **Visible amounts.** Each output is a public standard denomination (post-quantum
  hidden amounts aren't practical yet); a payment's *total* isn't linked, though.
- **Malware is out of scope.** If someone controls your computer, they can read
  keys as you type. Use a dedicated, encrypted, up-to-date machine.

---

## 📁 Layout

```
ling/
  main.ling            window + frame loop
  backend.ling         be_* contract → real_backend.ling or mock.ling
  real_backend.ling    spawns and talks to the isolates below
  seednode.ling        headless seed node for a server
  isolates/node.ling     chain, mempool, P2P      (caps: db, fs, p2p)
  isolates/walletd.ling  keys, scanning, signing  (caps: keys, db, fs)
  isolates/miner.ling    one per core             (no capabilities)
  core/                consensus: params, codec, money, chain, mempool, wallet
  ui/                  screens, widgets, theme, HyperTorus visualizer
  tools/seeds.ling     node identity · sign / show seed lists
  tests/               crypto, threads, p2p, chain, nodes test programs
  selftest.ling        drives the real backend end to end
docs/                  DESIGN (consensus spec), THREAT_MODEL, LING_API, LING_BACKEND
```

## 🧪 Tests

```sh
cd ling/tests/crypto  && ling run --interp t_crypto.ling   # 204 checks
cd ling/tests/threads && ling run --interp t_basic.ling    # 72
cd ling/tests/p2p     && ling run --interp t_p2p.ling      # 71
cd ling/tests/chain   && ling run --interp t_chain.ling    # 19: mine, send, double-spend, reorg
cd ling/tests/nodes   && ling run --interp t_nodes.ling    # 7: two nodes sync over P2P
cd ling && ling run --interp selftest.ling --data-dir <empty dir> --fast-kdf 1 --listen 127.0.0.1:18795   # 22
```

---

<div align="center">

**Built with [Ling](https://ling-lang.org)** · MIT license · an experiment, not a bank

*Read [`docs/THREAT_MODEL.md`](docs/THREAT_MODEL.md) before you trust it.*

</div>

← Back to index