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/tests/nodes/t_nodes.ling
# Two real node isolates over the real LWP-1 network, one miner isolate:
# A mines, B must sync to A's tip and learn A's address bundle via
# Dandelion++ relay. Headless (no UI).
use "../../core/params.ling"
use "../../core/codec.ling"
use "../../core/chain.ling"
use "../../core/wallet.ling"
fn check(name, cond) {
if cond {
print("PASS ", name)
st_add("pass", 1)
} else {
print("FAIL ", name)
st_add("fail", 1)
}
return cond
}
# Drain a node's status channel; remember its latest height.
fn pump(tag, ch) {
bind more = true
while more {
bind m = match chan_try_recv(ch) {
ok(v) => v,
bad(e) => (),
}
if m == () {
bind more = false
} else {
if list_get(m, 0) == "node_status" {
st_set(tag + "/height", list_get(m, 1))
st_set(tag + "/peers", len(list_get(m, 5)))
st_set(tag + "/hashes", st_get(tag + "/hashes", 0) + list_get(m, 9))
}
if list_get(m, 0) == "fatal" {
print(tag, " fatal: ", list_get(m, 1))
}
}
}
return 0
}
fn wait_for(secs, what) {
bind deadline = epoch_now() + secs
bind done = false
while done == false && epoch_now() < deadline {
pump("a", st_get("ui_a_rx", ""))
pump("b", st_get("ui_b_rx", ""))
if what == "connected" {
bind done = st_get("a/peers", 0) > 0 && st_get("b/peers", 0) > 0
}
if what == "mined" {
bind done = st_get("a/height", 0) >= 4
}
if what == "synced" {
bind done = st_get("b/height", 0) == st_get("a/height", -1) && st_get("a/height", 0) >= 4
}
sleep(100)
}
return done
}
bind start = do {
shared_put("test_genesis_difficulty", "1")
bind base = env_get("TEMP", ".") + "/lwtest-nodes-" + lw_random(4)
bind port_a = 21000 + hex_u32le(lw_random(4), 0).x % 20000
bind addr_a = format("127.0.0.1:{}", port_a)
bind addr_b = format("127.0.0.1:{}", port_a + 1)
bind ui_a = chan_new(1024)
bind ui_b = chan_new(1024)
st_set("ui_a_rx", list_get(ui_a, 1))
st_set("ui_b_rx", list_get(ui_b, 1))
bind in_a = chan_new(1024)
bind in_b = chan_new(1024)
bind wal_a = chan_new(64)
bind wal_b = chan_new(64)
bind mc = chan_new(16)
bind miner = thread_spawn("../../isolates/miner.ling", "miner_main", [0, list_get(mc, 1), list_get(in_a, 0), list_get(ui_a, 0)], [])
check("miner isolate spawned (no capabilities)", match miner { ok(h) => true, bad(e) => false, })
bind na = thread_spawn("../../isolates/node.ling", "node_main", [base + "/a", list_get(in_a, 1), list_get(ui_a, 0), list_get(wal_a, 0), [list_get(mc, 0)], addr_a, [], ""], ["db", "fs", "p2p"])
bind nb = thread_spawn("../../isolates/node.ling", "node_main", [base + "/b", list_get(in_b, 1), list_get(ui_b, 0), list_get(wal_b, 0), [], addr_b, [addr_a], ""], ["db", "fs", "p2p"])
check("node isolates spawned", match na { ok(h) => true, bad(e) => false, })
check("nodes connect over LWP-1", wait_for(30, "connected"))
# Publish an address for A's coinbases, then mine.
keys_load(lw_xof("test/miner", [], 32))
bind bundle = st_get("k_bundle", "")
bind bh = bundle_parse(bundle).x.hash
chan_send(list_get(in_a, 0), ["publish_bundle", bundle])
chan_send(list_get(in_a, 0), ["mining_cfg", 1, 1, 100, 0])
bind t0 = epoch_now()
check("A mines blocks", wait_for(180, "mined"))
print("A at height ", st_get("a/height", 0), " after ", floor(epoch_now() - t0), " s")
chan_send(list_get(in_a, 0), ["mining_cfg", 0, 1, 100, 0])
check("B syncs to A's tip", wait_for(60, "synced"))
check("miner reported hashes", st_get("a/hashes", 0) > 0)
# B learned A's bundle through Dandelion++ relay or a direct lookup.
chan_send(list_get(in_b, 0), ["lookup", bh])
bind got = false
bind deadline = epoch_now() + 60
while got == false && epoch_now() < deadline {
bind m = match chan_try_recv(list_get(wal_b, 1)) {
ok(v) => v,
bad(e) => (),
}
if m != () {
if list_get(m, 0) == "bundle_arrived" {
bind got = true
}
}
if got == false {
db_open(base + "/b/chain.db")
bind got = bundle_get(bh) != ""
}
sleep(200)
}
check("B obtained A's verified address bundle", got)
chan_send(list_get(mc, 0), ["stop"])
chan_send(list_get(in_a, 0), ["shutdown"])
chan_send(list_get(in_b, 0), ["shutdown"])
thread_join_timeout(na.x, 15000)
thread_join_timeout(nb.x, 15000)
print("")
print(format("{} passed, {} failed", st_get("pass", 0), st_get("fail", 0)))
}