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:
2026-07-13 06:52:34 -07:00
parent 9629e25e69
commit 4d1fb0256f
2 changed files with 21 additions and 1 deletions
@@ -50,6 +50,19 @@ fun String.decodeBitcoinDestination(): BitcoinDestination {
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
* different script shapes from this wallet's own P2WPKH (see [toP2wpkhScriptPubKey]), despite all three being a