nx_fin_ledger_gate.nx source
↩ module page · 134 lines · 8025 B
1// nx_fin_ledger_gate.nx -- R2 GATE: proves the double-entry ledger is exact, append-only, idempotent,
2// and never records a corrupt (unbalanced) entry. Dogfooded on the operator's HELOC crisis:
3// accounts: Home(asset), HELOC(liability), Cash(asset), OpeningEquity(equity), InterestExpense(expense)
4// txn1 opening balances -> net worth = Home + Cash + HELOC(neg) = $210,000.00
5// txn2 HELOC paydown $5,000 from Cash -> net worth INVARIANT (asset down == liability up) = THE PROOF
6// txn3 HELOC interest $1,000 from Cash -> net worth DOWN by $1,000 (expense, no offset)
7// Then: unbalanced txn REJECTED + never recorded (never-brick); re-post = idempotent DUP; history
8// retrievable + intact; and the live HELOC balance feeds nx_money for an exact monthly-interest figure.
9// Hermetic: a fresh per-run /tmp prefix, so the gate never touches the real ledger store.
10// Exits 0 iff ALL pass. license_tier: ORIGINAL
11import "nx_syscalls.nx"
12import "nx_money.nx"
13import "nx_canon_cid.nx"
14import "nx_uxf_decode.nx"
15import "nx_fin_ledger.nx"
16
17func g_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
18func g_putn(v: i64) -> i64 {
19 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 }
20 var m: i64 = v
21 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
22 let d: *u8 = sys_mmap(24); var k: i64 = 0
23 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
24 var j: i64 = k - 1
25 while j >= 0 { sys_write(1, ((d as i64)+j) as *u8, 1); j = j - 1 }
26 return 0
27}
28func chk(name: *u8, got: i64, want: i64, st: *i64) -> i64 {
29 if got == want { st[0] = st[0] + 1; g_puts(" PASS "); g_puts(name); g_puts("\n") }
30 else { st[1] = st[1] + 1; g_puts(" FAIL "); g_puts(name); g_puts(" got="); g_putn(got); g_puts(" want="); g_putn(want); g_puts("\n") }
31 return 0
32}
33
34func main() -> i64 {
35 let st: *i64 = sys_mmap(16) as *i64
36 st[0] = 0; st[1] = 0
37
38 // hermetic per-run prefix: "/tmp/finled_<us>-"
39 let pfx: *u8 = sys_mmap(64)
40 var pp: i64 = fl_cpy(pfx, "/tmp/finled_\x00" as *u8)
41 let ms: i64 = sys_now_us()
42 let tmp: *u8 = sys_mmap(32); var m: i64 = ms; var kk: i64 = 0
43 if m == 0 { tmp[0] = 0x30 as u8; kk = 1 }
44 while m > 0 { tmp[kk] = (0x30 + (m % 10)) as u8; m = m / 10; kk = kk + 1 }
45 var z: i64 = kk - 1
46 while z >= 0 { pfx[pp] = tmp[z]; pp = pp + 1; z = z - 1 }
47 pfx[pp] = 0x2d as u8; pp = pp + 1
48 pfx[pp] = 0 as u8
49
50 // open the chart of accounts
51 fl_acct_open(pfx, "Home\x00" as *u8, "asset\x00" as *u8)
52 fl_acct_open(pfx, "HELOC\x00" as *u8, "liability\x00" as *u8)
53 fl_acct_open(pfx, "Cash\x00" as *u8, "asset\x00" as *u8)
54 fl_acct_open(pfx, "OpeningEquity\x00" as *u8, "equity\x00" as *u8)
55 fl_acct_open(pfx, "InterestExpense\x00" as *u8, "expense\x00" as *u8)
56 chk("idempotent acct re-open = DUP(2)", fl_acct_open(pfx, "Home\x00" as *u8, "asset\x00" as *u8), 2, st)
57
58 // TXN1: opening balances. Home +300000.00, HELOC -100000.00, Cash +10000.00, OpeningEquity -210000.00
59 let accts1: *i64 = sys_mmap(8 * 8) as *i64
60 let amts1: *i64 = sys_mmap(8 * 8) as *i64
61 accts1[0] = "Home\x00" as *u8 as i64; amts1[0] = 30000000
62 accts1[1] = "HELOC\x00" as *u8 as i64; amts1[1] = 0 - 10000000
63 accts1[2] = "Cash\x00" as *u8 as i64; amts1[2] = 1000000
64 accts1[3] = "OpeningEquity\x00" as *u8 as i64; amts1[3] = 0 - 21000000
65 let cid1: *u8 = sys_mmap(96)
66 chk("post opening = NEW(1)", fl_post(pfx, "open-2026-06\x00" as *u8, "2026-06-01\x00" as *u8, "opening balances\x00" as *u8, accts1, amts1, 4, cid1), 1, st)
67 chk("net worth after open = 21000000", fl_networth(pfx), 21000000, st)
68 chk("Home balance = 30000000", fl_balance(pfx, "Home\x00" as *u8), 30000000, st)
69 chk("HELOC balance = -10000000", fl_balance(pfx, "HELOC\x00" as *u8), 0 - 10000000, st)
70 chk("Cash balance = 1000000", fl_balance(pfx, "Cash\x00" as *u8), 1000000, st)
71
72 // TXN2: pay $5,000 toward HELOC from Cash. Cash -5000.00, HELOC +5000.00 (owe less).
73 let accts2: *i64 = sys_mmap(8 * 8) as *i64
74 let amts2: *i64 = sys_mmap(8 * 8) as *i64
75 accts2[0] = "Cash\x00" as *u8 as i64; amts2[0] = 0 - 500000
76 accts2[1] = "HELOC\x00" as *u8 as i64; amts2[1] = 500000
77 let cid2: *u8 = sys_mmap(96)
78 chk("post paydown = NEW(1)", fl_post(pfx, "paydown-1\x00" as *u8, "2026-06-15\x00" as *u8, "HELOC paydown\x00" as *u8, accts2, amts2, 2, cid2), 1, st)
79 chk("net worth INVARIANT after paydown = 21000000", fl_networth(pfx), 21000000, st)
80 chk("HELOC reduced to -9500000", fl_balance(pfx, "HELOC\x00" as *u8), 0 - 9500000, st)
81 chk("Cash after paydown = 500000", fl_balance(pfx, "Cash\x00" as *u8), 500000, st)
82
83 // TXN3: pay $1,000 HELOC interest from Cash. Cash -1000.00, InterestExpense +1000.00.
84 let accts3: *i64 = sys_mmap(8 * 8) as *i64
85 let amts3: *i64 = sys_mmap(8 * 8) as *i64
86 accts3[0] = "Cash\x00" as *u8 as i64; amts3[0] = 0 - 100000
87 accts3[1] = "InterestExpense\x00" as *u8 as i64; amts3[1] = 100000
88 let cid3: *u8 = sys_mmap(96)
89 chk("post interest = NEW(1)", fl_post(pfx, "interest-1\x00" as *u8, "2026-06-20\x00" as *u8, "HELOC interest\x00" as *u8, accts3, amts3, 2, cid3), 1, st)
90 chk("net worth after interest = 20900000", fl_networth(pfx), 20900000, st)
91 chk("Cash after interest = 400000", fl_balance(pfx, "Cash\x00" as *u8), 400000, st)
92 chk("InterestExpense balance = 100000", fl_balance(pfx, "InterestExpense\x00" as *u8), 100000, st)
93
94 // LIAR-KILL / NEVER-BRICK: an unbalanced transaction (sum -50000) must be REJECTED and never recorded.
95 let acctsB: *i64 = sys_mmap(8 * 8) as *i64
96 let amtsB: *i64 = sys_mmap(8 * 8) as *i64
97 acctsB[0] = "Cash\x00" as *u8 as i64; amtsB[0] = 0 - 100000
98 acctsB[1] = "HELOC\x00" as *u8 as i64; amtsB[1] = 50000
99 let cidB: *u8 = sys_mmap(96)
100 chk("UNBALANCED txn REJECTED (-2)", fl_post(pfx, "bad-1\x00" as *u8, "2026-06-21\x00" as *u8, "unbalanced\x00" as *u8, acctsB, amtsB, 2, cidB), 0 - 2, st)
101 chk("net worth UNCHANGED after reject = 20900000", fl_networth(pfx), 20900000, st)
102 chk("txn count still 3 (corrupt never recorded)", fl_txn_count(pfx), 3, st)
103
104 // IDEMPOTENCY: re-post the SAME paydown (same extid + content) -> DUP no-op, no double count.
105 let cid2b: *u8 = sys_mmap(96)
106 chk("re-post paydown = DUP(2)", fl_post(pfx, "paydown-1\x00" as *u8, "2026-06-15\x00" as *u8, "HELOC paydown\x00" as *u8, accts2, amts2, 2, cid2b), 2, st)
107 chk("txn count STILL 3 (no double-count)", fl_txn_count(pfx), 3, st)
108 chk("HELOC STILL -9500000 (no double paydown)", fl_balance(pfx, "HELOC\x00" as *u8), 0 - 9500000, st)
109 chk("same content -> same CID", fl_streq(cid2, cid2b), 1, st)
110
111 // HISTORY INTACT: txn1 retrievable by CID, decodes to the original memo.
112 let rp: *i64 = sys_mmap(16) as *i64
113 let rn: *i64 = sys_mmap(16) as *i64
114 chk("txn1 retrievable by CID (=1)", fl_get_txn(pfx, cid1, rp, rn), 1, st)
115 let keys: *i64 = sys_mmap(8 * 256) as *i64
116 let vals: *i64 = sys_mmap(8 * 256) as *i64
117 let nf: i64 = canon_decode(rp[0] as *u8, rn[0], keys, vals, 256)
118 var dec_ok: i64 = 0
119 if nf > 0 { dec_ok = 1 }
120 chk("txn1 decodes (nf>0)", dec_ok, 1, st)
121 let memo1: *u8 = fl_get(keys, vals, nf, "memo\x00" as *u8)
122 chk("txn1 memo intact", fl_streq(memo1, "opening balances\x00" as *u8), 1, st)
123
124 // R1<->R2 INTEGRATION: the live HELOC balance feeds the no-float money engine.
125 // 6.5% APR, monthly, on the $95,000.00 owed = round(9500000 * round(6.5e7/12) / 1e9) = 51458 cents.
126 let owed: i64 = 0 - fl_balance(pfx, "HELOC\x00" as *u8)
127 let monthly: i64 = mny_rate_monthly(mny_rate_from_pct(65, 10))
128 chk("live HELOC monthly interest = 51458 ($514.58)", mny_apply_rate(owed, monthly, RND_HALF_EVEN), 51458, st)
129
130 g_puts("nx_fin_ledger_gate: PASS="); g_putn(st[0]); g_puts(" FAIL="); g_putn(st[1]); g_puts("\n")
131 if st[1] == 0 { g_puts("R2 nx_fin_ledger: GREEN\n"); return 0 }
132 g_puts("R2 nx_fin_ledger: RED\n")
133 return 1
134}