Skip to content

Commit

Permalink
Merge pull request #66 from novasamatech/develop
Browse files Browse the repository at this point in the history
v1.9.1
  • Loading branch information
valentunn authored Oct 9, 2023
2 parents 28d321f + ece3126 commit da027e7
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 21 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
buildscript {
ext {
// App version
versionName = '1.9.0'
versionName = '1.9.1'
versionCode = 1

// SDK and tools
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import jp.co.soramitsu.fearless_utils.runtime.definitions.types.toHexUntyped
import jp.co.soramitsu.fearless_utils.runtime.extrinsic.signer.Signer
import jp.co.soramitsu.fearless_utils.runtime.extrinsic.signer.SignerPayloadExtrinsic
import jp.co.soramitsu.fearless_utils.runtime.metadata.SignedExtensionId
import jp.co.soramitsu.fearless_utils.runtime.metadata.SignedExtensionValue
import jp.co.soramitsu.fearless_utils.runtime.metadata.call
import jp.co.soramitsu.fearless_utils.runtime.metadata.findSignedExtension
import jp.co.soramitsu.fearless_utils.runtime.metadata.module
Expand All @@ -38,13 +39,16 @@ class ExtrinsicBuilder(
private val blockHash: ByteArray = genesisHash,
private val era: Era = Era.Immortal,
private val tip: BigInteger = DEFAULT_TIP,
private val customSignedExtensions: Map<SignedExtensionId, Any?> = emptyMap(),
customSignedExtensions: Map<SignedExtensionId, SignedExtensionValue> = emptyMap(),
private val addressInstanceConstructor: RuntimeType.InstanceConstructor<AccountId> = AddressInstanceConstructor,
private val signatureConstructor: RuntimeType.InstanceConstructor<SignatureWrapper> = SignatureInstanceConstructor
) {

private val calls = mutableListOf<GenericCall.Instance>()

private val _customSignedExtensions = mutableMapOf<SignedExtensionId, SignedExtensionValue>()
.apply { putAll(customSignedExtensions) }

fun call(
moduleIndex: Int,
callIndex: Int,
Expand Down Expand Up @@ -77,7 +81,20 @@ class ExtrinsicBuilder(
return this
}

fun reset(): ExtrinsicBuilder {
fun signedExtension(
id: SignedExtensionId,
value: SignedExtensionValue
) {
_customSignedExtensions[id] = value
}

@Deprecated(
message = "Use restCalls() for better readability",
replaceWith = ReplaceWith(expression = "resetCalls()")
)
fun reset(): ExtrinsicBuilder = resetCalls()

fun resetCalls(): ExtrinsicBuilder {
calls.clear()

return this
Expand Down Expand Up @@ -153,26 +170,36 @@ class ExtrinsicBuilder(

private suspend fun buildSignatureObject(callRepresentation: CallRepresentation): Any? {
val signedExtrasInstance = buildSignedExtras()

val additionalExtrasInstance = mapOf(
DefaultSignedExtensions.CHECK_MORTALITY to blockHash,
DefaultSignedExtensions.CHECK_GENESIS to genesisHash,
DefaultSignedExtensions.CHECK_SPEC_VERSION to runtimeVersion.specVersion.toBigInteger(),
DefaultSignedExtensions.CHECK_TX_VERSION to runtimeVersion.transactionVersion.toBigInteger()
)
val additionalSignedInstance = buildAdditionalSigned()

val signerPayload = SignerPayloadExtrinsic(
runtime = runtime,
accountId = accountId,
call = callRepresentation,
signedExtras = signedExtrasInstance,
additionalSignedExtras = additionalExtrasInstance,
additionalSignedExtras = additionalSignedInstance,
)
val signatureWrapper = signer.signExtrinsic(signerPayload)

return signatureConstructor.constructInstance(runtime.typeRegistry, signatureWrapper)
}

private fun buildAdditionalSigned(): Map<String, Any?> {
val default = mapOf(
DefaultSignedExtensions.CHECK_MORTALITY to blockHash,
DefaultSignedExtensions.CHECK_GENESIS to genesisHash,
DefaultSignedExtensions.CHECK_SPEC_VERSION to runtimeVersion.specVersion.toBigInteger(),
DefaultSignedExtensions.CHECK_TX_VERSION to
runtimeVersion.transactionVersion.toBigInteger()
)

val custom = _customSignedExtensions.mapValues { (_, extensionValues) ->
extensionValues.additionalSigned
}

return default + custom
}

private fun wrapInBatch(useBatchAll: Boolean): GenericCall.Instance {
val batchModule = runtime.metadata.module("Utility")
val batchFunctionName = if (useBatchAll) "batch_all" else "batch"
Expand All @@ -198,7 +225,11 @@ class ExtrinsicBuilder(
DefaultSignedExtensions.CHECK_NONCE to encodeNonce(nonce)
)

return default + customSignedExtensions
val custom = _customSignedExtensions.mapValues { (_, extensionValues) ->
extensionValues.signedExtra
}

return default + custom
}

private fun encodeNonce(nonce: BigInteger): Any {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package jp.co.soramitsu.fearless_utils.runtime.extrinsic

import jp.co.soramitsu.fearless_utils.runtime.metadata.SignedExtensionId
import jp.co.soramitsu.fearless_utils.runtime.metadata.SignedExtensionValue

fun ExtrinsicBuilder.signedExtra(id: SignedExtensionId, value: Any?) {
signedExtension(id, SignedExtensionValue(signedExtra = value))
}

fun ExtrinsicBuilder.additionalSigned(id: SignedExtensionId, value: Any?) {
signedExtension(id, SignedExtensionValue(additionalSigned = value))
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ class ExtrinsicMetadata(

typealias SignedExtensionId = String

class SignedExtensionValue(
val signedExtra: Any? = null,
val additionalSigned: Any? = null
)

class SignedExtensionMetadata(
val id: SignedExtensionId,
val type: RuntimeType<*, *>?,
Expand All @@ -32,10 +37,20 @@ class SignedExtensionMetadata(

companion object {

/**
* SignedExtras is signature params that are both signed
* and put separately in payload for verification
* Examples: tip, mortality
*/
fun onlySigned(id: String, type: RuntimeType<*, *>): SignedExtensionMetadata {
return SignedExtensionMetadata(id, type, Null)
}

/**
* AdditionalSigned is signature params that are signed
* and that are verified by runtime based on-chain state
* Examples: genesis hash, runtime version
*/
fun onlyAdditional(id: String, additionalSigned: RuntimeType<*, *>): SignedExtensionMetadata {
return SignedExtensionMetadata(id, Null, additionalSigned)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import jp.co.soramitsu.fearless_utils.runtime.definitions.types.composite.Struct
import jp.co.soramitsu.fearless_utils.runtime.definitions.types.fromHex
import jp.co.soramitsu.fearless_utils.runtime.definitions.types.generics.Era
import jp.co.soramitsu.fearless_utils.runtime.definitions.types.generics.Extrinsic
import jp.co.soramitsu.fearless_utils.runtime.definitions.types.generics.multiAddressFromId
import jp.co.soramitsu.fearless_utils.runtime.extrinsic.signer.KeyPairSigner
import jp.co.soramitsu.fearless_utils.runtime.metadata.SignedExtensionValue
import jp.co.soramitsu.fearless_utils.ss58.SS58Encoder.publicKeyToSubstrateAccountId
import jp.co.soramitsu.fearless_utils.ss58.SS58Encoder.toAccountId
import jp.co.soramitsu.fearless_utils.wsrpc.request.runtime.chain.RuntimeVersion
Expand Down Expand Up @@ -47,7 +47,7 @@ class ExtrinsicBuilderTest {
val runtime = RealRuntimeProvider.buildRuntime("westend")

@Test
fun `should build extrinsic from raw call bytes`() = runBlockingTest{
fun `should build extrinsic from raw call bytes`() = runBlockingTest {
val extrinsic = createExtrinsicBuilder()
.build(TRANSFER_CALL_BYTES)

Expand Down Expand Up @@ -118,7 +118,7 @@ class ExtrinsicBuilderTest {
}

@Test
fun `should build batch_all extrinsic`() = runBlockingTest{
fun `should build batch_all extrinsic`() = runBlockingTest {
val extrinsicBuilder = createExtrinsicBuilder()

repeat(2) {
Expand All @@ -135,7 +135,7 @@ class ExtrinsicBuilderTest {
}

@Test
fun `should build big extrinsic`() = runBlockingTest{
fun `should build big extrinsic`() = runBlockingTest {
val extrinsicBuilder = createExtrinsicBuilder()

repeat(20) {
Expand All @@ -151,7 +151,7 @@ class ExtrinsicBuilderTest {
}

@Test
fun `should build single transfer extrinsic statemine`() = runBlockingTest{
fun `should build single transfer extrinsic statemine`() = runBlockingTest {
val runtime = RealRuntimeProvider.buildRuntimeV14("statemine")

val extrinsicInHex =
Expand All @@ -166,10 +166,12 @@ class ExtrinsicBuilderTest {
accountId = KEYPAIR.publicKey.publicKeyToSubstrateAccountId(),
era = Era.Mortal(64, 59),
customSignedExtensions = mapOf(
"ChargeAssetTxPayment" to Struct.Instance(
mapOf(
"tip" to BigInteger.ZERO,
"assetId" to null
"ChargeAssetTxPayment" to SignedExtensionValue(
Struct.Instance(
mapOf(
"tip" to BigInteger.ZERO,
"assetId" to null
)
)
)
),
Expand All @@ -186,6 +188,44 @@ class ExtrinsicBuilderTest {
assertEquals(extrinsicInHex, encoded)
}

@Test
fun `should register signed extensions after creation`() = runBlockingTest {
val runtime = RealRuntimeProvider.buildRuntimeV14("statemine")

val extrinsicInHex =
"0x45028400fdc41550fb5186d71cae699c31731b3e1baa10680c7bd6b3831a6d222cf4d1680045ba1f9d291fff7dddf36f7ec060405d5e87ac8fab8832cfcc66858e6975141748ce89c41bda6c3a84204d3c6f929b928702168ca38bbed69b172044b599a10ab5038800000a0000bcc5ecf679ebd776866a04c212a4ec5dc45cefab57d7aa858c389844e212693f0700e40b5402"

val builder = ExtrinsicBuilder(
runtime = runtime,
nonce = 34.toBigInteger(),
runtimeVersion = RuntimeVersion(601, 4),
genesisHash = "48239ef607d7928874027a43a67689209727dfb3d3dc5e5b03a39bdc2eda771a".fromHex(),
signer = keypairSigner(),
accountId = KEYPAIR.publicKey.publicKeyToSubstrateAccountId(),
era = Era.Mortal(64, 59),
customSignedExtensions = emptyMap(),
blockHash = "0xdd7532c5c01242696001e57cded1bc1326379059300287552a9c344e5bea1070".fromHex()
)

builder.transfer(
recipientAccountId = "GqqKJJZ1MtiWiC6CzNg3g8bawriq6HZioHW1NEpxdf6Q6P5".toAccountId(),
amount = BigInteger("10000000000")
)

val chargeAssetTxPaymentValue = Struct.Instance(
mapOf(
"tip" to BigInteger.ZERO,
"assetId" to null
)
)

builder.signedExtra("ChargeAssetTxPayment", chargeAssetTxPaymentValue)

val encoded = builder.build()

assertEquals(extrinsicInHex, encoded)
}

private fun createExtrinsicBuilder() = ExtrinsicBuilder(
runtime = runtime,
signer = keypairSigner(),
Expand Down

0 comments on commit da027e7

Please sign in to comment.