From b7c70a219fdcace4aabd2ad6dfe6db376332edd3 Mon Sep 17 00:00:00 2001 From: JC-000 <3798556+JC-000@users.noreply.github.com> Date: Fri, 14 Aug 2026 10:15:11 -0500 Subject: [PATCH] =?UTF-8?q?fix(contract):=20the=20=C2=A78.0=20ownership=20?= =?UTF-8?q?expectation=20is=20profile-dependent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both onchip variants — half the release matrix — failed to link at the v0.9.1 pin: ld65: Error: src/lib_contract_asserts.s(166): libs/nistcurves shared-primitive ownership claim moved Root cause (od65 on the two archives we build): REU reports SHARED_PRIMITIVES = $0007, onchip reports $0005. That is the reu_mul bit correctly leaving both masks under -D FP_ONCHIP_MUL, which upstream's CHANGELOG documents for that row — the profile has no REU multiply path, so owning nothing there is right. The assert hardcoded $0007, a value measured at v0.6.0 when both profiles still agreed; the masks split upstream since. The expectation is now derived per profile. The assert is NOT weakened: both branches verified by negative control — feeding onchip the old $0007 fails the onchip link, and feeding REU $0001 fails the REU link. Also rewrites the error text, which sent the reader to re-derive archive member drops in build_nistcurves_p256.sh. That is the wrong remedy here (nothing about the surgery changed) and it cost real time. It now names the profile split, gives both expected values, and says to re-derive the wrapper only if which primitives SHIP has changed. Verified from clean, all five build configurations: make 47,105 B make BACKEND=uci 62,977 B make USE_NISTCURVES_ONCHIP=1 47,105 B make BACKEND=uci USE_NISTCURVES_ONCHIP=1 62,977 B make BACKEND=uci USE_NISTCURVES_ONCHIP_COMB=1 62,977 B ECDSA KAT 6/6 including the three negative CAVP vectors. Co-Authored-By: Claude Opus 5 (1M context) --- src/lib_contract_asserts.s | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/lib_contract_asserts.s b/src/lib_contract_asserts.s index bd49e5f..4941874 100644 --- a/src/lib_contract_asserts.s +++ b/src/lib_contract_asserts.s @@ -159,11 +159,29 @@ APP_OWNED = LIB_SHARED_PRIMITIVES_SQTAB | LIB_SHARED_PRIMITIVES_REU_MUL | LIB_SH ; tools/integration/build_nistcurves_p256.sh. Measured $0007 on both ; the REU and FP_ONCHIP_MUL variants at the v0.6.0 pin. ; -; If this fires, upstream changed which §8 primitives it owns. Re-derive -; which archive members the wrapper must drop (or which `SHARED_*` -; deferral switches it must pass) BEFORE updating the expected value. +; THE MASKS SPLIT AT v0.9.x. Under `-D FP_ONCHIP_MUL` upstream drops the +; reu_mul bit from both SHARED_PRIMITIVES and SHARED_CONSUMES, because +; that profile has no REU multiply path at all. Confirmed with od65 on +; the two archives we build: REU $0007, onchip $0005. That is upstream +; behaving correctly for the profile, not drift — so the expectation is +; profile-dependent, and a single hardcoded value breaks half the +; release matrix (both onchip variants) at link time. +; +; If this fires, upstream changed which §8 primitives it owns FOR THE +; PROFILE YOU ARE BUILDING. Read that profile's CHANGELOG row first. +; Only re-derive the archive member drops in +; tools/integration/build_nistcurves_p256.sh if the change is in which +; primitives actually SHIP — a mask moving between profiles does not +; imply the surgery is wrong, and chasing the wrapper first costs an +; afternoon (it did). .import LIB_NISTCURVES_SHARED_PRIMITIVES -.assert LIB_NISTCURVES_SHARED_PRIMITIVES = APP_OWNED, lderror, "libs/nistcurves shared-primitive ownership claim moved — re-derive the archive member drops in tools/integration/build_nistcurves_p256.sh before touching this assert" +.ifdef USE_NISTCURVES_ONCHIP +; FP_ONCHIP_MUL: no REU multiply path, so reu_mul leaves both masks. +EXPECTED_SHARED = LIB_SHARED_PRIMITIVES_SQTAB | LIB_SHARED_PRIMITIVES_CT_MUL_8X8 +.else +EXPECTED_SHARED = APP_OWNED +.endif +.assert LIB_NISTCURVES_SHARED_PRIMITIVES = EXPECTED_SHARED, lderror, "libs/nistcurves shared-primitive ownership claim moved for this build profile (expected $0007 on the REU profile, $0005 under USE_NISTCURVES_ONCHIP where reu_mul correctly leaves the mask) — check that profile's CHANGELOG row before changing the expectation, and only re-derive the wrapper's member drops if which primitives SHIP has changed" ; =====================================================================