mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-android.git
synced 2026-08-03 16:05:40 +00:00
Merge 3d0ccf657a into b616ca23d6
This commit is contained in:
+7
-11
@@ -8,10 +8,8 @@ import io.novafoundation.nova.feature_account_api.data.signer.SigningContext
|
||||
import io.novafoundation.nova.common.utils.min
|
||||
import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSplitter
|
||||
import io.novafoundation.nova.feature_account_api.data.extrinsic.SplitCalls
|
||||
import io.novafoundation.nova.runtime.ext.isPezkuwiChain
|
||||
import io.novafoundation.nova.runtime.ext.requireGenesisHash
|
||||
import io.novafoundation.nova.runtime.extrinsic.CustomTransactionExtensions
|
||||
import io.novafoundation.nova.runtime.extrinsic.extensions.PezkuwiCheckImmortal
|
||||
import io.novafoundation.nova.runtime.extrinsic.multi.CallBuilder
|
||||
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
|
||||
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
|
||||
@@ -135,6 +133,12 @@ internal class RealExtrinsicSplitter @Inject constructor(
|
||||
return split
|
||||
}
|
||||
|
||||
/**
|
||||
* A throwaway signed extrinsic, built only to measure the weight of `call`.
|
||||
*
|
||||
* Immortal era: this extrinsic is never submitted, so there is nothing for a mortal
|
||||
* era to protect, and an immortal one needs no block hash lookup.
|
||||
*/
|
||||
private suspend fun wrapInFakeExtrinsic(
|
||||
signer: NovaSigner,
|
||||
call: GenericCall.Instance,
|
||||
@@ -148,15 +152,7 @@ internal class RealExtrinsicSplitter @Inject constructor(
|
||||
extrinsicVersion = ExtrinsicVersion.V4,
|
||||
batchMode = BatchMode.BATCH,
|
||||
).apply {
|
||||
// Use custom CheckMortality for Pezkuwi chains to avoid DictEnum type lookup issues.
|
||||
// Gated on chain identity (not signed-extension presence): both Pezkuwi and Polkadot
|
||||
// Asset Hub declare "AuthorizeCall", so that alone can't tell the chains apart, and
|
||||
// PezkuwiCheckImmortal's raw DictEnum value fails Polkadot's own Era type codec.
|
||||
if (chain.isPezkuwiChain) {
|
||||
setTransactionExtension(PezkuwiCheckImmortal(genesisHash))
|
||||
} else {
|
||||
setTransactionExtension(CheckMortality(Era.Immortal, genesisHash))
|
||||
}
|
||||
setTransactionExtension(CheckMortality(Era.Immortal, genesisHash))
|
||||
setTransactionExtension(CheckGenesis(chain.requireGenesisHash().fromHex()))
|
||||
setTransactionExtension(ChargeTransactionPayment(BigInteger.ZERO))
|
||||
setTransactionExtension(CheckMetadataHash(CheckMetadataHashMode.Disabled))
|
||||
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
package io.novafoundation.nova.runtime.extrinsic.extensions
|
||||
|
||||
import io.novasama.substrate_sdk_android.runtime.definitions.types.composite.DictEnum
|
||||
import io.novasama.substrate_sdk_android.runtime.extrinsic.v5.transactionExtension.extensions.FixedValueTransactionExtension
|
||||
|
||||
/**
|
||||
* Custom CheckMortality extension for Pezkuwi chains using IMMORTAL era.
|
||||
*
|
||||
* Pezkuwi uses pezsp_runtime.generic.era.Era which is a DictEnum with variants:
|
||||
* - Immortal (encoded as 0x00)
|
||||
* - Mortal1(u8), Mortal2(u8), ..., Mortal255(u8)
|
||||
*
|
||||
* This extension uses Immortal era with genesis hash, which matches how @pezkuwi/api signs.
|
||||
*
|
||||
* @param genesisHash The chain's genesis hash (32 bytes) for the signer payload
|
||||
*/
|
||||
class PezkuwiCheckImmortal(
|
||||
genesisHash: ByteArray
|
||||
) : FixedValueTransactionExtension(
|
||||
name = "CheckMortality",
|
||||
implicit = genesisHash, // Genesis hash goes into signer payload for immortal transactions
|
||||
explicit = DictEnum.Entry<Any?>("Immortal", null) // Immortal variant - unit type with no value
|
||||
)
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
package io.novafoundation.nova.runtime.extrinsic.extensions
|
||||
|
||||
import io.novasama.substrate_sdk_android.runtime.definitions.types.composite.DictEnum
|
||||
import io.novasama.substrate_sdk_android.runtime.definitions.types.generics.Era
|
||||
import io.novasama.substrate_sdk_android.runtime.extrinsic.v5.transactionExtension.extensions.FixedValueTransactionExtension
|
||||
import java.math.BigInteger
|
||||
|
||||
/**
|
||||
* Custom CheckMortality extension for Pezkuwi chains.
|
||||
*
|
||||
* Pezkuwi uses pezsp_runtime.generic.era.Era which is a DictEnum with variants:
|
||||
* - Immortal
|
||||
* - Mortal1(u8), Mortal2(u8), ..., Mortal255(u8)
|
||||
*
|
||||
* The variant name is "MortalX" where X is the first byte of the encoded era,
|
||||
* and the variant's value is the second byte (u8).
|
||||
*
|
||||
* @param era The mortal era from MortalityConstructor
|
||||
* @param blockHash The block hash (32 bytes) for the signer payload
|
||||
*/
|
||||
class PezkuwiCheckMortality(
|
||||
era: Era.Mortal,
|
||||
blockHash: ByteArray
|
||||
) : FixedValueTransactionExtension(
|
||||
name = "CheckMortality",
|
||||
implicit = blockHash, // blockHash goes into signer payload
|
||||
explicit = createEraEntry(era) // Era as DictEnum.Entry
|
||||
) {
|
||||
companion object {
|
||||
/**
|
||||
* Creates a DictEnum.Entry for the Era.
|
||||
*
|
||||
* Standard Era encoding produces 2 bytes:
|
||||
* - First byte determines the variant name (Mortal1, Mortal2, ..., Mortal255)
|
||||
* - Second byte is the variant's value (u8)
|
||||
*/
|
||||
private fun createEraEntry(era: Era.Mortal): DictEnum.Entry<BigInteger> {
|
||||
val period = era.period.toLong()
|
||||
val phase = era.phase.toLong()
|
||||
val quantizeFactor = maxOf(period shr 12, 1)
|
||||
|
||||
// Calculate the two-byte encoding
|
||||
val encoded = ((countTrailingZeroBits(period) - 1).coerceIn(1, 15)) or
|
||||
((phase / quantizeFactor).toInt() shl 4)
|
||||
|
||||
val firstByte = encoded and 0xFF
|
||||
val secondByte = (encoded shr 8) and 0xFF
|
||||
|
||||
// DictEnum variant: "MortalX" where X is the first byte
|
||||
// Variant value: second byte as u8 (BigInteger)
|
||||
return DictEnum.Entry(
|
||||
name = "Mortal$firstByte",
|
||||
value = BigInteger.valueOf(secondByte.toLong())
|
||||
)
|
||||
}
|
||||
|
||||
private fun countTrailingZeroBits(value: Long): Int {
|
||||
if (value == 0L) return 64
|
||||
var n = 0
|
||||
var x = value
|
||||
while ((x and 1L) == 0L) {
|
||||
n++
|
||||
x = x shr 1
|
||||
}
|
||||
return n
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user