code wiki / _hdl_build / nx_adnet_bill.nx
nx_adnet_bill.nx source
↩ module page · 122 lines · 6275 B
1// nx_adnet_bill.nx -- LIB: CPM/CPC billing math for the sovereign ad network (adnet lane; the June
2// performance lane nx_ad_bill -- flat fee + capped bonus -- stays separate and untouched). ALL integer
3// milli-units (no float). HONEST-BILLING LAW (same as nx_ad_bill): a missing rate (<0 sentinel) or a
4// negative count REFUSES (-1) -- "cannot bill what we cannot price/measure"; default = NO CHARGE.
5// A period ceiling keeps every bill budgetable (flat cap, operator relationship > quick buck).
6// Counts come from the daemon's per-AD append-only logs (id-per-line; NO visitor identity by contract).
7// license_tier: ORIGINAL
8import "nx_syscalls.nx"
9import "_hdl_build/nx_adnet.nx"
10
11// total due in milli-units: imps at cpm_milli per 1000 + clicks at cpc_milli each. -1 = REFUSED.
12func anb_total_milli(imps: i64, clicks: i64, cpm_milli: i64, cpc_milli: i64) -> i64 {
13 if imps < 0 { return 0 - 1 }
14 if clicks < 0 { return 0 - 1 }
15 if cpm_milli < 0 { return 0 - 1 }
16 if cpc_milli < 0 { return 0 - 1 }
17 let a: i64 = (imps * cpm_milli) / 1000
18 let b: i64 = clicks * cpc_milli
19 return a + b
20}
21
22// budgetable flat ceiling: cap_milli >= 0 caps the bill; cap_milli < 0 = no cap configured.
23func anb_capped(total_milli: i64, cap_milli: i64) -> i64 {
24 if total_milli < 0 { return 0 - 1 }
25 if cap_milli < 0 { return total_milli }
26 if total_milli > cap_milli { return cap_milli }
27 return total_milli
28}
29
30// per-AD count from an append-only id-per-line log (delegates to the gated nx_adnet counter).
31func anb_count(logbuf: *u8, llen: i64, ad_id: *u8) -> i64 {
32 return ad_event_count(logbuf, llen, ad_id)
33}
34
35func anb_catd(dst: *u8, off: i64, v: i64) -> i64 {
36 var o: i64 = off
37 var m: i64 = v
38 if m < 0 { dst[o] = 45 as u8; o = o + 1; m = 0 - m }
39 let t: *u8 = sys_mmap(24)
40 var k: i64 = 0
41 if m == 0 { t[0] = 48 as u8; k = 1 }
42 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
43 var i: i64 = k - 1
44 while i >= 0 { dst[o] = t[i]; o = o + 1; i = i - 1 }
45 return o
46}
47
48// one plain-text invoice line: "adnet-bill id=<id> imps=<n> clicks=<n> due_milli=<t|REFUSED>".
49func anb_invoice_line(ad_id: *u8, imps: i64, clicks: i64, cpm_milli: i64, cpc_milli: i64, cap_milli: i64, out: *u8, cap: i64) -> i64 {
50 if cap < 256 { return 0 }
51 let t0: i64 = anb_total_milli(imps, clicks, cpm_milli, cpc_milli)
52 let due: i64 = anb_capped(t0, cap_milli)
53 var o: i64 = 0
54 o = ad_cat(out, o, "adnet-bill id=" as *u8)
55 o = ad_cat(out, o, ad_id)
56 o = ad_cat(out, o, " imps=" as *u8)
57 o = anb_catd(out, o, imps)
58 o = ad_cat(out, o, " clicks=" as *u8)
59 o = anb_catd(out, o, clicks)
60 o = ad_cat(out, o, " due_milli=" as *u8)
61 if due < 0 { o = ad_cat(out, o, "REFUSED" as *u8) } else { o = anb_catd(out, o, due) }
62 out[o] = 10 as u8
63 o = o + 1
64 return o
65}
66
67// ---- VIEWABLE-BASIS BILLING (debt 1785512185) --------------------------------------------------
68// THE DEFECT: anb_invoice_line bills `imps` taken from the SERVED-impression journal, which is written
69// when the slot HTML is INJECTED -- before the browser has laid anything out, and for a lazy-loaded
70// creative that is frequently never fetched at all. Charging a client for pixels no human saw is the
71// credibility rock for the entire network, so the basis moves to MRC-viewable (50 percent of pixels for
72// 1 CONTINUOUS second), measured by nx_adnet_view.
73//
74// The served count is PRINTED ALONGSIDE rather than discarded: served/viewable is the honest delivery
75// ratio, and an advertiser who can see it is being told something almost no network tells them.
76//
77// HONEST-BILLING LAW, EXTENDED TWICE:
78// (1) viewable < 0 means UNMEASURED and REFUSES. It must NEVER fall back to the served count -- that
79// fallback IS the defect being closed, and a biller that quietly substitutes a weaker number when
80// the strong one is missing manufactures exactly the false invoice this exists to prevent.
81// (2) viewable > served REFUSES. The /ad/view beacon is unauthenticated and its url is printed in every
82// page's source, so a viewable count is FORGEABLE by anyone who reads the html. A creative cannot be
83// seen more times than it was sent: viewable > served is not a large number, it is a BROKEN one, and
84// a broken measurement must refuse rather than invoice. This bounds forgery to "no worse than
85// served" -- the figure we already declined to bill on.
86
87// delivery ratio in permille. -1 = REFUSED: no denominator, either side unmeasured, or the pair is
88// impossible. A ratio with no grounding is not emitted as a number at all.
89func anb_deliv_permille(served: i64, viewable: i64) -> i64 {
90 if served < 0 { return 0 - 1 }
91 if viewable < 0 { return 0 - 1 }
92 if served == 0 { return 0 - 1 }
93 if viewable > served { return 0 - 1 }
94 return (viewable * 1000) / served
95}
96
97// invoice line billed on VIEWABLE impressions; served is reported, never billed.
98func anb_invoice_line_v(ad_id: *u8, served: i64, viewable: i64, clicks: i64, cpm_milli: i64, cpc_milli: i64, cap_milli: i64, out: *u8, cap: i64) -> i64 {
99 if cap < 384 { return 0 }
100 var due: i64 = 0 - 1
101 var basis_ok: i64 = 1
102 if viewable < 0 { basis_ok = 0 }
103 if viewable > served { basis_ok = 0 }
104 if basis_ok == 1 { due = anb_capped(anb_total_milli(viewable, clicks, cpm_milli, cpc_milli), cap_milli) }
105 let dp: i64 = anb_deliv_permille(served, viewable)
106 var o: i64 = 0
107 o = ad_cat(out, o, "adnet-bill id=" as *u8)
108 o = ad_cat(out, o, ad_id)
109 o = ad_cat(out, o, " basis=viewable served=" as *u8)
110 o = anb_catd(out, o, served)
111 o = ad_cat(out, o, " viewable=" as *u8)
112 if viewable < 0 { o = ad_cat(out, o, "UNMEASURED" as *u8) } else { o = anb_catd(out, o, viewable) }
113 o = ad_cat(out, o, " deliv_permille=" as *u8)
114 if dp < 0 { o = ad_cat(out, o, "REFUSED" as *u8) } else { o = anb_catd(out, o, dp) }
115 o = ad_cat(out, o, " clicks=" as *u8)
116 o = anb_catd(out, o, clicks)
117 o = ad_cat(out, o, " due_milli=" as *u8)
118 if due < 0 { o = ad_cat(out, o, "REFUSED" as *u8) } else { o = anb_catd(out, o, due) }
119 if viewable > served { o = ad_cat(out, o, " reason=viewable-exceeds-served-forged-or-broken" as *u8) }
120 out[o] = 10 as u8
121 o = o + 1
122 return o
123}