Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 0.7.0-rc.57 (Synonym Fork)
# 0.7.0-rc.58 (Synonym Fork)

## Bug Fixes

Expand Down Expand Up @@ -68,6 +68,8 @@

## Synonym Fork Additions

- Added stable GNU build IDs to every Android ABI and verified that packaged
libraries match their unstripped native debug symbols.
- Added rolling lookahead for derived on-chain accounts after their initial full scan.
- Added configurable Electrum batch size and stop gap for full scans of non-primary on-chain
wallets, while preserving the existing primary-wallet behavior and defaults.
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ exclude = ["bindings/uniffi-bindgen"]

[package]
name = "ldk-node"
version = "0.7.0-rc.57"
version = "0.7.0-rc.58"
authors = ["Elias Rohrer <dev@tnull.de>"]
homepage = "https://lightningdevkit.org/"
license = "MIT OR Apache-2.0"
Expand Down
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

import PackageDescription

let tag = "v0.7.0-rc.57"
let checksum = "930c0eb9b043a23cd519e1dec4697f51f9c8ad669a303f18da902b5943840d00"
let tag = "v0.7.0-rc.58"
let checksum = "caca6b4ef9df81cd84279438894aa37116c69fd4b86e3070722c824e7af5f634"
let url = "https://github.com/synonymdev/ldk-node/releases/download/\(tag)/LDKNodeFFI.xcframework.zip"

