灵符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/isolates/miner.ling
# miner.ling — one passive mining thread (no capabilities: it can only hash
# and talk over the channels it was given).
#
# ctl  ← ["template", difficulty, header_without_nonce_hex, rest_hex]
#        ["cfg", active, intensity_pct]   ["stop"]
# node → ["found", block_hex]  ["hashstat", idx, hashes]
# ui   → ["trace", points]  (thread 0 only, for the HyperTorus visualizer)

fn miner_main(idx, ctl, node, ui) {
    st_set("active", false)
    st_set("intensity", 35)
    st_set("tpl", ())
    st_set("running", true)
    # Random start nonce per thread (< 2^52 so it stays exact).
    bind nonce = hex_u32le(lw_random(4), 0).x * 1048576
    bind hashes = 0
    bind count = 0
    bind last_report = epoch_now()
    while st_get("running", false) {
        drain(ctl)
        bind tpl = st_get("tpl", ())
        if st_get("active", false) && tpl != () {
            bind header = hex_concat([list_get(tpl, 2), u64le_hex(nonce)])
            bind started = epoch_now()
            bind pow = ""
            if idx == 0 && count % 8 == 0 {
                bind traced = lw_pow_trace(header, 1024)
                bind pow = list_get(traced, 0)
                chan_try_send(ui, ["trace", list_get(traced, 1)])
            } else {
                bind pow = lw_pow_hash(header)
            }
            bind count = count + 1
            bind hashes = hashes + 1
            if lw_meets_difficulty(pow, list_get(tpl, 1)) {
                chan_send(node, ["found", hex_concat([header, list_get(tpl, 3)])])
                # Wait for a template on the new tip.
                st_set("tpl", ())
            }
            bind nonce = nonce + 1
            # Duty cycle: hash for t, then rest t·(100−i)/i.
            bind i = st_get("intensity", 35)
            if i < 100 {
                bind spent_ms = (epoch_now() - started) * 1000
                sleep(floor(spent_ms * (100 - i) / i))
            }
        } else {
            match chan_recv_timeout(ctl, 500) {
                ok(m) => handle(m),
                bad(e) => 0,
            }
        }
        if epoch_now() - last_report >= 2 {
            chan_try_send(node, ["hashstat", idx, hashes])
            bind hashes = 0
            bind last_report = epoch_now()
        }
    }
    return ok(())
}

fn drain(ctl) {
    bind more = true
    while more {
        match chan_try_recv(ctl) {
            ok(m) => handle(m),
            bad(e) => st_set("drained", 1),
        }
        if st_get("drained", 0) == 1 {
            st_set("drained", 0)
            bind more = false
        }
    }
    return 0
}

fn handle(m) {
    bind kind = list_get(m, 0)
    if kind == "template" {
        st_set("tpl", m)
    }
    if kind == "cfg" {
        st_set("active", list_get(m, 1))
        st_set("intensity", list_get(m, 2))
    }
    if kind == "stop" {
        st_set("running", false)
    }
    return 0
}

← Back to index