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/seednode.ling
# seednode.ling — a headless LNG node for a server: no window and no wallet. It keeps the chain, relays blocks and
# transactions, tells new nodes about the peers it knows, and serves the chain to wallets that are catching up.
#
# ling run ling/seednode.ling --data-dir /srv/lng [--listen 0.0.0.0:18780] [--peer host:port ...]
# [--mine THREADS --pay-to lngkey1...|@file]
#
# Mining needs somewhere to pay the block reward: --pay-to takes a wallet's key bundle (Receive > Copy bundle, the
# lngkey1… text) or @a file holding it. The node remembers it, so later starts can leave --pay-to out.
#
# At start it writes its identity public key to <data-dir>/node_identity.pub: that is what a seed list pins for this node
# (ling run ling/tools/seeds.ling sign ... host:port=@<data-dir>/node_identity.pub). Open the listen port (TCP) in the
# firewall / router.
use "backend.ling"
use "core/wallet.ling"
fn arg_value(name, d) {
bind args = get_args()
bind i = 0
while i + 1 < len(args) {
if list_get(args, i) == "--" + name { return list_get(args, i + 1) }
bind i = i + 1
}
return d
}
fn node_identity(data_dir) {
make_dir(data_dir)
bind idfile = data_dir + "/node_identity.hex"
if !file_exists(idfile) { file_write_hex(idfile, lw_random(32)) }
bind seed = match file_read_hex(idfile) {
ok(v) => v,
bad(e) => "",
}
bind pk = match lw_id_keypair(seed) {
ok(k) => lw_id_public(k),
bad(e) => "",
}
# the full key (2592 bytes) goes to a file the seed tool can read: host:port=@<data>/node_identity.pub
if pk != "" { write_file(data_dir + "/node_identity.pub", pk) }
return pk
}
fn pay_bad(e) {
println(" --pay-to: ", e, " (expected the lngkey1… text from Receive > Copy bundle)")
return false
}
fn sel_pay(pay) {
if pay != "" { return "" }
return " (to the address given before; never given one? add --pay-to, or nothing gets mined)"
}
# the hex an lngkey1… address carries
fn base64url_hex(s) {
return match base64url_decode(substr(str_trim(s), 7, str_len(str_trim(s)) - 7)) {
ok(h) => h,
bad(e) => "",
}
}
bind start = do {
bind data_dir = arg_value("data-dir", default_data_dir())
println("LNG seed node")
println(" data: ", data_dir)
println(" listen: ", arg_value("listen", "0.0.0.0:18780"))
bind pk = node_identity(data_dir)
println(" identity: ", substr(pk, 0, 32), "… (full key: ", data_dir, "/node_identity.pub)")
be_init()
bind pay = arg_value("pay-to", "")
if str_starts_with(pay, "@") { bind pay = str_trim(read_file(substr(pay, 1, str_len(pay) - 1))) }
if pay != "" {
bind ok_pay = match bundle_import(pay) {
ok(bd) => true,
bad(e) => pay_bad(e),
}
if ok_pay {
chan_try_send(st_get("node_send", ""), ["publish_bundle", base64url_hex(pay)])
println(" pays to: ", substr(str_trim(pay), 0, 24), "…")
}
}
bind threads = to_number(arg_value("mine", "0"))
if threads > 0 {
be_set_mining(true, threads, 100, false)
println(" mining on ", threads, " thread(s)", sel_pay(pay))
}
bind t0 = epoch_now()
bind last = 0 - 100
while true {
be_tick()
bind t = epoch_now()
if t - last >= 30 {
bind last = t
bind n = be_network()
bind seeds = if n.seeds_verified { "seed list ok" } else { "no seed list" }
println("up ", floor(t - t0), " s height ", n.height, " peers ", len(n.peers), " mempool ", n.mempool, " ", n.route, ", ", seeds)
}
sleep(200)
}
}