L
ling-wallet
↓ 0 downloadsLing Wallet: a post-quantum privacy-coin wallet, full node and HyperTorus miner for LNG
Keywords wallet, cryptocurrency, lng, node, miner, ling
lingfu install ling-walletCode / 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
}