Updated on 2026-08-14
This commit is contained in:
commit
92849d43c2
1407 changed files with 64092 additions and 11990 deletions
|
|
@ -1,28 +1,24 @@
|
|||
plugins {
|
||||
alias(deps.plugins.android.library)
|
||||
alias(deps.plugins.kotlin.android)
|
||||
alias(deps.plugins.kotlin.kapt)
|
||||
alias(deps.plugins.kotlin.serialization)
|
||||
id("configuration")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.tangem.lib.crypto"
|
||||
namespace = "com.tangem.libs.crypto"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
// region Tangem SDKs
|
||||
api(tangemDeps.blockchain)
|
||||
api(tangemDeps.card.core)
|
||||
// endregion
|
||||
|
||||
// region Project
|
||||
implementation(projects.core.utils)
|
||||
implementation(projects.libs.blockchainSdk)
|
||||
// endregion
|
||||
|
||||
// region Tangem SDKs
|
||||
implementation(tangemDeps.card.core)
|
||||
implementation(tangemDeps.blockchain)
|
||||
// endregion
|
||||
|
||||
// region Other deps
|
||||
implementation(deps.kotlin.coroutines)
|
||||
api(projects.domain.models)
|
||||
api(projects.libs.blockchainSdk)
|
||||
// endregion
|
||||
|
||||
// region Test libraries
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
package com.tangem.lib.crypto.derivation
|
||||
|
||||
import com.tangem.common.card.EllipticCurve
|
||||
import com.tangem.crypto.hdWallet.DerivationPath
|
||||
|
||||
/**
|
||||
* Checks whether this [EllipticCurve] is able to derive the given [path].
|
||||
*
|
||||
* `ed25519` and `ed25519_slip0010` support hardened derivation only (SLIP-0010), so any path that contains a
|
||||
* non-hardened node cannot produce a key/address for them. This is the root cause of the "custom token added without
|
||||
* an address" bug: e.g. an Algorand (ed25519) token with an EVM derivation path like `m/44'/60'/0'/0/0`.
|
||||
*
|
||||
* `secp256k1`, `secp256r1` and `bip0340` support both hardened and non-hardened derivation, so any path is fine.
|
||||
*
|
||||
* BLS curves do not support derivation at all.
|
||||
*/
|
||||
fun EllipticCurve.supportsDerivationPath(path: DerivationPath): Boolean {
|
||||
return when (this) {
|
||||
EllipticCurve.Ed25519,
|
||||
EllipticCurve.Ed25519Slip0010,
|
||||
-> path.nodes.all { it.isHardened }
|
||||
EllipticCurve.Secp256k1,
|
||||
EllipticCurve.Secp256r1,
|
||||
EllipticCurve.Bip0340,
|
||||
-> true
|
||||
EllipticCurve.Bls12381G2,
|
||||
EllipticCurve.Bls12381G2Aug,
|
||||
EllipticCurve.Bls12381G2Pop,
|
||||
-> false
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
package com.tangem.lib.crypto.derivation
|
||||
|
||||
import com.google.common.truth.Truth
|
||||
import com.tangem.common.card.EllipticCurve
|
||||
import com.tangem.crypto.hdWallet.DerivationPath
|
||||
import com.tangem.test.core.ProvideTestModels
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
internal class EllipticCurveDerivationSupportTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@ProvideTestModels
|
||||
fun supportsDerivationPath(model: TestModel) {
|
||||
// Arrange
|
||||
val path = DerivationPath(rawPath = model.derivationPath)
|
||||
|
||||
// Act
|
||||
val actual = model.curve.supportsDerivationPath(path)
|
||||
|
||||
// Assert
|
||||
Truth.assertThat(actual).isEqualTo(model.expected)
|
||||
}
|
||||
|
||||
private fun provideTestModels() = provideEd25519Models() +
|
||||
provideSecpModels() +
|
||||
provideBlsModels()
|
||||
|
||||
private fun provideEd25519Models() = listOf(
|
||||
// region ed25519-family require a fully-hardened path
|
||||
// Algorand default path — fully hardened
|
||||
TestModel(curve = EllipticCurve.Ed25519, derivationPath = "m/44'/283'/0'/0'/0'", expected = true),
|
||||
TestModel(curve = EllipticCurve.Ed25519Slip0010, derivationPath = "m/44'/283'/0'/0'/0'", expected = true),
|
||||
// The reported bug: Algorand (ed25519) + ApeChain/EVM path with non-hardened tail
|
||||
TestModel(curve = EllipticCurve.Ed25519, derivationPath = "m/44'/60'/0'/0/0", expected = false),
|
||||
TestModel(curve = EllipticCurve.Ed25519Slip0010, derivationPath = "m/44'/60'/0'/0/0", expected = false),
|
||||
// Solana default path — fully hardened
|
||||
TestModel(curve = EllipticCurve.Ed25519Slip0010, derivationPath = "m/44'/501'/0'/0'", expected = true),
|
||||
// A single non-hardened node is enough to make it unsupported
|
||||
TestModel(curve = EllipticCurve.Ed25519, derivationPath = "m/44'/283'/0'/0'/0", expected = false),
|
||||
// endregion
|
||||
)
|
||||
|
||||
private fun provideSecpModels() = listOf(
|
||||
// region secp256k1 / secp256r1 / bip0340 accept any path
|
||||
TestModel(curve = EllipticCurve.Secp256k1, derivationPath = "m/44'/60'/0'/0/0", expected = true),
|
||||
TestModel(curve = EllipticCurve.Secp256k1, derivationPath = "m/44'/0'/0'/0/0", expected = true),
|
||||
TestModel(curve = EllipticCurve.Secp256k1, derivationPath = "m/44'/283'/0'/0'/0'", expected = true),
|
||||
TestModel(curve = EllipticCurve.Secp256r1, derivationPath = "m/44'/60'/0'/0/0", expected = true),
|
||||
TestModel(curve = EllipticCurve.Bip0340, derivationPath = "m/44'/60'/0'/0/0", expected = true),
|
||||
// endregion
|
||||
)
|
||||
|
||||
private fun provideBlsModels() = listOf(
|
||||
// region BLS curves do not support derivation at all
|
||||
TestModel(curve = EllipticCurve.Bls12381G2, derivationPath = "m/44'/60'/0'/0/0", expected = false),
|
||||
TestModel(curve = EllipticCurve.Bls12381G2Aug, derivationPath = "m/44'/60'/0'/0'/0'", expected = false),
|
||||
TestModel(curve = EllipticCurve.Bls12381G2Pop, derivationPath = "m/44'/60'/0'/0'/0'", expected = false),
|
||||
// endregion
|
||||
)
|
||||
|
||||
data class TestModel(
|
||||
val curve: EllipticCurve,
|
||||
val derivationPath: String,
|
||||
val expected: Boolean,
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue