From 3f6e6441c68c9e1038a4f1cdb08be328baf314f6 Mon Sep 17 00:00:00 2001 From: Satoshi Qazi Muhammed Date: Sat, 18 Jul 2026 17:23:36 -0700 Subject: [PATCH] debug: trace isPezkuwi detection and CheckMortality encoding failure Real on-device failure while approving a multisig operation on Polkadot Asset Hub: 'Failed to encode extension CheckMortality'. isPezkuwi is detected via signedExtensions.any { it.id == "AuthorizeCall" } - confirmed via direct metadata inspection that AuthorizeCall exists on BOTH Polkadot Asset Hub and Pezkuwi Asset Hub (both on Metadata V16), so this heuristic can't actually distinguish the two chains. Need to confirm what isPezkuwi evaluates to at the moment of the real failure, and exactly where the throw happens (setTransactionExtension vs buildExtrinsic), before proposing a fix. --- .../data/extrinsic/ExtrinsicSplitter.kt | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/extrinsic/ExtrinsicSplitter.kt b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/extrinsic/ExtrinsicSplitter.kt index ce49d319..199751b7 100644 --- a/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/extrinsic/ExtrinsicSplitter.kt +++ b/feature-account-impl/src/main/java/io/novafoundation/nova/feature_account_impl/data/extrinsic/ExtrinsicSplitter.kt @@ -143,17 +143,29 @@ internal class RealExtrinsicSplitter @Inject constructor( val genesisHash = chain.requireGenesisHash().fromHex() val isPezkuwi = runtime.metadata.extrinsic.signedExtensions.any { it.id == "AuthorizeCall" } + android.util.Log.e( + "ExtrinsicDebug", + "wrapInFakeExtrinsic: chain=${chain.name} isPezkuwi=$isPezkuwi " + + "signedExtensionIds=${runtime.metadata.extrinsic.signedExtensions.map { it.id }}" + ) - return ExtrinsicBuilder( + val builder = ExtrinsicBuilder( runtime = runtime, extrinsicVersion = ExtrinsicVersion.V4, batchMode = BatchMode.BATCH, ).apply { // Use custom CheckMortality for Pezkuwi chains to avoid DictEnum type lookup issues if (isPezkuwi) { + android.util.Log.e("ExtrinsicDebug", "using PezkuwiCheckImmortal") setTransactionExtension(PezkuwiCheckImmortal(genesisHash)) } else { - setTransactionExtension(CheckMortality(Era.Immortal, genesisHash)) + android.util.Log.e("ExtrinsicDebug", "using standard CheckMortality(Era.Immortal)") + runCatching { + setTransactionExtension(CheckMortality(Era.Immortal, genesisHash)) + }.onFailure { e -> + android.util.Log.e("ExtrinsicDebug", "standard CheckMortality setTransactionExtension threw", e) + throw e + } } setTransactionExtension(CheckGenesis(chain.requireGenesisHash().fromHex())) setTransactionExtension(ChargeTransactionPayment(BigInteger.ZERO)) @@ -167,6 +179,10 @@ internal class RealExtrinsicSplitter @Inject constructor( val signingContext = signingContextFactory.default(chain) signer.setSignerDataForFee(signingContext) - }.buildExtrinsic() + } + + return runCatching { builder.buildExtrinsic() } + .onFailure { e -> android.util.Log.e("ExtrinsicDebug", "buildExtrinsic threw", e) } + .getOrThrow() } }