灵符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)

ling/ui/about.ling
# about.ling — ABOUT: the cryptography and known limitations shown as clickable
# badges. Click a badge on the left to read what it is on the right. Each card is
# [label, title, status, description]; status drives the colour and the credit line
# ("novel"/"experimental" pieces are LNG originals — © Ling Country).

bind ABOUT_CARDS = [
    ["ML-DSA-87", "Identity signatures — ML-DSA-87", "standard",
     "The post-quantum signature scheme standardised as FIPS 204 (Dilithium, level 5). Every wallet address bundle and every peer handshake is signed with it, so identities can't be forged even by a quantum adversary. It replaces the elliptic-curve signatures a classical coin would use."],
    ["X25519 + ML-KEM-1024", "Key exchange — hybrid KEM", "standard",
     "Shared secrets combine X25519 (classical elliptic-curve Diffie-Hellman) with ML-KEM-1024 (FIPS 203, lattice key encapsulation). The result is secure as long as EITHER one holds, so a future break of one primitive doesn't expose traffic. Used for the encrypted P2P transport and stealth-address secrets."],
    ["XChaCha20-Poly1305", "Authenticated encryption", "standard",
     "The AEAD cipher that encrypts the wallet file on disk, transaction memos, and every network frame. 24-byte random nonces (XChaCha) mean nonce reuse isn't a practical worry, and the Poly1305 tag detects any tampering."],
    ["Argon2id", "Password hashing", "standard",
     "Turns your wallet password into the file-encryption key with a deliberately slow, memory-hard function: 256 MiB of memory and 3 passes. That makes brute-forcing the password on GPUs or ASICs enormously expensive compared with a plain hash."],
    ["SHAKE256", "Hashing", "standard",
     "The SHA-3 extendable-output function is the single hash used throughout, always with a domain-separation prefix (\"LW1/...\") so a hash computed for one purpose can never be mistaken for another. Block IDs, Merkle trees, key derivation and the PoW finaliser all use it."],
    ["DICE-42", "Network wire layer", "novel",
     "An extra cascade cipher wrapped around frames that are ALREADY encrypted with XChaCha20-Poly1305. It is defence-in-depth only — the real confidentiality comes from the AEAD underneath — but it raises the cost of traffic analysis and bespoke attacks on the wire format. An LNG original."],
    ["LRS-87", "Ring signatures — LRS-87", "experimental",
     "Lattice-based linkable ring signatures over the ML-DSA ring. Each input is signed on behalf of a ring of 11 possible outputs, so an observer can't tell which one was really spent, while a per-spend \"key image\" still lets the network catch double-spends. This is new research built for LNG and has not had independent cryptanalysis — treat it as experimental."],
    ["HyperTorus", "Proof of work — HyperTorus", "novel",
     "The mining function: an integer-only, memory-hard walk over a 16 MiB scratchpad, projected each step through one of four tetrahedral bases selected by the walk's own state — the hypertoroidal Möbius–tetrahedral projection — and finalised with SHAKE256. Being memory-hard keeps mining closer to commodity CPUs than to specialised ASICs. An LNG original, © Ling Country."],
    ["Dandelion++", "Network privacy", "standard",
     "Transactions first travel along a quiet \"stem\" of single hops before being broadcast widely in the \"fluff\" phase, which hides which node originally created them. Combined with padded frames, cover traffic and optional Tor (SOCKS5), it makes it hard to link a transaction to an IP address."],

    ["Spend-tracing", "The payer can see when you spend", "known",
     "Whoever paid you can recognise the moment you spend those exact coins. The key image is a linear function of a value the sender knows, so a payer who made several outputs to you can match them against on-chain spends and defeat the ring anonymity — against that payer only. It never reveals your spend key or lets anyone steal funds.\n\nWork around it now: send the coins to yourself once (\"churn\") to break the link. A real fix needs a non-linear key image; it's a known, documented open problem in the LRS-87 design."],
    ["Visible amounts", "Amounts are public", "known",
     "Output amounts are fixed denominations (d × 10^e with d in {1,2,5}) and are visible on-chain per output. There is no confidential-transaction amount hiding yet.\n\nHiding amounts the way Monero does needs Pedersen commitments and range proofs — but those rest on discrete-log hardness and aren't post-quantum. A quantum-safe equivalent (lattice commitments + range proofs) exists only as heavy, still-maturing research, which is why LNG ships visible denominations for now."],
    ["Small anonymity set", "Few decoys on a young chain", "known",
     "Ring anonymity depends on having many plausible decoy outputs to hide among. A new chain has few outputs per denomination, so early rings draw from a small pool (and may even be smaller than 11 members until enough outputs exist).\n\nThis one heals with use: as more people transact, the decoy pool grows and rings get stronger. Post-quantum ring signatures are large, so simply cranking the ring size up isn't free — adoption is the real lever."]
]

