Skip to content

make android can package a stale anchor cdylib and still report BUILD SUCCESSFUL #642

Description

@cryptskii

Hit today while building the artifact for the two-phone current-format run. Caught only by checking the shipping binary for code markers; every conventional signal said the build was good.

What happened

make android at 5a0b4cb3 (clean tree) produced an APK whose libdsm_sdk.so was byte-identical to an August 8th libdsm_android_anchor.so — three days stale, predating #635, #638, #640 and #641 entirely. The armv7 and x86_64 cdylibs were from August 2nd.

Everything looked right: correct SHA, clean tree, BUILD SUCCESSFUL, fresh jniLibs timestamps (06:10:42), and cargo genuinely did compile the new code — its own output at deterministic_state_machine/target/aarch64-linux-android/release/libdsm_sdk.so (06:08, sha a722ef6b…) contains the new strings.

Gradle's refreshDsmJniLibs then overwrote both jniLibs directories with the stale cdylib (sha 4affa99f…), and that is what got packaged.

Why

refreshDsmJniLibs (dsm_client/android/app/build.gradle.kts:299+) resolves the shipping library as, in order:

  1. crates/dsm-android-anchor/target/<triple>/{release,debug}/libdsm_android_anchor.so
  2. the staged jniLibs copies

That preference is correct — the anchor cdylib is the shipping library; it links dsm_sdk statically and adds the anchor glue, and a plain dsm_sdk cdylib silently loses the offline/anchor paths.

The problem is that nothing in make android builds that cdylib. android-libs builds --package dsm_sdk only. So any previously-built cdylib — however old — wins over a freshly compiled dsm_sdk, every time.

The task's own comment documents the same wound from 2026-07-26 in the opposite direction, where a stale plain dsm_sdk .so overwrote a fresh anchor build and shipped an APK "whose native library had no token.mint/token.burn at all". The fix then made "a freshly built cdylib always win outright". It does — including when it is not fresh at all.

Suggested fix

Make make android-libs build the artifact that actually ships:

cd crates/dsm-android-anchor && cargo ndk -t arm64-v8a -t armeabi-v7a -t x86_64 \
    --platform 23 build --release --features on_device_installs

(The crate is excluded from the workspace because it transitively pulls tropic01, so it needs its own invocation.)

Belt-and-braces, independent of the above: refreshDsmJniLibs should refuse to use a cdylib older than the newest dsm_sdk cargo output for the same triple, and fail the build rather than silently prefer it. A stale artifact should be a build error, not a log line.

Why this matters beyond one bad APK

A hardware run against this artifact would have "proven" behaviour of code from three days earlier while reporting success against the intended SHA. Nothing in the pipeline would have contradicted it — the failure is invisible unless you check the shipping binary for content you expect to be there.

Worth a CI assertion too: after packaging, extract lib/arm64-v8a/libdsm_sdk.so from the APK and require a marker string from the current commit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions