Skip to content

Commit 0f1d01c

Browse files
authored
Merge pull request #596 from synonymdev/refactor/remove-ldk-dependency
refactor: remove dependency on LDK
2 parents 3079320 + 2017b5a commit 0f1d01c

6 files changed

Lines changed: 16 additions & 63 deletions

File tree

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ suspend fun getData(): Result<Data> = withContext(Dispatchers.IO) {
206206
- ALWAYS use template in `.github/pull_request_template.md` for PR descriptions
207207
- ALWAYS wrap `ULong` numbers with `USat` in arithmetic operations, to guard against overflows
208208
- PREFER to use one-liners with `run { }` when applicable, e.g. `override fun someCall(value: String) = run { this.value = value }`
209+
- ALWAYS add imports instead of inline fully-qualified names
209210

210211
### Architecture Guidelines
211212

app/build.gradle.kts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ android {
4646
applicationId = "to.bitkit"
4747
minSdk = 28
4848
targetSdk = 36
49-
versionCode = 162
50-
versionName = "0.0.17"
49+
versionCode = 163
50+
versionName = "2.0.0-rc.1"
5151
testInstrumentationRunner = "to.bitkit.test.HiltTestRunner"
5252
vectorDrawables {
5353
useSupportLibrary = true
@@ -176,8 +176,7 @@ android {
176176
}
177177

178178
composeCompiler {
179-
featureFlags = setOf(
180-
)
179+
featureFlags = setOf()
181180
reportsDestination = layout.buildDirectory.dir("compose_compiler")
182181
}
183182

app/libs/LDK-release.aar

-17.4 MB
Binary file not shown.
Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,13 @@
11
package to.bitkit.ext
22

3-
import java.security.MessageDigest
43
import kotlin.io.encoding.Base64
5-
import kotlin.io.encoding.ExperimentalEncodingApi
64

7-
// region hex
8-
@OptIn(ExperimentalStdlibApi::class)
95
fun ByteArray.toHex(): String = this.toHexString()
106

11-
@OptIn(ExperimentalStdlibApi::class)
127
fun String.fromHex(): ByteArray = this.hexToByteArray()
13-
// endregion
148

15-
@OptIn(ExperimentalEncodingApi::class)
169
fun ByteArray.toBase64(): String = Base64.encode(this)
1710

18-
@OptIn(ExperimentalEncodingApi::class)
1911
fun String.fromBase64(): ByteArray = Base64.decode(this)
2012

2113
val String.uByteList get() = this.toByteArray().map { it.toUByte() }
22-
23-
fun ByteArray.toSha256(): ByteArray {
24-
val digest = MessageDigest.getInstance("SHA-256")
25-
return digest.digest(this)
26-
}

app/src/main/java/to/bitkit/services/RNBackupClient.kt

Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,12 @@ import kotlinx.serialization.Serializable
1717
import kotlinx.serialization.json.Json
1818
import kotlinx.serialization.json.buildJsonObject
1919
import kotlinx.serialization.json.put
20-
import org.bouncycastle.crypto.digests.SHA512Digest
21-
import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator
22-
import org.bouncycastle.crypto.params.KeyParameter
23-
import org.ldk.structs.KeysManager
2420
import org.lightningdevkit.ldknode.Network
21+
import org.lightningdevkit.ldknode.deriveNodeSecretFromMnemonic
2522
import to.bitkit.data.keychain.Keychain
2623
import to.bitkit.di.IoDispatcher
2724
import to.bitkit.env.Env
25+
import to.bitkit.ext.toHex
2826
import to.bitkit.utils.AppError
2927
import to.bitkit.utils.Crypto
3028
import to.bitkit.utils.Logger
@@ -255,41 +253,11 @@ class RNBackupClient @Inject constructor(
255253
return crypto.sign(fullMessage, privateKey)
256254
}
257255

258-
private fun deriveSigningKey(mnemonic: String, passphrase: String?): ByteArray {
259-
val bip39Seed = deriveSeed(mnemonic, passphrase)
260-
val bip32Seed = deriveMasterKey(bip39Seed)
261-
val seconds = System.currentTimeMillis() / 1000L
262-
val nanoSeconds = ((System.currentTimeMillis() % 1000) * 1_000_000).toInt()
256+
private fun deriveSigningKey(mnemonic: String, passphrase: String?): ByteArray =
257+
deriveNodeSecretFromMnemonic(mnemonic, passphrase).map { it.toByte() }.toByteArray()
263258

264-
return runCatching {
265-
val keysManager = KeysManager.of(bip32Seed, seconds, nanoSeconds)
266-
keysManager._node_secret_key
267-
}.getOrElse { bip32Seed }
268-
}
269-
270-
private fun deriveEncryptionKey(mnemonic: String, passphrase: String?): ByteArray {
271-
// Match iOS: use the same node secret key as signing key for encryption
272-
// iOS uses SymmetricKey(data: secretKey) where secretKey is the node secret key
273-
return deriveSigningKey(mnemonic, passphrase)
274-
}
275-
276-
private fun deriveSeed(mnemonic: String, passphrase: String?): ByteArray {
277-
val mnemonicBytes = mnemonic.toByteArray(Charsets.UTF_8)
278-
val salt = ("mnemonic" + (passphrase ?: "")).toByteArray(Charsets.UTF_8)
279-
val generator = PKCS5S2ParametersGenerator(SHA512Digest())
280-
generator.init(mnemonicBytes, salt, PBKDF2_ITERATIONS)
281-
282-
return (generator.generateDerivedParameters(PBKDF2_KEY_LENGTH_BITS) as KeyParameter).key
283-
}
284-
285-
private fun deriveMasterKey(seed: ByteArray): ByteArray {
286-
val algorithm = "HmacSHA512"
287-
val hmac = Mac.getInstance(algorithm)
288-
val keySpec = SecretKeySpec("Bitcoin seed".toByteArray(), algorithm)
289-
hmac.init(keySpec)
290-
val i = hmac.doFinal(seed)
291-
return i.sliceArray(0 until 32)
292-
}
259+
private fun deriveEncryptionKey(mnemonic: String, passphrase: String?): ByteArray =
260+
deriveSigningKey(mnemonic, passphrase)
293261

294262
private fun decrypt(blob: ByteArray, encryptionKey: ByteArray): ByteArray {
295263
if (blob.size < GCM_IV_LENGTH + GCM_TAG_LENGTH) throw RNBackupError.DecryptFailed("Data too short")
@@ -306,8 +274,6 @@ class RNBackupClient @Inject constructor(
306274

307275
return cipher.doFinal(ciphertext + tag)
308276
}
309-
310-
private fun ByteArray.toHex(): String = this.joinToString("") { "%02x".format(it) }
311277
}
312278

313279
@Serializable

gradle/libs.versions.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,17 @@ haze = "1.7.1"
1515
[libraries]
1616
accompanist-pager-indicators = { module = "com.google.accompanist:accompanist-pager-indicators", version = "0.36.0" }
1717
accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version = "0.37.3" }
18-
activity-compose = { module = "androidx.activity:activity-compose", version = "1.12.1" }
18+
activity-compose = { module = "androidx.activity:activity-compose", version = "1.12.2" }
1919
appcompat = { module = "androidx.appcompat:appcompat", version = "1.7.1" }
2020
barcode-scanning = { module = "com.google.mlkit:barcode-scanning", version = "17.3.0" }
21-
biometric = { module = "androidx.biometric:biometric", version = "1.4.0-alpha04" }
21+
biometric = { module = "androidx.biometric:biometric", version = "1.4.0-alpha05" }
2222
bitkit-core = { module = "com.synonym:bitkit-core-android", version = "0.1.35" }
2323
bouncycastle-provider-jdk = { module = "org.bouncycastle:bcprov-jdk18on", version = "1.83" }
2424
camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "camera" }
2525
camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "camera" }
2626
camera-view = { module = "androidx.camera:camera-view", version.ref = "camera" }
2727
# https://developer.android.com/develop/ui/compose/bom/bom-mapping
28-
compose-bom = { group = "androidx.compose", name = "compose-bom", version = "2025.12.00" }
28+
compose-bom = { group = "androidx.compose", name = "compose-bom", version = "2025.12.01" }
2929
compose-material-icons-extended = { module = "androidx.compose.material:material-icons-extended" }
3030
compose-material3 = { module = "androidx.compose.material3:material3" }
3131
compose-ui = { group = "androidx.compose.ui", name = "ui" }
@@ -39,8 +39,8 @@ core-ktx = { module = "androidx.core:core-ktx", version = "1.17.0" }
3939
core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version = "1.2.0" }
4040
datastore-preferences = { module = "androidx.datastore:datastore-preferences", version = "1.2.0" }
4141
detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" }
42-
detekt-compose-rules = { module = "io.nlopez.compose.rules:detekt", version = "0.5.1" }
43-
firebase-bom = { module = "com.google.firebase:firebase-bom", version = "34.6.0" }
42+
detekt-compose-rules = { module = "io.nlopez.compose.rules:detekt", version = "0.5.3" }
43+
firebase-bom = { module = "com.google.firebase:firebase-bom", version = "34.7.0" }
4444
firebase-messaging = { module = "com.google.firebase:firebase-messaging" }
4545
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" }
4646
hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt" }
@@ -57,7 +57,7 @@ ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
5757
ktor-client-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor" }
5858
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
5959
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
60-
ldk-node-android = { module = "com.github.synonymdev:ldk-node", version = "v0.7.0-rc.2" } # fork | local: remove `v`
60+
ldk-node-android = { module = "com.github.synonymdev:ldk-node", version = "v0.7.0-rc.6" } # fork | local: remove `v`
6161
lifecycle-process = { group = "androidx.lifecycle", name = "lifecycle-process", version.ref = "lifecycle" }
6262
lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycle" }
6363
lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycle" }

0 commit comments

Comments
 (0)