fn about_is_novel(status) { return status == "novel" || status == "experimental" }

fn about_status_color(status) {
    if status == "standard" { return C_GREEN }
    if status == "novel" { return C_YELLOW }
    if status == "experimental" { return C_ORANGE }
    if status == "known" || status == "limitation" { return C_RED }
    return C_TEXT_DIM
}

fn about_status_label(status) {
    if status == "known" || status == "limitation" { return "limitation" }
    return status
}

# A clickable pill. Draws it and returns [width, hot].
fn about_pill(x, y, text, col, selected) {
    bind w = label_w(text) + 22
    bind h = 26
    bind hot = u_hover(x, y, w, h)
    if selected {
        fill_a(x, y, w, h, col, 0.20)
        hatch(x + 2, y + 2, w - 4, h - 4, col, true, 3, 0.30)
    } else if hot {
        fill_a(x, y, w, h, col, 0.10)
    }
    outline(x, y, w, h, col, sel(selected || hot, 1, 0.65))
    brackets(x, y, w, h, 5, lift(col, sel(selected, 0.4, 0.2)), 1)
    label(x + 11, y + h / 2 + t_cap(F_UI, 13) / 2, text, lift(col, sel(selected || hot, 0.45, 0.2)))
    return [w, hot]
}

# Lay out a wrapping row of pills for the cards whose indices are in `idxs`.
# Clicking one sets "about_sel". Returns the y just below the last row.
fn about_flow(x0, y0, maxw, idxs, sel_idx) {
    bind cx = x0
    bind cy = y0
    bind i = 0
    while i < len(idxs) {
        bind gi = list_get(idxs, i)
        bind card = list_get(ABOUT_CARDS, gi)
        bind text = list_get(card, 0)
        bind col = about_status_color(list_get(card, 2))
        bind w = label_w(text) + 22
        if cx + w > x0 + maxw && cx > x0 {
            bind cx = x0
            bind cy = cy + 34
        }
        bind r = about_pill(cx, cy, text, col, gi == sel_idx)
        if list_get(r, 1) && u_pressed() { st_set("about_sel", gi) }
        bind cx = cx + w + 8
        bind i = i + 1
    }
    return cy + 34
}

fn about_draw(ax, ay, aw, ah) {
    bind sel_idx = st_get("about_sel", 0)
    bind crypto = [0, 1, 2, 3, 4, 5, 6, 7, 8]
    bind limits = [9, 10, 11]

    # ── Left panel: the badges ──────────────────────────────────────────────
    bind lw = floor(aw * 50 / 100)
    bind inn = panel(ax, ay, lw, ah, "COMPONENTS", C_TEXT_DIM)
    bind x = list_get(inn, 0)
    bind y = list_get(inn, 1)
    bind iw = list_get(inn, 2)
    bind ih = list_get(inn, 3)

    t_text(F_UI, 14, x, y + 6, "CRYPTOGRAPHY", C_TEXT_FAINT)
    bind yy = about_flow(x, y + 16, iw, crypto, sel_idx)

    t_text(F_UI, 14, x, yy + 6, "KNOWN LIMITATIONS", C_TEXT_FAINT)
    bind yy = about_flow(x, yy + 16, iw, limits, sel_idx)

    bind ny = y + ih - 56
    hline(x, ny - 8, iw, C_LINE_SOFT, 1)
    t_para(F_UI, 15, x, ny + 4, iw, 19, "Standard: published and widely reviewed. Novel / experimental: designed for LNG and not yet independently reviewed. Click a badge for details.", C_TEXT_FAINT)

    # ── Right panel: the selected card ──────────────────────────────────────
    bind rx = ax + lw + 24
    bind rw = aw - lw - 24
    bind inr = panel(rx, ay, rw, ah, "DETAILS", C_VIOLET)
    bind dx = list_get(inr, 0)
    bind dy = list_get(inr, 1)
    bind dw = list_get(inr, 2)

    bind card = list_get(ABOUT_CARDS, sel_idx)
    bind st0 = list_get(card, 2)
    bind col = about_status_color(st0)

    fill(dx, dy + 6, 3, 22, col)
    t_text(F_UI, 21, dx + 14, dy + 10, list_get(card, 1), C_TEXT_STRONG)
    badge(dx + 14, dy + 44, about_status_label(st0), col, true)

    bind by = dy + 68
    bind hh = t_para(F_UI, 16, dx, by, dw, 23, list_get(card, 3), C_TEXT)

    if about_is_novel(st0) {
        bind cy2 = by + hh + 14
        hline(dx, cy2, dw, C_LINE_FAINT, 1)
        t_text(F_UI, 14, dx, cy2 + 10, "Invented for LNG · © Ling Country", C_VIOLET)
    }
}

← Back to index