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
This commit is contained in:
Jaco Greeff
2019-08-19 09:28:52 +02:00
committed by GitHub
parent c2b29eff7f
commit a9746b3641
21 changed files with 156 additions and 174 deletions
@@ -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' +
+2
View File
@@ -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
});
+5 -2
View File
@@ -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<Index>;
runtimeVersion: RuntimeVersion;
tip: Compact<Balance>;
version: u8;
}
@@ -30,6 +31,7 @@ const _Payload: Constructor<SignerPayloadType> = Struct.with({
genesisHash: 'Hash',
method: 'Call',
nonce: 'Compact<Index>',
runtimeVersion: 'RuntimeVersion',
tip: 'Compact<Balance>',
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()
};
+4 -5
View File
@@ -176,10 +176,11 @@ export default function createSubmittableExtrinsic<ApiType> (
function expandOptions (options: Partial<SignerOptions>, 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<ApiType> (
...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) {
+5
View File
@@ -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
*/
@@ -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<ExtrinsicV1 | ExtrinsicV2 | Extrinsi
assert(total <= value.length, `Extrinsic: required length less than remainder, expected at least ${total}, found ${value.length}`);
return Extrinsic.decodeU8a(value.subarray(offset, total));
} else if (value instanceof Call) {
} else if (value instanceof ClassOf('Call')) {
return Extrinsic.newFromValue({ method: value }, version);
}
@@ -234,6 +233,7 @@ export default class Extrinsic extends Base<ExtrinsicV1 | ExtrinsicV2 | Extrinsi
genesisHash: new Uint8Array(),
method: this.method.toHex(),
nonce: args[0] as string,
specVersion: 0,
tip: 0
};
}
@@ -11,6 +11,7 @@ import { createType } from '../../codec/create';
import Base from '../../codec/Base';
import Compact from '../../codec/Compact';
import U8a from '../../codec/U8a';
import u32 from '../../primitive/U32';
import ExtrinsicPayloadV1 from './v1/ExtrinsicPayload';
import ExtrinsicPayloadV2 from './v2/ExtrinsicPayload';
import ExtrinsicPayloadV3 from './v3/ExtrinsicPayload';
@@ -83,6 +84,14 @@ export default class ExtrinsicPayload extends Base<ExtrinsicPayloadV1 | Extrinsi
return this.raw.nonce;
}
/**
* @description The specVersion as a [[u32]] for this payload
*/
public get specVersion (): u32 {
// NOTE only v3
return (this.raw as ExtrinsicPayloadV3).specVersion || createType('u32');
}
/**
* @description The [[Balance]]
*/
@@ -2,19 +2,19 @@
// 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 } from '../../../codec/create';
import Struct from '../../../codec/Struct';
import Call from '../../Generic/Call';
import Address from '../../Generic/Address';
import ExtrinsicSignature from './ExtrinsicSignature';
import ExtrinsicSignatureV1 from './ExtrinsicSignature';
export interface ExtrinsicValueV1 {
method?: Call;
signature?: ExtrinsicSignature;
signature?: ExtrinsicSignatureV1;
}
const TRANSACTION_VERSION = 1;
@@ -27,8 +27,8 @@ const TRANSACTION_VERSION = 1;
export default class ExtrinsicV1 extends Struct implements IExtrinsicImpl {
public constructor (value?: Uint8Array | ExtrinsicValueV1, { isSigned }: ExtrinsicOptions = {}) {
super({
signature: ExtrinsicSignature,
method: Call
signature: ExtrinsicSignatureV1,
method: 'Call'
}, ExtrinsicV1.decodeExtrinsic(value, isSigned));
}
@@ -39,8 +39,8 @@ export default class ExtrinsicV1 extends Struct implements IExtrinsicImpl {
return 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 ExtrinsicSignatureV1(value, { isSigned });
const method = createType('Call', value.subarray(signature.encodedLength));
return {
method,
@@ -66,10 +66,10 @@ export default class ExtrinsicV1 extends Struct implements IExtrinsicImpl {
}
/**
* @description The [[ExtrinsicSignature]]
* @description The [[ExtrinsicSignatureV1]]
*/
public get signature (): ExtrinsicSignature {
return this.get('signature') as ExtrinsicSignature;
public get signature (): ExtrinsicSignatureV1 {
return this.get('signature') as ExtrinsicSignatureV1;
}
/**
@@ -80,7 +80,7 @@ export default class ExtrinsicV1 extends Struct implements IExtrinsicImpl {
}
/**
* @description Add an [[ExtrinsicSignature]] to the extrinsic (already generated)
* @description Add an [[ExtrinsicSignatureV1]] to the extrinsic (already generated)
*/
public addSignature (signer: Address | Uint8Array | string, signature: Uint8Array | string, payload: ExtrinsicPayloadValue | Uint8Array | string): ExtrinsicV1 {
this.signature.addSignature(signer, signature, payload);
@@ -2,13 +2,12 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Hash, Index } from '../../../interfaces/runtime';
import { Hash, ExtrinsicEra, Index } from '../../../interfaces/runtime';
import { ExtrinsicPayloadValue, IKeyringPair } 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';
/**
@@ -27,7 +26,7 @@ export default class ExtrinsicPayloadV1 extends Struct {
super({
nonce: 'Compact<Index>',
method: 'Bytes',
era: ExtrinsicEra,
era: 'ExtrinsicEra',
blockHash: 'Hash'
}, value);
}
@@ -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<Index>',
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));
@@ -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(
@@ -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);
@@ -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]));
});
});
@@ -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<Index>',
tip: 'Compact<Balance>'
}, 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<Index> {
return this.get('nonce') as Compact<Index>;
}
/**
* @description The [[Address]] that signed
*/
public get signer (): Address {
return this.get('signer') as Address;
}
/**
* @description The [[Balance]] tip
*/
public get tip (): Compact<Balance> {
return this.get('tip') as Compact<Balance>;
}
}
@@ -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<string, InterfaceTypes> = {
// system::CheckEra<Runtime>
blockHash: 'Hash'
// system::CheckNonce<Runtime>
// system::CheckWeight<Runtime>
// balances::TakeFees<Runtime>
};
/**
* @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<Index>',
tip: 'Compact<Balance>',
blockHash: 'Hash'
...SignedExtraV2
}, value);
}
@@ -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<Index>',
tip: 'Compact<Balance>'
}, 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<Index> {
return this.extra.nonce;
return this.get('nonce') as Compact<Index>;
}
/**
@@ -96,16 +88,15 @@ export default class ExtrinsicSignatureV2 extends Struct implements IExtrinsicSi
* @description The [[Balance]] tip
*/
public get tip (): Compact<Balance> {
return this.extra.tip;
return this.get('tip') as Compact<Balance>;
}
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));
@@ -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' +
@@ -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);
@@ -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<string, InterfaceTypes> = {
// system::CheckVersion<Runtime>
specVersion: 'u32',
// system::CheckGenesis<Runtime>
genesisHash: 'Hash',
// system::CheckEra<Runtime>
blockHash: 'Hash'
// system::CheckNonce<Runtime>
// system::CheckWeight<Runtime>
// balances::TakeFees<Runtime>
};
/**
* @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<Index>',
tip: 'Compact<Balance>',
genesisHash: 'Hash',
blockHash: 'Hash'
...SignedExtraV3
}, value);
}
@@ -64,6 +76,13 @@ export default class ExtrinsicPayloadV3 extends Struct {
return this.get('nonce') as Compact<Index>;
}
/**
* @description The specVersion for this signature
*/
public get specVersion (): u32 {
return this.get('specVersion') as u32;
}
/**
* @description The tip [[Balance]]
*/
@@ -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));
+2 -1
View File
@@ -148,8 +148,8 @@ export interface SignatureOptions {
era?: IExtrinsicEra;
genesisHash: AnyU8a;
nonce: AnyNumber;
runtimeVersion: RuntimeVersionInterface;
tip?: AnyNumber;
version?: RuntimeVersionInterface;
}
export type ArgsDef = Record<string, Constructor>;
@@ -180,6 +180,7 @@ export interface ExtrinsicPayloadValue {
genesisHash: AnyU8a;
method: AnyU8a | IMethod;
nonce: AnyNumber;
specVersion: AnyNumber;
tip: AnyNumber;
}