fix: verify native release build ids#1106
Conversation
Greptile SummaryNative release generation now verifies full-DWARF symbol archives and GNU build-ID parity against both final app artifacts.
Confidence Score: 5/5The PR appears safe to merge, with the release artifact paths, configured ABIs, symbol inputs, and build-ID validation aligned across current release callers. The known release paths build both required artifacts before validation, use filenames derived from the same version code, and validate the same arm64-v8a and armeabi-v7a ABI set configured for release builds; no actionable changed-code failure remains.
|
| Filename | Overview |
|---|---|
| scripts/create-native-debug-symbols.sh | Adds full-DWARF and GNU build-ID validation against correctly named AAB and universal APK artifacts for the configured release ABIs. |
| scripts/test-create-native-debug-symbols.sh | Adds isolated fixtures covering absent GNU notes, mismatched packaged IDs, and successful parity across both app artifacts. |
| .github/workflows/release-internal.yml | Builds both release artifact formats before resolving and validating native symbols. |
| app/build.gradle.kts | Resolves Paykit’s native debug-symbol classifier alongside the other Rust producers. |
| app/src/main/java/to/bitkit/services/LightningService.kt | Supplies explicit LDK defaults for additional-wallet full-scan batch size and stop gap. |
| gradle/libs.versions.toml | Updates the four native producer dependencies to versions that publish compatible symbol artifacts. |
| app/src/test/java/to/bitkit/build/NativeReleaseConfigTest.kt | Extends release configuration coverage for all symbol producers, app-artifact parity, and executable script fixtures. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
A[Build release APK and AAB] --> B[Resolve producer symbol archives]
B --> C[Normalize symbols by ABI and library]
C --> D{Full DWARF and GNU build IDs present?}
D -- No --> E[Fail release]
D -- Yes --> F{IDs match AAB and universal APK?}
F -- No --> E
F -- Yes --> G[Create native debug-symbol archive]
Reviews (1): Last reviewed commit: "fix: verify native symbol build ids" | Re-trigger Greptile
coreyphillips
left a comment
There was a problem hiding this comment.
The script itself holds up well. I traced it against dash, macOS sh, NDK 28 llvm-readelf and Info-ZIP, and these are all correct and need no changes:
build_id()awk parse. Realllvm-readelf -nputs theNT_GNU_BUILD_IDmarker and the hash on separate lines, so$3on theBuild ID:line is the hash and thenextnever skips it. binutilsreadelfuses the identical two-line form, so the GNU fallback infind_readelfparses the same.require_build_id'sexit 1inside a command substitution. POSIX gives an assignment the status of its last command substitution, and dash propagates it underset -e. A probe where every packaged lib lacksNT_GNU_BUILD_IDaborts with status 1 rather than passing vacuously.validate_symbol_treealso always runs first at both call sites and callsrequire_build_idin the current shell, so the symbol side can never be empty when parity runs.llvm-strippreserves.note.gnu.build-id, so packaged-to-symbol parity is satisfiable in principle.- The fixture's trap re-installation and temp-dir cleanup, and the hardcoded AAB name against the
FinalizeBundleTaskrename block. - The
LightningServicechange is forced, not scope creep:ElectrumSyncConfiggainedadditional_wallet_full_scan_batch_sizeandadditional_wallet_full_scan_stop_gapin ldk-node rc.55 with no UDL defaults, so the generated Kotlin constructor requires both. The/** LDK's default */KDoc is literally accurate againstsrc/config.rs(5 and 20). Worth saying so in the PR body, since as written a reader cannot tell a forced binding update from an unrelated wallet-config change.
Blocking status is exactly as the body says. All four upstream PRs are still open and none of the four pinned versions are published (latest: ldk-node v0.7.0-rc.57, bitkit-core v0.4.3, vss-rust-client-ffi v0.5.20, paykit v0.1.0-rc39). That fully explains the red CI and is not a defect here.
Five things to resolve before this lands.
1. The paykit line needs a decision
0.1.1 is not rc33 plus six RCs. pubky/paykit-rs#124 targets release/0.1.1, and the CHANGELOG on that branch goes straight from [Unreleased] to [0.1.0-rc33], so rc34 through rc39 are not in it.
Meanwhile four open PRs here are on the newer line: codex/paykit-incoming-payment-requests-rc39 and codex/batch-paykit-contact-cleanup on rc39, codex/970-pubky-paykit-ui-parity and codex/paykit-watch-only-accounts on rc37. rc37 is breaking (session signup/signin/auth require the receiver Noise key explicitly) and rc38/rc39 are breaking (no implicit private-to-public fallback, callers choose the payment mode).
Whichever merges second loses something: keep 0.1.1 and the rc39 call sites no longer exist, keep 0.1.0-rc39 and create-native-debug-symbols.sh aborts at require_build_id with no NT_GNU_BUILD_ID for libpaykit.so. Can we get a build-ID-enabled release cut on top of rc39, or land this with paykit left at rc33 and add libpaykit.so to required_libs in a follow-up once the lines converge?
2. ADDITIONAL_WALLET_FULL_SCAN_STOP_GAP = 20u contradicts the derived-account branches
The four in-flight branches carrying the watch-only work all set 100/1000 for these. If one of them rebases onto master after this lands, the KDoc makes 20 look authoritative, and a Trezor account whose owner previously received beyond 20 consecutive unused addresses would come back with a missing balance.
Was 5/20 a deliberate divergence from the 100/1000 those branches already agreed on, or just preserving pre-rc.55 behavior? If the latter, worth either matching them or leaving a comment tying the value to that work so a later rebase does not silently keep 20.
3. The ldk-node jump needs wallet QA
rc.52 to rc.58 crosses six release candidates. rc.54's notes cover "corrected RBF input/change selection, replacement fee enforcement, foreign-input weight estimation, and reserve calculations across aggregated wallets", which touches boost and coin selection directly. rc.55/rc.56 add rolling receive-address lookahead for derived accounts.
The QA notes here are all symbol and build checks plus a launch on device. Could you add boost, send with anchor reserves, and restore-from-seed balance on regtest, or split the ldk-node bump into its own PR so it gets reviewed as a wallet change rather than as tooling?
4. QA note names an ABI the gate does not check
The notes end with "final build-ID parity passed for arm64-v8a and x86_64". validate_packaged_build_id_parity loops arm64-v8a armeabi-v7a, and the release abiFilters are armeabi-v7a plus arm64-v8a (x86_64 is debug only), so x86_64 is neither packaged nor inspected, and armeabi-v7a is not mentioned. Since CI cannot run here, the QA notes are the only evidence the gate was exercised end to end, and armeabi-v7a is the ABI most likely to diverge because it is a separate toolchain.
5. Changelog fragment
Native build IDs are release tooling rather than something a user observes, while the parts of this PR that are user facing (ldk-node rc.54's RBF and coin-selection corrections, bitkit-core 0.4.1 to 0.4.4) are not mentioned. Either drop the fragment or rewrite it to cover the user-visible change.
Minor, on naming: every other fragment in changelog.d/next/ is keyed to the PR number, including 1091.fixed.md which fixes issue #1034. 1104.fixed.md is the only one keyed to an issue.
Conflicts with #1107
git merge-tree gives conflicts in scripts/create-native-debug-symbols.sh, app/src/test/java/to/bitkit/build/NativeReleaseConfigTest.kt and gradle/libs.versions.toml. release-internal.yml and app/build.gradle.kts auto-merge cleanly.
The dangerous hunk: this PR adds libpaykit.so to required_libs, #1107 splits the same line into dependency_required_libs plus application_required_libs. Taking #1107's side drops libpaykit.so from the release symbol gate silently, and NativeReleaseConfigTest then fails whichever side is taken, where the least-effort green fix is to delete libpaykit.so from the script and cement the gap. Correct resolution:
dependency_symbols_dir=${NATIVE_SYMBOLS_DEPENDENCY_DIR:-app/build/intermediates/native-debug-symbol-artifacts}
dependency_required_libs="libbitkitcore.so libldk_node.so libpaykit.so libvss_rust_client_ffi.so"
application_required_libs="libimage_processing_util_jni.so libsurface_util_jni.so libandroidx.graphics.path.so"
required_libs="$dependency_required_libs $application_required_libs"with the test assertion updated to match and both new @Test methods kept.
Also worth noting: #1107's check-16kb-compat.sh validates every .so in the final artifacts, including all four Rust libraries this PR bumps, and that gate runs only on release paths, never on PRs. I checked the current versions (ldk-node rc.52, paykit rc33, vss-client 0.5.20, bitkit-core) and all pass on both ABIs, but this PR replaces all four. Suggest running llvm-readelf -W -l and llvm-readelf -n over the jni/arm64-v8a and jni/armeabi-v7a .so files in the four new AARs once they publish, and pasting the results into the QA notes, so an unaligned or build-ID-less lib is caught before a release rather than during one.
Fixes #1104
Implements the Android consumer portion of #1105.
This PR is blocked until synonymdev/ldk-node#98, synonymdev/bitkit-core#131, synonymdev/vss-rust-client-ffi#19, and pubky/paykit-rs#124 receive human approval, merge, and publish their versioned artifacts.
Description
native-debug-symbolsclassifier and addslibpaykit.soto the required release symbol setlibldk_node.so,libbitkitcore.so,libvss_rust_client_ffi.so, andlibpaykit.soacross both release ABIs0.7.0-rc.58, bitkit-core0.4.4, VSS0.5.21, and Paykit0.1.1Preview
N/A — release artifact validation only.
QA Notes
Manual Tests
native-debug-symbols-187.zip, the matching mainnet release AAB, and the universal release APK.llvm-readelf -n; all eight packaged libraries matched their full-DWARF symbol counterparts.Automated Checks
just compilejust testjust lint(passes with existing warnings)just releaseNativeReleaseConfigTest.kt— 7 passed./scripts/test-create-native-debug-symbols.shshellcheck scripts/create-native-debug-symbols.sh scripts/test-create-native-debug-symbols.shactionlint .github/workflows/release-internal.ymlarm64-v8aandx86_64across all four native libraries