mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-android.git
synced 2026-07-22 14:55:48 +00:00
fix: crash when generating an icon for a P2SH/P2PKH recipient
Confirmed live via logcat: tapping "send" to a P2SH address force-closed the app - FATAL EXCEPTION: IllegalArgumentException: Bech32 string is mixed case, thrown from Chain.accountIdOf() -> bitcoinAddressToAccountId() (native-SegWit-only) via the Confirm Send screen's address icon generator, a completely separate call path from the transaction-building fix already shipped. Chain.accountIdOf() now falls back to decodeBitcoinDestination() for P2SH/P2PKH, safe here because this generic accountId is only ever used for opaque purposes (identicons, presence checks) - the real send path already bypasses it entirely and builds the scriptPubKey straight from the typed BitcoinDestination.
This commit is contained in:
@@ -50,6 +50,19 @@ fun String.decodeBitcoinDestination(): BitcoinDestination {
|
|||||||
|
|
||||||
fun String.isValidBitcoinDestinationAddress(): Boolean = runCatching { decodeBitcoinDestination() }.isSuccess
|
fun String.isValidBitcoinDestinationAddress(): Boolean = runCatching { decodeBitcoinDestination() }.isSuccess
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The raw 20-byte hash underlying any destination type, with its type tag dropped - safe ONLY for consumers
|
||||||
|
* that treat it as an opaque identicon/display seed (e.g. `Chain.accountIdOf` and, downstream, address icon
|
||||||
|
* generation) and never feed it back into [toScriptPubKey] or re-encode it as an address. Real transaction
|
||||||
|
* construction must keep using [decodeBitcoinDestination]/[toScriptPubKey] directly, which keep the type.
|
||||||
|
*/
|
||||||
|
val BitcoinDestination.hash: ByteArray
|
||||||
|
get() = when (this) {
|
||||||
|
is BitcoinDestination.NativeSegwit -> witnessProgram
|
||||||
|
is BitcoinDestination.P2sh -> scriptHash
|
||||||
|
is BitcoinDestination.P2pkh -> pubKeyHash
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the scriptPubKey a transaction output must use to actually pay this destination - P2SH/P2PKH have
|
* @return the scriptPubKey a transaction output must use to actually pay this destination - P2SH/P2PKH have
|
||||||
* different script shapes from this wallet's own P2WPKH (see [toP2wpkhScriptPubKey]), despite all three being a
|
* different script shapes from this wallet's own P2WPKH (see [toP2wpkhScriptPubKey]), despite all three being a
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import io.novafoundation.nova.common.utils.TokenSymbol
|
|||||||
import io.novafoundation.nova.common.utils.Urls
|
import io.novafoundation.nova.common.utils.Urls
|
||||||
import io.novafoundation.nova.common.utils.asTokenSymbol
|
import io.novafoundation.nova.common.utils.asTokenSymbol
|
||||||
import io.novafoundation.nova.common.utils.bitcoinAddressToAccountId
|
import io.novafoundation.nova.common.utils.bitcoinAddressToAccountId
|
||||||
|
import io.novafoundation.nova.common.utils.decodeBitcoinDestination
|
||||||
|
import io.novafoundation.nova.common.utils.hash
|
||||||
import io.novafoundation.nova.common.utils.bitcoinPublicKeyToAccountId
|
import io.novafoundation.nova.common.utils.bitcoinPublicKeyToAccountId
|
||||||
import io.novafoundation.nova.common.utils.emptyBitcoinAccountId
|
import io.novafoundation.nova.common.utils.emptyBitcoinAccountId
|
||||||
import io.novafoundation.nova.common.utils.emptyEthereumAccountId
|
import io.novafoundation.nova.common.utils.emptyEthereumAccountId
|
||||||
@@ -303,7 +305,12 @@ fun ByteArray.toEthereumAddress(): String {
|
|||||||
fun Chain.accountIdOf(address: String): ByteArray {
|
fun Chain.accountIdOf(address: String): ByteArray {
|
||||||
return when {
|
return when {
|
||||||
isTronBased -> address.tronAddressToAccountId()
|
isTronBased -> address.tronAddressToAccountId()
|
||||||
isBitcoinBased -> address.bitcoinAddressToAccountId()
|
// Falls back to decodeBitcoinDestination() for a valid P2SH/P2PKH address (real exchange withdrawal
|
||||||
|
// addresses were confirmed to be P2SH-only) - this wallet's own address stays native-SegWit-only, but a
|
||||||
|
// SEND destination legitimately isn't. Safe here ONLY because this generic accountId is used for
|
||||||
|
// opaque purposes (identicon generation, presence checks) elsewhere, never fed back into building a
|
||||||
|
// scriptPubKey - see BitcoinDestinationAddress.kt's [hash] doc.
|
||||||
|
isBitcoinBased -> runCatching { address.bitcoinAddressToAccountId() }.getOrElse { address.decodeBitcoinDestination().hash }
|
||||||
isEthereumBased -> address.asEthereumAddress().toAccountId().value
|
isEthereumBased -> address.asEthereumAddress().toAccountId().value
|
||||||
else -> address.toAccountId()
|
else -> address.toAccountId()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user