let package = Package(
Expand Down
2 changes: 1 addition & 1 deletion bindings/kotlin/ldk-node-android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ android.useAndroidX=true
android.enableJetifier=true
kotlin.code.style=official
group=com.synonym
version=0.7.0-rc.57
version=0.7.0-rc.58
87 changes: 84 additions & 3 deletions bindings/kotlin/ldk-node-android/lib/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import java.io.ByteArrayOutputStream
import java.io.File
import java.util.zip.ZipFile

plugins {
id("com.android.library")
Expand Down Expand Up @@ -105,6 +106,19 @@ fun Project.runReadelf(readelf: String, vararg args: String): Pair<Int, String>
return result.exitValue to stdout.toString().ifBlank { stderr.toString() }
}

fun Project.gnuBuildId(readelf: String, lib: File): String {
val (notesExit, notes) = runReadelf(readelf, "-n", lib.absolutePath)
val buildId = Regex("""(?s)NT_GNU_BUILD_ID.*?Build ID:\s*([0-9a-fA-F]+)""")
.find(notes)
?.groupValues
?.get(1)
if (notesExit != 0 || buildId.isNullOrEmpty()) {
throw GradleException("Android native library has no NT_GNU_BUILD_ID: '${lib.path}'")
}

return buildId
}

fun String.parseElfAlignment(): Long {
return if (startsWith("0x")) {
removePrefix("0x").toLong(16)
Expand All @@ -115,12 +129,11 @@ fun String.parseElfAlignment(): Long {

val validateReleaseNativeLibraries by tasks.registering {
group = "verification"
description = "Validates release JNI libraries are stripped and keep 16 KB LOAD alignment."
description = "Validates release JNI libraries are stripped, 16 KB aligned, and carry GNU build IDs."

doLast {
val readelf = findReadelf()
val loadAlignmentRegex = Regex("""^\s*LOAD\s+.*\s+(0x[0-9a-fA-F]+|\d+)\s*$""")

androidNativeAbis.forEach { abi ->
val lib = layout.projectDirectory.file("src/main/jniLibs/$abi/libldk_node.so").asFile
if (!lib.isFile) {
Expand All @@ -135,6 +148,8 @@ val validateReleaseNativeLibraries by tasks.registering {
throw GradleException("Android release native library still contains .debug_* sections: '${lib.path}'")
}

gnuBuildId(readelf, lib)

val wideHeaders = runReadelf(readelf, "-W", "-l", lib.absolutePath)
val headers = if (wideHeaders.first == 0) {
wideHeaders.second
Expand All @@ -158,10 +173,76 @@ val validateReleaseNativeLibraries by tasks.registering {
}
}

tasks.matching { it.name == "bundleReleaseAar" || it.name.startsWith("publish") }.configureEach {
val validatePublishedNativeArtifacts by tasks.registering {
group = "verification"
description = "Validates final AAR and full-DWARF symbol build IDs match for every Android ABI."
dependsOn("bundleReleaseAar", validateReleaseNativeLibraries)

doLast {
val readelf = findReadelf()
val aar = layout.buildDirectory.dir("outputs/aar").get().asFile
.listFiles()
?.singleOrNull { it.name.endsWith("-release.aar") }
?: throw GradleException("Exactly one release AAR is required for native build-ID validation")
val symbolArchive = rootProject.layout.projectDirectory.file("native-debug-symbols.zip").asFile
if (!symbolArchive.isFile) {
throw GradleException("Native debug symbol archive missing at '${symbolArchive.path}'")
}

val validationDir = layout.buildDirectory.dir("tmp/validatePublishedNativeArtifacts").get().asFile
validationDir.deleteRecursively()
validationDir.mkdirs()

fun extract(zip: ZipFile, entryName: String, output: File): File {
val entry = zip.getEntry(entryName)
?: throw GradleException("Native artifact entry missing: '$entryName'")
output.parentFile.mkdirs()
zip.getInputStream(entry).use { input ->
output.outputStream().use { input.copyTo(it) }
}
return output
}

ZipFile(aar).use { aarZip ->
ZipFile(symbolArchive).use { symbolZip ->
androidNativeAbis.forEach { abi ->
val packaged = extract(
aarZip,
"jni/$abi/libldk_node.so",
File(validationDir, "aar/$abi/libldk_node.so")
)
val symbols = extract(
symbolZip,
"$abi/libldk_node.so",
File(validationDir, "symbols/$abi/libldk_node.so")
)
val (sectionsExit, sections) = runReadelf(readelf, "-S", symbols.absolutePath)
if (sectionsExit != 0 || !sections.contains(".debug_info")) {
throw GradleException("Full DWARF .debug_info missing for '$abi/libldk_node.so'")
}

val packagedBuildId = gnuBuildId(readelf, packaged)
val symbolBuildId = gnuBuildId(readelf, symbols)
if (packagedBuildId != symbolBuildId) {
throw GradleException(
"Native build ID mismatch for '$abi/libldk_node.so': " +
"aar=$packagedBuildId symbols=$symbolBuildId"
)
}
}
}
}
}
}

tasks.matching { it.name == "bundleReleaseAar" }.configureEach {
dependsOn(validateReleaseNativeLibraries)
}

tasks.matching { it.name == "build" || it.name == "check" || it.name.startsWith("publish") }.configureEach {
dependsOn(validatePublishedNativeArtifacts)
Comment thread
ovitrif marked this conversation as resolved.
}

afterEvaluate {
publishing {
publications {
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion bindings/kotlin/ldk-node-jvm/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
org.gradle.jvmargs=-Xmx1536m
kotlin.code.style=official
group=com.synonym
version=0.7.0-rc.57
version=0.7.0-rc.58
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion bindings/python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "ldk_node"
version = "0.7.0-rc.57"
version = "0.7.0-rc.58"
authors = [
{ name="Elias Rohrer", email="dev@tnull.de" },
]
Expand Down
60 changes: 53 additions & 7 deletions scripts/uniffi_bindgen_generate_kotlin_android.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ echo "Building for Android architectures..."
JNI_LIB_DIR="$ANDROID_LIB_DIR/lib/src/main/jniLibs"
export CARGO_PROFILE_RELEASE_SMALLER_STRIP=false
export CARGO_PROFILE_RELEASE_SMALLER_DEBUG=2
export RUSTFLAGS="-C link-args=-Wl,-z,max-page-size=16384,-z,common-page-size=16384"
export RUSTFLAGS="-C link-arg=-Wl,--build-id=sha1 -C link-args=-Wl,-z,max-page-size=16384,-z,common-page-size=16384"
export CFLAGS="-D__ANDROID_MIN_SDK_VERSION__=21"

find_readelf() {
Expand Down Expand Up @@ -130,6 +130,28 @@ has_dwarf_sections() {
"$READELF_BIN" -S "$1" | grep -E '\.debug_' >/dev/null
}

android_build_id() {
readelf_notes=$("$READELF_BIN" -n "$1") || {
echo "Error: Unable to inspect Android native library notes: $1" >&2
return 1
}

printf '%s\n' "$readelf_notes" | awk '
/NT_GNU_BUILD_ID/ { found_gnu_build_id = 1; next }
found_gnu_build_id && /Build ID:/ { print $3; exit }
'
}

require_android_build_id() {
build_id=$(android_build_id "$1")
if [ -z "$build_id" ]; then
echo "Error: Android native library has no NT_GNU_BUILD_ID: $1" >&2
exit 1
fi

printf '%s\n' "$build_id"
}

readelf_program_headers() {
if "$READELF_BIN" -W -l "$1" >/dev/null 2>&1; then
"$READELF_BIN" -W -l "$1"
Expand Down Expand Up @@ -160,6 +182,8 @@ EOF

validate_android_library() {
lib="$1"
require_android_build_id "$lib" >/dev/null

if ! has_dwarf_debug_metadata "$lib"; then
echo "Error: Android native library has no .debug_info DWARF metadata: $lib"
exit 1
Expand All @@ -174,6 +198,8 @@ validate_android_library() {

validate_stripped_android_library() {
lib="$1"
require_android_build_id "$lib" >/dev/null

if has_dwarf_sections "$lib"; then
echo "Error: Android release native library still contains .debug_* sections: $lib"
exit 1
Expand Down Expand Up @@ -249,17 +275,36 @@ validate_android_aar_symbols() {
fi

tmp_dir=$(mktemp -d)
unzip -q "$aar" -d "$tmp_dir"
aar_dir="$tmp_dir/aar"
symbols_dir="$tmp_dir/symbols"
mkdir -p "$aar_dir" "$symbols_dir"
unzip -q "$aar" -d "$aar_dir"
unzip -q "$NATIVE_DEBUG_SYMBOLS_ZIP" -d "$symbols_dir"

for abi in armeabi-v7a arm64-v8a x86_64; do
lib="$tmp_dir/jni/$abi/libldk_node.so"
if [ ! -f "$lib" ]; then
echo "Error: Android release AAR native library missing at $lib"
packaged_lib="$aar_dir/jni/$abi/libldk_node.so"
symbol_lib="$symbols_dir/$abi/libldk_node.so"
if [ ! -f "$packaged_lib" ]; then
echo "Error: Android release AAR native library missing at $packaged_lib"
rm -rf "$tmp_dir"
exit 1
fi
if [ ! -f "$symbol_lib" ]; then
echo "Error: Android native debug symbol library missing at $symbol_lib"
rm -rf "$tmp_dir"
exit 1
fi

validate_stripped_android_library "$lib"
validate_stripped_android_library "$packaged_lib"
validate_android_library "$symbol_lib"

packaged_build_id=$(require_android_build_id "$packaged_lib")
symbol_build_id=$(require_android_build_id "$symbol_lib")
if [ "$packaged_build_id" != "$symbol_build_id" ]; then
echo "Error: Android build ID mismatch for $abi/libldk_node.so: packaged=$packaged_build_id symbols=$symbol_build_id"
rm -rf "$tmp_dir"
exit 1
fi
done

rm -rf "$tmp_dir"
Expand Down Expand Up @@ -310,7 +355,8 @@ echo "Version synced: $CARGO_VERSION"

# Verify android library publish task graph
echo "Testing android library publish to Maven Local..."
$ANDROID_LIB_DIR/gradlew --project-dir "$ANDROID_LIB_DIR" clean publishToMavenLocal
$ANDROID_LIB_DIR/gradlew --project-dir "$ANDROID_LIB_DIR" clean bundleReleaseAar
validate_android_aar_symbols
$ANDROID_LIB_DIR/gradlew --project-dir "$ANDROID_LIB_DIR" publishToMavenLocal

echo "Android build process completed successfully!"