From a9746b3641dba784bb15deecebb417b116517909 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Mon, 19 Aug 2019 09:28:52 +0200 Subject: [PATCH] Add specVersion to SignedExtra payload (#1324) * Add specVersion to SignedExtra payload * Update ExtrinsicPayload.ts * Cleanup linting & tests (code-only) * Update after e2e testing in apps * Check and fix tests * Grrr... case sensitivity * Use interfaces where available * Case sensitive fixes --- .../api-metadata/src/extrinsics/index.spec.ts | 11 +++- packages/api/src/SignerPayload.spec.ts | 2 + packages/api/src/SignerPayload.ts | 7 ++- packages/api/src/SubmittableExtrinsic.ts | 9 ++-- packages/api/src/types.ts | 5 ++ .../src/primitive/Extrinsic/Extrinsic.ts | 8 +-- .../primitive/Extrinsic/ExtrinsicPayload.ts | 9 ++++ .../src/primitive/Extrinsic/v1/Extrinsic.ts | 24 ++++----- .../Extrinsic/v1/ExtrinsicPayload.ts | 5 +- .../Extrinsic/v1/ExtrinsicSignature.ts | 7 ++- .../primitive/Extrinsic/v2/Extrinsic.spec.ts | 9 ++++ .../src/primitive/Extrinsic/v2/Extrinsic.ts | 26 ++++----- .../Extrinsic/v2/ExtrinsicExtra.spec.ts | 27 ---------- .../primitive/Extrinsic/v2/ExtrinsicExtra.ts | 54 ------------------- .../Extrinsic/v2/ExtrinsicPayload.ts | 18 +++++-- .../Extrinsic/v2/ExtrinsicSignature.ts | 30 ++++------- .../primitive/Extrinsic/v3/Extrinsic.spec.ts | 13 ++++- .../src/primitive/Extrinsic/v3/Extrinsic.ts | 26 ++++----- .../Extrinsic/v3/ExtrinsicPayload.ts | 31 ++++++++--- .../Extrinsic/v3/ExtrinsicSignature.ts | 6 +-- packages/types/src/types.ts | 3 +- 21 files changed, 156 insertions(+), 174 deletions(-) delete mode 100644 packages/types/src/primitive/Extrinsic/v2/ExtrinsicExtra.spec.ts delete mode 100644 packages/types/src/primitive/Extrinsic/v2/ExtrinsicExtra.ts diff --git a/packages/api-metadata/src/extrinsics/index.spec.ts b/packages/api-metadata/src/extrinsics/index.spec.ts index 9fb230dea1..fd3d75356a 100644 --- a/packages/api-metadata/src/extrinsics/index.spec.ts +++ b/packages/api-metadata/src/extrinsics/index.spec.ts @@ -4,6 +4,7 @@ import '@polkadot/types/injector'; +import BN from 'bn.js'; import testingPairs from '@polkadot/keyring/testingPairs'; import { createType } from '@polkadot/types'; @@ -19,7 +20,15 @@ describe('extrinsics', (): void => { ).sign(keyring.alice, { blockHash: '0xec7afaf1cca720ce88c1d1b689d81f0583cc15a97d621cf046dd9abf605ef22f', genesisHash: '0xdcd1346701ca8396496e52aa2785b1748deb6db09551b72159dcb3e08991025b', - nonce: 0 + nonce: 0, + runtimeVersion: { + apis: [], + authoringVersion: new BN(123), + implName: 'test', + implVersion: new BN(123), + specName: 'test', + specVersion: new BN(123) + } }).toHex() ).toEqual( '0x' + diff --git a/packages/api/src/SignerPayload.spec.ts b/packages/api/src/SignerPayload.spec.ts index 481750f284..599835791a 100644 --- a/packages/api/src/SignerPayload.spec.ts +++ b/packages/api/src/SignerPayload.spec.ts @@ -16,6 +16,7 @@ describe('SignerPayload', (): void => { genesisHash: '0xdcd1346701ca8396496e52aa2785b1748deb6db09551b72159dcb3e08991025b', method: '0x0500ffd7568e5f0a7eda67a82691ff379ac4bba4f9c9b859fe779b5d46363b61ad2db9e56c', nonce: '0x00001234', + specVersion: '0x00000000', tip: '0x00000000000000000000000000005678', version: 3 }; @@ -45,6 +46,7 @@ describe('SignerPayload', (): void => { genesisHash: '0xdcd1346701ca8396496e52aa2785b1748deb6db09551b72159dcb3e08991025b', method: '0x0500ffd7568e5f0a7eda67a82691ff379ac4bba4f9c9b859fe779b5d46363b61ad2db9e56c', nonce: '0x00001234', + specVersion: '0x00000000', tip: '0x00000000000000000000000000005678', version: 3 }); diff --git a/packages/api/src/SignerPayload.ts b/packages/api/src/SignerPayload.ts index c66392bda6..c86eeb98c5 100644 --- a/packages/api/src/SignerPayload.ts +++ b/packages/api/src/SignerPayload.ts @@ -2,7 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { Address, Balance, BlockNumber, Call, ExtrinsicEra, Hash, Index } from '@polkadot/types/interfaces'; +import { Address, Balance, BlockNumber, Call, ExtrinsicEra, Hash, Index, RuntimeVersion } from '@polkadot/types/interfaces'; import { Constructor } from '@polkadot/types/types'; import { SignerPayload, SignerPayloadRaw } from './types'; @@ -16,6 +16,7 @@ export interface SignerPayloadType { genesisHash: Hash; method: Call; nonce: Compact; + runtimeVersion: RuntimeVersion; tip: Compact; version: u8; } @@ -30,6 +31,7 @@ const _Payload: Constructor = Struct.with({ genesisHash: 'Hash', method: 'Call', nonce: 'Compact', + runtimeVersion: 'RuntimeVersion', tip: 'Compact', version: u8 }); @@ -46,7 +48,7 @@ export default class Payload extends _Payload { * @description Creates an representation of the structure as an ISignerPayload JSON */ public toPayload (): SignerPayload { - const { address, blockHash, blockNumber, era, genesisHash, method, nonce, tip, version } = this.self; + const { address, blockHash, blockNumber, era, genesisHash, method, nonce, runtimeVersion: { specVersion }, tip, version } = this.self; return { address: address.toString(), @@ -56,6 +58,7 @@ export default class Payload extends _Payload { genesisHash: genesisHash.toHex(), method: method.toHex(), nonce: nonce.toHex(), + specVersion: specVersion.toHex(), tip: tip.toHex(), version: version.toNumber() }; diff --git a/packages/api/src/SubmittableExtrinsic.ts b/packages/api/src/SubmittableExtrinsic.ts index b80b274808..cd2284b1cd 100644 --- a/packages/api/src/SubmittableExtrinsic.ts +++ b/packages/api/src/SubmittableExtrinsic.ts @@ -176,10 +176,11 @@ export default function createSubmittableExtrinsic ( function expandOptions (options: Partial, extras: { blockHash?: Hash; era?: ExtrinsicEra; nonce?: Index }): SignatureOptions { return { blockHash: api.genesisHash, - version: api.runtimeVersion, ...options, ...extras, - genesisHash: api.genesisHash + genesisHash: api.genesisHash, + runtimeVersion: api.runtimeVersion, + version: api.extrinsicType } as unknown as SignatureOptions; } @@ -272,9 +273,7 @@ export default function createSubmittableExtrinsic ( ...eraOptions, address, method: _extrinsic.method, - blockNumber: header ? header.number : 0, - genesisHash: api.genesisHash, - version: api.extrinsicType + blockNumber: header ? header.number : 0 }); if (api.signer.signPayload) { diff --git a/packages/api/src/types.ts b/packages/api/src/types.ts index 24ad36fcda..009f261c38 100644 --- a/packages/api/src/types.ts +++ b/packages/api/src/types.ts @@ -246,6 +246,11 @@ export interface SignerPayload { */ nonce: string; + /** + * @description The current spec version for the runtime + */ + specVersion: string; + /** * @description The tip for this transaction, in hex */ diff --git a/packages/types/src/primitive/Extrinsic/Extrinsic.ts b/packages/types/src/primitive/Extrinsic/Extrinsic.ts index b7d4601991..86fd105796 100644 --- a/packages/types/src/primitive/Extrinsic/Extrinsic.ts +++ b/packages/types/src/primitive/Extrinsic/Extrinsic.ts @@ -3,15 +3,14 @@ // of the Apache-2.0 license. See the LICENSE file for details. import { FunctionMetadataV7 } from '../../interfaces/metadata/types'; -import { Balance, Index } from '../../interfaces/runtime'; +import { Address, Balance, Call, Index } from '../../interfaces/runtime'; import { AnyU8a, ArgsDef, Codec, ExtrinsicPayloadValue, IExtrinsic, IHash, IKeyringPair, SignatureOptions } from '../../types'; import { assert, isHex, isU8a, u8aConcat, u8aToHex, u8aToU8a } from '@polkadot/util'; +import { ClassOf } from '../../codec/create'; import Base from '../../codec/Base'; import Compact from '../../codec/Compact'; -import Address from '../Generic/Address'; -import Call from '../Generic/Call'; import ExtrinsicV1, { ExtrinsicValueV1 } from './v1/Extrinsic'; import ExtrinsicV2, { ExtrinsicValueV2 } from './v2/Extrinsic'; import ExtrinsicV3, { ExtrinsicValueV3 } from './v3/Extrinsic'; @@ -85,7 +84,7 @@ export default class Extrinsic extends Base', method: 'Bytes', - era: ExtrinsicEra, + era: 'ExtrinsicEra', blockHash: 'Hash' }, value); } diff --git a/packages/types/src/primitive/Extrinsic/v1/ExtrinsicSignature.ts b/packages/types/src/primitive/Extrinsic/v1/ExtrinsicSignature.ts index 198597eb9b..c54f8607e0 100644 --- a/packages/types/src/primitive/Extrinsic/v1/ExtrinsicSignature.ts +++ b/packages/types/src/primitive/Extrinsic/v1/ExtrinsicSignature.ts @@ -2,15 +2,13 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { Address, Balance, Index, Signature } from '../../../interfaces/runtime'; +import { Address, Balance, Call, ExtrinsicEra, Index, Signature } from '../../../interfaces/runtime'; import { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, SignatureOptions } from '../../../types'; import { ExtrinsicSignatureOptions } from '../types'; import { createType } from '../../../codec/create'; import Compact from '../../../codec/Compact'; import Struct from '../../../codec/Struct'; -import Call from '../../Generic/Call'; -import ExtrinsicEra from '../ExtrinsicEra'; import { EMPTY_U8A, IMMORTAL_ERA } from '../constants'; import ExtrinsicPayloadV1 from './ExtrinsicPayload'; @@ -30,7 +28,7 @@ export default class ExtrinsicSignatureV1 extends Struct implements IExtrinsicSi signer: 'Address', signature: 'Signature', nonce: 'Compact', - era: ExtrinsicEra + era: 'ExtrinsicEra' }, ExtrinsicSignatureV1.decodeExtrinsicSignature(value, isSigned)); } @@ -128,6 +126,7 @@ export default class ExtrinsicSignatureV1 extends Struct implements IExtrinsicSi genesisHash, method: method.toHex(), nonce, + specVersion: 0, // unsed for v1, added for compat tip: 0 }); const signature = createType('Signature', payload.sign(account)); diff --git a/packages/types/src/primitive/Extrinsic/v2/Extrinsic.spec.ts b/packages/types/src/primitive/Extrinsic/v2/Extrinsic.spec.ts index 26711dd4fb..30df4d2f09 100644 --- a/packages/types/src/primitive/Extrinsic/v2/Extrinsic.spec.ts +++ b/packages/types/src/primitive/Extrinsic/v2/Extrinsic.spec.ts @@ -2,6 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. +import BN from 'bn.js'; import extrinsics from '@polkadot/api-metadata/extrinsics/static'; import testingPairs from '@polkadot/keyring/testingPairs'; @@ -43,6 +44,14 @@ describe('ExtrinsicV2', (): void => { blockHash: '0xec7afaf1cca720ce88c1d1b689d81f0583cc15a97d621cf046dd9abf605ef22f', genesisHash: '0xdcd1346701ca8396496e52aa2785b1748deb6db09551b72159dcb3e08991025b', nonce: 1, + runtimeVersion: { + apis: [], + authoringVersion: new BN(123), + implName: 'test', + implVersion: new BN(123), + specName: 'test', + specVersion: new BN(123) + }, tip: 2 }).toHex() ).toEqual( diff --git a/packages/types/src/primitive/Extrinsic/v2/Extrinsic.ts b/packages/types/src/primitive/Extrinsic/v2/Extrinsic.ts index 3f470b3d32..c688cdf8e5 100644 --- a/packages/types/src/primitive/Extrinsic/v2/Extrinsic.ts +++ b/packages/types/src/primitive/Extrinsic/v2/Extrinsic.ts @@ -2,21 +2,21 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. +import { Address, Call } from '../../../interfaces/runtime'; import { ExtrinsicPayloadValue, IExtrinsicImpl, IKeyringPair, SignatureOptions } from '../../../types'; import { ExtrinsicOptions } from '../types'; import { isU8a } from '@polkadot/util'; +import { createType, ClassOf } from '../../../codec/create'; import Struct from '../../../codec/Struct'; -import Call from '../../Generic/Call'; -import Address from '../../Generic/Address'; -import ExtrinsicSignature from './ExtrinsicSignature'; +import ExtrinsicSignatureV2 from './ExtrinsicSignature'; const TRANSACTION_VERSION = 2; export interface ExtrinsicValueV2 { method?: Call; - signature?: ExtrinsicSignature; + signature?: ExtrinsicSignatureV2; } /** @@ -27,8 +27,8 @@ export interface ExtrinsicValueV2 { export default class ExtrinsicV2 extends Struct implements IExtrinsicImpl { public constructor (value?: Uint8Array | ExtrinsicValueV2 | Call, { isSigned }: ExtrinsicOptions = {}) { super({ - signature: ExtrinsicSignature, - method: Call + signature: ExtrinsicSignatureV2, + method: 'Call' }, ExtrinsicV2.decodeExtrinsic(value, isSigned)); } @@ -37,12 +37,12 @@ export default class ExtrinsicV2 extends Struct implements IExtrinsicImpl { return {}; } else if (value instanceof ExtrinsicV2) { return value; - } else if (value instanceof Call) { + } else if (value instanceof ClassOf('Call')) { return { method: value }; } else if (isU8a(value)) { // here we decode manually since we need to pull through the version information - const signature = new ExtrinsicSignature(value, { isSigned }); - const method = new Call(value.subarray(signature.encodedLength)); + const signature = new ExtrinsicSignatureV2(value, { isSigned }); + const method = createType('Call', value.subarray(signature.encodedLength)); return { method, @@ -68,10 +68,10 @@ export default class ExtrinsicV2 extends Struct implements IExtrinsicImpl { } /** - * @description The [[ExtrinsicSignature]] + * @description The [[ExtrinsicSignatureV2]] */ - public get signature (): ExtrinsicSignature { - return this.get('signature') as ExtrinsicSignature; + public get signature (): ExtrinsicSignatureV2 { + return this.get('signature') as ExtrinsicSignatureV2; } /** @@ -82,7 +82,7 @@ export default class ExtrinsicV2 extends Struct implements IExtrinsicImpl { } /** - * @description Add an [[ExtrinsicSignature]] to the extrinsic (already generated) + * @description Add an [[ExtrinsicSignatureV2]] to the extrinsic (already generated) */ public addSignature (signer: Address | Uint8Array | string, signature: Uint8Array | string, payload: ExtrinsicPayloadValue | Uint8Array | string): ExtrinsicV2 { this.signature.addSignature(signer, signature, payload); diff --git a/packages/types/src/primitive/Extrinsic/v2/ExtrinsicExtra.spec.ts b/packages/types/src/primitive/Extrinsic/v2/ExtrinsicExtra.spec.ts deleted file mode 100644 index b84db55e04..0000000000 --- a/packages/types/src/primitive/Extrinsic/v2/ExtrinsicExtra.spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2017-2019 @polkadot/types authors & contributors -// This software may be modified and distributed under the terms -// of the Apache-2.0 license. See the LICENSE file for details. - -import '../../../injector'; - -import ExtrinsicExtra from './ExtrinsicExtra'; - -describe('ExtrinsicExtraV2', (): void => { - it('encodes to a sane Uint8Array (default construction)', (): void => { - expect( - new ExtrinsicExtra().toU8a() - ).toEqual(new Uint8Array([0, 0, 0])); - }); - - it('encodes to a sane Uint8Array (struct in)', (): void => { - expect( - new ExtrinsicExtra({ nonce: 1, tip: 2 }).toU8a() - ).toEqual(new Uint8Array([0, 4, 8])); // numbers are Compact - }); - - it('encodes to a sane Uint8Array (Uint8Array in)', (): void => { - expect( - new ExtrinsicExtra(new Uint8Array([0, 8, 4])).toU8a() - ).toEqual(new Uint8Array([0, 8, 4])); - }); -}); diff --git a/packages/types/src/primitive/Extrinsic/v2/ExtrinsicExtra.ts b/packages/types/src/primitive/Extrinsic/v2/ExtrinsicExtra.ts deleted file mode 100644 index 241b9ab372..0000000000 --- a/packages/types/src/primitive/Extrinsic/v2/ExtrinsicExtra.ts +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2017-2019 @polkadot/types authors & contributors -// This software may be modified and distributed under the terms -// of the Apache-2.0 license. See the LICENSE file for details. - -import { Balance, Index } from '../../../interfaces/runtime'; -import { ExtrinsicExtraValue } from '../types'; - -import Compact from '../../../codec/Compact'; -import Struct from '../../../codec/Struct'; -import Address from '../../Generic/Address'; -import ExtrinsicEra from '../ExtrinsicEra'; - -/** - * @name ExtrinsicExtraV2 - * @description - * A container for the extra information in an extrinsic - */ -export default class ExtrinsicExtraV2 extends Struct { - public constructor (value?: ExtrinsicExtraValue | Uint8Array) { - super({ - era: ExtrinsicEra, - nonce: 'Compact', - tip: 'Compact' - }, value); - } - - /** - * @description The [[ExtrinsicEra]] (mortal or immortal) this signature applies to - */ - public get era (): ExtrinsicEra { - return this.get('era') as ExtrinsicEra; - } - - /** - * @description The [[Index]] for the signature - */ - public get nonce (): Compact { - return this.get('nonce') as Compact; - } - - /** - * @description The [[Address]] that signed - */ - public get signer (): Address { - return this.get('signer') as Address; - } - - /** - * @description The [[Balance]] tip - */ - public get tip (): Compact { - return this.get('tip') as Compact; - } -} diff --git a/packages/types/src/primitive/Extrinsic/v2/ExtrinsicPayload.ts b/packages/types/src/primitive/Extrinsic/v2/ExtrinsicPayload.ts index 2eb7c724d9..b0cfeb148c 100644 --- a/packages/types/src/primitive/Extrinsic/v2/ExtrinsicPayload.ts +++ b/packages/types/src/primitive/Extrinsic/v2/ExtrinsicPayload.ts @@ -2,15 +2,23 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { Balance, Hash, Index } from '../../../interfaces/runtime'; -import { ExtrinsicPayloadValue, IKeyringPair } from '../../../types'; +import { Balance, ExtrinsicEra, Hash, Index } from '../../../interfaces/runtime'; +import { ExtrinsicPayloadValue, IKeyringPair, InterfaceTypes } from '../../../types'; import Compact from '../../../codec/Compact'; import Struct from '../../../codec/Struct'; import Bytes from '../../../primitive/Bytes'; -import ExtrinsicEra from '../ExtrinsicEra'; import { sign } from '../util'; +// SignedExtra adds the following fields to the payload +const SignedExtraV2: Record = { + // system::CheckEra + blockHash: 'Hash' + // system::CheckNonce + // system::CheckWeight + // balances::TakeFees +}; + /** * @name ExtrinsicPayloadV2 * @description @@ -21,10 +29,10 @@ export default class ExtrinsicPayloadV2 extends Struct { public constructor (value?: ExtrinsicPayloadValue | Uint8Array | string) { super({ method: 'Bytes', - era: ExtrinsicEra, + era: 'ExtrinsicEra', nonce: 'Compact', tip: 'Compact', - blockHash: 'Hash' + ...SignedExtraV2 }, value); } diff --git a/packages/types/src/primitive/Extrinsic/v2/ExtrinsicSignature.ts b/packages/types/src/primitive/Extrinsic/v2/ExtrinsicSignature.ts index 8b71952a0f..0647c45552 100644 --- a/packages/types/src/primitive/Extrinsic/v2/ExtrinsicSignature.ts +++ b/packages/types/src/primitive/Extrinsic/v2/ExtrinsicSignature.ts @@ -2,17 +2,14 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { Address, Balance, Index, Signature } from '../../../interfaces/runtime'; +import { Address, Balance, Call, ExtrinsicEra, Index, Signature } from '../../../interfaces/runtime'; import { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, SignatureOptions } from '../../../types'; import { ExtrinsicSignatureOptions } from '../types'; import { createType } from '../../../codec/create'; import Compact from '../../../codec/Compact'; import Struct from '../../../codec/Struct'; -import Call from '../../Generic/Call'; -import ExtrinsicEra from '../ExtrinsicEra'; import { EMPTY_U8A, IMMORTAL_ERA } from '../constants'; -import ExtrinsicExtraV2 from './ExtrinsicExtra'; import ExtrinsicPayloadV2 from './ExtrinsicPayload'; /** @@ -25,7 +22,9 @@ export default class ExtrinsicSignatureV2 extends Struct implements IExtrinsicSi super({ signer: 'Address', signature: 'Signature', - extra: ExtrinsicExtraV2 + era: 'ExtrinsicEra', + nonce: 'Compact', + tip: 'Compact' }, ExtrinsicSignatureV2.decodeExtrinsicSignature(value, isSigned)); } @@ -57,25 +56,18 @@ export default class ExtrinsicSignatureV2 extends Struct implements IExtrinsicSi return !this.signature.isEmpty; } - /** - * @description Returns the extra extrinsic info - */ - public get extra (): ExtrinsicExtraV2 { - return this.get('extra') as ExtrinsicExtraV2; - } - /** * @description The [[ExtrinsicEra]] (mortal or immortal) this signature applies to */ public get era (): ExtrinsicEra { - return this.extra.era; + return this.get('era') as ExtrinsicEra; } /** * @description The [[Index]] for the signature */ public get nonce (): Compact { - return this.extra.nonce; + return this.get('nonce') as Compact; } /** @@ -96,16 +88,15 @@ export default class ExtrinsicSignatureV2 extends Struct implements IExtrinsicSi * @description The [[Balance]] tip */ public get tip (): Compact { - return this.extra.tip; + return this.get('tip') as Compact; } protected injectSignature (signer: Address, signature: Signature, { era, nonce, tip }: ExtrinsicPayloadV2): IExtrinsicSignature { - this.extra.set('era', era); - this.extra.set('nonce', nonce); - this.extra.set('tip', tip); - + this.set('era', era); + this.set('nonce', nonce); this.set('signer', signer); this.set('signature', signature); + this.set('tip', tip); return this; } @@ -132,6 +123,7 @@ export default class ExtrinsicSignatureV2 extends Struct implements IExtrinsicSi genesisHash, method: method.toHex(), nonce, + specVersion: 0, // unused for v2 tip: tip || 0 }); const signature = createType('Signature', payload.sign(account)); diff --git a/packages/types/src/primitive/Extrinsic/v3/Extrinsic.spec.ts b/packages/types/src/primitive/Extrinsic/v3/Extrinsic.spec.ts index 6015125f96..e195fa135a 100644 --- a/packages/types/src/primitive/Extrinsic/v3/Extrinsic.spec.ts +++ b/packages/types/src/primitive/Extrinsic/v3/Extrinsic.spec.ts @@ -2,6 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. +import BN from 'bn.js'; import extrinsics from '@polkadot/api-metadata/extrinsics/static'; import testingPairs from '@polkadot/keyring/testingPairs'; @@ -43,14 +44,22 @@ describe('ExtrinsicV3', (): void => { blockHash: '0xec7afaf1cca720ce88c1d1b689d81f0583cc15a97d621cf046dd9abf605ef22f', genesisHash: '0xdcd1346701ca8396496e52aa2785b1748deb6db09551b72159dcb3e08991025b', nonce: 1, + runtimeVersion: { + apis: [], + authoringVersion: new BN(123), + implName: 'test', + implVersion: new BN(123), + specName: 'test', + specVersion: new BN(123) + }, tip: 2 }).toHex() ).toEqual( '0x' + 'ff' + 'd172a74cda4c865912c32ba0a80a57ae69abae410e5ccb59dee84e2f4432db4f' + - '2bb401483999053d2d69a4aebefb9682c8710ddd495d1298d4eedd241c73869f' + - '9d32c82dba98b12ef74bea5f987851b592956de3cf3e946533da815e3b6a2904' + + '21de8ff3cae3ee72ced565ed5f79fd153dc84a3be9166b7904eecde8045ba59a' + + 'd2f998cc970e59157f168ec762eea061f4930b5288f57a45a1c1911863860208' + '000408' + // era. nonce, tip '0500' + 'ff' + diff --git a/packages/types/src/primitive/Extrinsic/v3/Extrinsic.ts b/packages/types/src/primitive/Extrinsic/v3/Extrinsic.ts index 4a6d7ca4f7..03e60c03ea 100644 --- a/packages/types/src/primitive/Extrinsic/v3/Extrinsic.ts +++ b/packages/types/src/primitive/Extrinsic/v3/Extrinsic.ts @@ -2,21 +2,21 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. +import { Address, Call } from '../../../interfaces/runtime'; import { ExtrinsicPayloadValue, IExtrinsicImpl, IKeyringPair, SignatureOptions } from '../../../types'; import { ExtrinsicOptions } from '../types'; import { isU8a } from '@polkadot/util'; +import { createType, ClassOf } from '../../../codec/create'; import Struct from '../../../codec/Struct'; -import Call from '../../Generic/Call'; -import Address from '../../Generic/Address'; -import ExtrinsicSignature from './ExtrinsicSignature'; +import ExtrinsicSignatureV3 from './ExtrinsicSignature'; const TRANSACTION_VERSION = 3; export interface ExtrinsicValueV3 { method?: Call; - signature?: ExtrinsicSignature; + signature?: ExtrinsicSignatureV3; } /** @@ -27,8 +27,8 @@ export interface ExtrinsicValueV3 { export default class ExtrinsicV3 extends Struct implements IExtrinsicImpl { public constructor (value?: Uint8Array | ExtrinsicValueV3 | Call, { isSigned }: ExtrinsicOptions = {}) { super({ - signature: ExtrinsicSignature, - method: Call + signature: ExtrinsicSignatureV3, + method: 'Call' }, ExtrinsicV3.decodeExtrinsic(value, isSigned)); } @@ -37,12 +37,12 @@ export default class ExtrinsicV3 extends Struct implements IExtrinsicImpl { return {}; } else if (value instanceof ExtrinsicV3) { return value; - } else if (value instanceof Call) { + } else if (value instanceof ClassOf('Call')) { return { method: value }; } else if (isU8a(value)) { // here we decode manually since we need to pull through the version information - const signature = new ExtrinsicSignature(value, { isSigned }); - const method = new Call(value.subarray(signature.encodedLength)); + const signature = new ExtrinsicSignatureV3(value, { isSigned }); + const method = createType('Call', value.subarray(signature.encodedLength)); return { method, @@ -68,10 +68,10 @@ export default class ExtrinsicV3 extends Struct implements IExtrinsicImpl { } /** - * @description The [[ExtrinsicSignature]] + * @description The [[ExtrinsicSignatureV3]] */ - public get signature (): ExtrinsicSignature { - return this.get('signature') as ExtrinsicSignature; + public get signature (): ExtrinsicSignatureV3 { + return this.get('signature') as ExtrinsicSignatureV3; } /** @@ -82,7 +82,7 @@ export default class ExtrinsicV3 extends Struct implements IExtrinsicImpl { } /** - * @description Add an [[ExtrinsicSignature]] to the extrinsic (already generated) + * @description Add an [[ExtrinsicSignatureV3]] to the extrinsic (already generated) */ public addSignature (signer: Address | Uint8Array | string, signature: Uint8Array | string, payload: ExtrinsicPayloadValue | Uint8Array | string): ExtrinsicV3 { this.signature.addSignature(signer, signature, payload); diff --git a/packages/types/src/primitive/Extrinsic/v3/ExtrinsicPayload.ts b/packages/types/src/primitive/Extrinsic/v3/ExtrinsicPayload.ts index d4cac98375..fab3102c8d 100644 --- a/packages/types/src/primitive/Extrinsic/v3/ExtrinsicPayload.ts +++ b/packages/types/src/primitive/Extrinsic/v3/ExtrinsicPayload.ts @@ -2,15 +2,28 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { Balance, Hash, Index } from '../../../interfaces/runtime'; -import { ExtrinsicPayloadValue, IKeyringPair } from '../../../types'; +import { Balance, ExtrinsicEra, Hash, Index } from '../../../interfaces/runtime'; +import { ExtrinsicPayloadValue, IKeyringPair, InterfaceTypes } from '../../../types'; import Compact from '../../../codec/Compact'; import Struct from '../../../codec/Struct'; import Bytes from '../../../primitive/Bytes'; -import ExtrinsicEra from '../ExtrinsicEra'; +import u32 from '../../../primitive/U32'; import { sign } from '../util'; +// SignedExtra adds the following fields to the payload +const SignedExtraV3: Record = { + // system::CheckVersion + specVersion: 'u32', + // system::CheckGenesis + genesisHash: 'Hash', + // system::CheckEra + blockHash: 'Hash' + // system::CheckNonce + // system::CheckWeight + // balances::TakeFees +}; + /** * @name ExtrinsicPayloadV3 * @description @@ -21,11 +34,10 @@ export default class ExtrinsicPayloadV3 extends Struct { public constructor (value?: ExtrinsicPayloadValue | Uint8Array | string) { super({ method: 'Bytes', - era: ExtrinsicEra, + era: 'ExtrinsicEra', nonce: 'Compact', tip: 'Compact', - genesisHash: 'Hash', - blockHash: 'Hash' + ...SignedExtraV3 }, value); } @@ -64,6 +76,13 @@ export default class ExtrinsicPayloadV3 extends Struct { return this.get('nonce') as Compact; } + /** + * @description The specVersion for this signature + */ + public get specVersion (): u32 { + return this.get('specVersion') as u32; + } + /** * @description The tip [[Balance]] */ diff --git a/packages/types/src/primitive/Extrinsic/v3/ExtrinsicSignature.ts b/packages/types/src/primitive/Extrinsic/v3/ExtrinsicSignature.ts index d5f115c319..6e5859c996 100644 --- a/packages/types/src/primitive/Extrinsic/v3/ExtrinsicSignature.ts +++ b/packages/types/src/primitive/Extrinsic/v3/ExtrinsicSignature.ts @@ -2,11 +2,10 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { Address } from '../../../interfaces/runtime'; +import { Address, Call } from '../../../interfaces/runtime'; import { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, SignatureOptions } from '../../../types'; import { createType } from '../../../codec/create'; -import Call from '../../Generic/Call'; import { IMMORTAL_ERA } from '../constants'; import ExtrinsicSignatureV2 from '../v2/ExtrinsicSignature'; import ExtrinsicPayloadV3 from './ExtrinsicPayload'; @@ -31,7 +30,7 @@ export default class ExtrinsicSignatureV3 extends ExtrinsicSignatureV2 { /** * @description Generate a payload and pplies the signature from a keypair */ - public sign (method: Call, account: IKeyringPair, { blockHash, era, genesisHash, nonce, tip }: SignatureOptions): IExtrinsicSignature { + public sign (method: Call, account: IKeyringPair, { blockHash, era, genesisHash, nonce, tip, runtimeVersion: { specVersion } }: SignatureOptions): IExtrinsicSignature { const signer = createType('Address', account.publicKey); const payload = new ExtrinsicPayloadV3({ blockHash, @@ -39,6 +38,7 @@ export default class ExtrinsicSignatureV3 extends ExtrinsicSignatureV2 { genesisHash, method: method.toHex(), nonce, + specVersion, tip: tip || 0 }); const signature = createType('Signature', payload.sign(account)); diff --git a/packages/types/src/types.ts b/packages/types/src/types.ts index 5ffcc0aeb0..416abf2a78 100644 --- a/packages/types/src/types.ts +++ b/packages/types/src/types.ts @@ -148,8 +148,8 @@ export interface SignatureOptions { era?: IExtrinsicEra; genesisHash: AnyU8a; nonce: AnyNumber; + runtimeVersion: RuntimeVersionInterface; tip?: AnyNumber; - version?: RuntimeVersionInterface; } export type ArgsDef = Record; @@ -180,6 +180,7 @@ export interface ExtrinsicPayloadValue { genesisHash: AnyU8a; method: AnyU8a | IMethod; nonce: AnyNumber; + specVersion: AnyNumber; tip: AnyNumber; }