Skip to content

Commit

Permalink
Merge branch 'release-app_5.19' into merge_5.18_5.19
Browse files Browse the repository at this point in the history
  • Loading branch information
kozarezvlad committed Dec 9, 2024
2 parents 7e98dec + 3ce1984 commit 81ba28b
Show file tree
Hide file tree
Showing 12 changed files with 345 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ fun TangemSdkError.localizedDescriptionRes(): TangemSdkErrorDescription {
is TangemSdkError.UnsupportedWalletConfig,
is TangemSdkError.WalletIsNotCreated,
is TangemSdkError.WalletIsPurged,
is TangemSdkError.HashSizeMustBeEqual,
is TangemSdkError.SignHashesNotAvailable,
is TangemSdkError.CardVerificationFailed,
is TangemSdkError.NonHardenedDerivationNotSupported,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package com.tangem.common

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.tangem.operations.CommandResponse

@JsonClass(generateAdapter = true)
data class SuccessResponse(val cardId: String) : CommandResponse
data class SuccessResponse(
@Json(name = "cardId")
val cardId: String,
) : CommandResponse
7 changes: 7 additions & 0 deletions tangem-sdk-core/src/main/java/com/tangem/common/UserCode.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.tangem.common

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.tangem.common.core.SessionEnvironment
import com.tangem.common.extensions.calculateSha256

@JsonClass(generateAdapter = true)
class UserCode constructor(
@Json(name = "type")
val type: UserCodeType,
@Json(name = "value")
val value: ByteArray?,
) {
constructor(type: UserCodeType) : this(type, type.defaultValue)
Expand All @@ -19,8 +22,12 @@ class UserCode constructor(
}
}

@JsonClass(generateAdapter = false)
enum class UserCodeType(val defaultValue: String) {
@Json(name = "AccessCode")
AccessCode(UserCode.DefaultAccessCode),

@Json(name = "Passcode")
Passcode(UserCode.DefaultPasscode),
;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,6 @@ sealed class TangemSdkError(code: Int) : TangemError(code) {
*/
class EmptyHashes : TangemSdkError(code = 40902)

/**
* This error is returned when a [com.tangem.operations.SignCommand]
* receives hashes of different lengths for signature.
*/
class HashSizeMustBeEqual : TangemSdkError(code = 40903)
class WalletIsNotCreated : TangemSdkError(code = 40904)
class SignHashesNotAvailable : TangemSdkError(code = 40905)

Expand Down
16 changes: 15 additions & 1 deletion tangem-sdk-core/src/main/java/com/tangem/common/json/JSONRPC.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.tangem.common.json

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.tangem.common.core.TangemError

Expand Down Expand Up @@ -55,18 +56,31 @@ class JSONRPCRequest constructor(

@JsonClass(generateAdapter = true)
data class JSONRPCResponse(
@Json(name = "result")
val result: Any?,
@Json(name = "error")
val error: JSONRPCError?,
@Json(name = "id")
val id: Int? = null,
@Json(name = "jsonrpc")
val jsonrpc: String = "2.0",
) : JSONStringConvertible

data class ErrorData(val code: Int, val message: String)
@JsonClass(generateAdapter = true)
data class ErrorData(
@Json(name = "code")
val code: Int,
@Json(name = "message")
val message: String,
)

@JsonClass(generateAdapter = true)
class JSONRPCError constructor(
@Json(name = "code")
val code: Int,
@Json(name = "message")
val message: String,
@Json(name = "data")
val data: ErrorData? = null,
) : JSONStringConvertible {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,14 @@ class DeriveMultipleWalletPublicKeysTask(
response[key] = result.data
derive(keys = keys, index = index + 1, session = session, callback = callback)
}
is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error))
is CompletionResult.Failure -> {
if (response.isEmpty()) {
callback(CompletionResult.Failure(result.error))
} else {
// return partial response
callback(CompletionResult.Success(DerivationTaskResponse(response.toMap())))
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,18 @@ class DeriveWalletPublicKeysTask(
is TangemSdkError.WalletNotFound,
is TangemSdkError.UnsupportedCurve,
-> {
// continue derivation
Log.error { "Error: ${result.error}" }
}
else -> callback(CompletionResult.Failure(result.error))
else -> {
if (keys.keys.isEmpty()) {
callback(CompletionResult.Failure(result.error))
} else {
Log.error { "Error: ${result.error}" }
// return partial response
callback(CompletionResult.Success(ExtendedPublicKeysMap(keys)))
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.tangem.operations.sign

internal object ChunkHashesUtils {
// The max answer is 1152 bytes (unencrypted) and 1120 (encrypted).
// The worst case is 8 hashes * 64 bytes for ed + 512 bytes of signatures + cardId, SignedHashes + TLV + SW is ok.
private const val PACKAGE_SIZE = 512
// Card limitation
private const val MAX_CHUNK_SIZE = 10

fun chunkHashes(hashesRaw: Array<ByteArray>): List<Chunk> {
val hashes = hashesRaw.mapIndexed { index, hash -> Hash(index = index, data = hash) }
val hashesBySize = hashes.groupBy { it.data.size }

return hashesBySize.flatMap { hashesGroup ->
val hashSize = hashesGroup.key
val chunkSize = getChunkSize(hashSize)

hashesGroup.value
.chunked(chunkSize)
.map { Chunk(hashSize, it) }
}
}

private fun getChunkSize(hashSize: Int) = (PACKAGE_SIZE / hashSize).coerceIn(1, MAX_CHUNK_SIZE)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.tangem.operations.sign

class ChunkedHashesContainer(
hashes: Array<ByteArray>,
) {
val isEmpty: Boolean = hashes.isEmpty()
var currentChunkIndex: Int = 0
private set

private val chunks = ChunkHashesUtils.chunkHashes(hashes)
val chunksCount = chunks.size

private var signedChunks: MutableList<SignedChunk> = mutableListOf()

fun getCurrentChunk(): Chunk {
return chunks[currentChunkIndex]
}

fun addSignedChunk(signedChunk: SignedChunk) {
signedChunks.add(signedChunk)
currentChunkIndex++
}

fun getSignatures(): List<ByteArray> {
return signedChunks
.flatMap { it.signedHashes }
.sortedBy { it.index }
.map { it.signature }
}
}
Loading

0 comments on commit 81ba28b

Please sign in to comment.