code wiki / _hdl_build / nx_adnet_creative.nx
nx_adnet_creative.nx source
↩ module page · 116 lines · 4787 B
1// nx_adnet_creative.nx -- LIB: advertiser CREATIVE INTAKE for the sovereign ad network (debt 1785512202).
2// THE CHICKEN-AND-EGG IT CLOSES: nx_adnet_selfserve accepts an inventory row whose img field must already
3// be a FIRST-PARTY url -- but nothing ever let an advertiser produce one, so no client could onboard at all.
4//
5// CONTENT-ADDRESSED BY CONSTRUCTION. The stored name is derived from the BYTES, so:
6// * replacing artwork MINTS A NEW URL -- the cache-busting problem solves itself and the creative can
7// finally be served cacheable (today every page view re-pulls it under a blanket no-cache).
8// * the same bytes always land on the same name -- re-upload is idempotent, never a duplicate.
9// The digest is FNV-1a, a NON-CRYPTOGRAPHIC content hash. It is named that here on purpose: it is a
10// cache key, NOT an integrity or authenticity claim, and must never be cited as one.
11//
12// THE SIZE CEILING IS A REFUSAL, NOT A GUIDELINE. The four house banners are 196,733 bytes each of
13// UNCOMPRESSED png -- a 728x90 banner roughly ten times heavier than it should be, re-fetched on every
14// page view. A platform that merely hopes clients upload small files will host that class forever, so an
15// oversize creative is REFUSED at intake with a named reason. Weight is an advertiser-facing quality
16// problem: a banner that slows the host page reflects on the client who paid for it.
17// license_tier: ORIGINAL
18import "nx_syscalls.nx"
19import "_hdl_build/nx_adnet_slot.nx"
20
21const ACR_W: i64 = 728
22const ACR_H: i64 = 90
23const ACR_MAX_BYTES: i64 = 65536
24const ACR_MIN_BYTES: i64 = 68
25
26// big-endian u32 at off
27func acr_be32(b: *u8, off: i64) -> i64 {
28 return ((b[off] as i64) * 16777216) + ((b[off + 1] as i64) * 65536) + ((b[off + 2] as i64) * 256) + (b[off + 3] as i64)
29}
30
31// PNG signature check: 89 50 4E 47 0D 0A 1A 0A
32func acr_is_png(b: *u8, n: i64) -> i64 {
33 if n < ACR_MIN_BYTES { return 0 }
34 if b[0] != (137 as u8) { return 0 }
35 if b[1] != (80 as u8) { return 0 }
36 if b[2] != (78 as u8) { return 0 }
37 if b[3] != (71 as u8) { return 0 }
38 if b[4] != (13 as u8) { return 0 }
39 if b[5] != (10 as u8) { return 0 }
40 if b[6] != (26 as u8) { return 0 }
41 if b[7] != (10 as u8) { return 0 }
42 if b[12] != (73 as u8) { return 0 }
43 if b[13] != (72 as u8) { return 0 }
44 if b[14] != (68 as u8) { return 0 }
45 if b[15] != (82 as u8) { return 0 }
46 return 1
47}
48
49func acr_width(b: *u8, n: i64) -> i64 { if acr_is_png(b, n) == 0 { return 0 - 1 } return acr_be32(b, 16) }
50func acr_height(b: *u8, n: i64) -> i64 { if acr_is_png(b, n) == 0 { return 0 - 1 } return acr_be32(b, 20) }
51
52// Verdicts -- a sealed enum so a caller cannot confuse WHY a creative was refused.
53const ACR_OK: i64 = 1
54const ACR_NOT_PNG: i64 = 2
55const ACR_BAD_DIMS: i64 = 3
56const ACR_TOO_HEAVY: i64 = 4
57
58func acr_validate(b: *u8, n: i64) -> i64 {
59 if acr_is_png(b, n) == 0 { return ACR_NOT_PNG }
60 if n > ACR_MAX_BYTES { return ACR_TOO_HEAVY }
61 if acr_width(b, n) != ACR_W { return ACR_BAD_DIMS }
62 if acr_height(b, n) != ACR_H { return ACR_BAD_DIMS }
63 return ACR_OK
64}
65
66func acr_reason(v: i64, out: *u8) -> i64 {
67 var o: i64 = 0
68 if v == ACR_OK { o = ad_cat(out, o, "accepted" as *u8) }
69 if v == ACR_NOT_PNG { o = ad_cat(out, o, "refused=not-a-png" as *u8) }
70 if v == ACR_BAD_DIMS { o = ad_cat(out, o, "refused=wrong-dimensions-must-be-728x90" as *u8) }
71 if v == ACR_TOO_HEAVY { o = ad_cat(out, o, "refused=over-64KB-recompress-the-png" as *u8) }
72 out[o] = 0 as u8
73 return o
74}
75
76// FNV-1a 64-bit over the creative bytes. CACHE KEY ONLY -- not an integrity claim.
77func acr_digest(b: *u8, n: i64) -> i64 {
78 var h: i64 = 0x00000100000001B3
79 var i: i64 = 0
80 while i < n {
81 h = h ^ (b[i] as i64)
82 h = h * 0x100000001B3
83 i = i + 1
84 }
85 if h < 0 { h = 0 - h }
86 return h
87}
88
89// content-addressed basename: adnet_<16 lowercase hex>.png
90func acr_name(b: *u8, n: i64, out: *u8, cap: i64) -> i64 {
91 if cap < 32 { return 0 }
92 if acr_validate(b, n) != ACR_OK { return 0 }
93 let h: i64 = acr_digest(b, n)
94 var o: i64 = ad_cat(out, 0, "adnet_" as *u8)
95 var shift: i64 = 60
96 while shift >= 0 {
97 let nib: i64 = (h / (1 << shift)) & 15
98 if nib < 10 { out[o] = (48 + nib) as u8 } else { out[o] = (87 + nib) as u8 }
99 o = o + 1
100 shift = shift - 4
101 }
102 o = ad_cat(out, o, ".png" as *u8)
103 out[o] = 0 as u8
104 return o
105}
106
107// the first-party url the advertiser puts in their inventory row's img field
108func acr_url(b: *u8, n: i64, out: *u8, cap: i64) -> i64 {
109 if cap < 48 { return 0 }
110 let nm: *u8 = sys_mmap(64)
111 if acr_name(b, n, nm, 64) == 0 { return 0 }
112 var o: i64 = ad_cat(out, 0, "/synth/" as *u8)
113 o = ad_cat(out, o, nm)
114 out[o] = 0 as u8
115 return o
116}