Drop support for Extrinsic V1, V2 & V3 (#2638)

* Drop support for Extrinsic V1 & V2

* Update interfaces

* Swap default to V4

* Remove V1/V2 extrinsic tests

* Fix v3 toU8a

* Fix Decorated tests for v4

* V3 payload extends v4 payload

* Revert "V3 payload extends v4 payload"

This reverts commit b1e546aa08fe1027aa77a235fd3b98441c426812.

* Drop extrinsic v3

* Update CHANGELOG.md
This commit is contained in:
Jaco Greeff
2020-09-26 12:02:27 +02:00
committed by GitHub
parent f2fbedb407
commit cb93cb34b7
31 changed files with 38 additions and 1441 deletions
@@ -34,7 +34,7 @@ describe('Decorated', () => {
// length (encoded)
4 << 2,
// version, no signature
1,
4,
// index
3, 0,
// values, Compact<Moment>
@@ -31,7 +31,7 @@ describe('fromMetadata', (): void => {
// length (encoded)
4 << 2,
// version, no signature
1,
4,
// index
3, 0,
// values, Compact<Moment>
@@ -37,12 +37,13 @@ describe('extrinsics', (): void => {
}).toHex()
).toEqual(
'0x' +
'2502' + // length
'81' + // signed flag
'2d02' + // length
'84' + // signed flag
'ffd172a74cda4c865912c32ba0a80a57ae69abae410e5ccb59dee84e2f4432db4f' + // who
'5322aca55349f72dbfa57f3e2484f3457c960fbd7f540fcf70433180c70f8af5' + // sig1
'0f3c8dd7a7fbc8e23cfd9e3bc87f31008598e2be3feef512ed942f0240e1a908' + // sig2
'0000' + // nonce & era
'00' + // ed25519
'4634f7b973084f983ef48e2afbd72a990f7d4dd9d86c39e645cb34d9a45466b6' + // sig1
'263f0f2020363a6475f91e323a8b1bd43dedd97e78ec3c5d5b5197466305400e' + // sig2
'000000' + // nonce, era, tip
'0600' + // balances.transfer
'ffd7568e5f0a7eda67a82691ff379ac4bba4f9c9b859fe779b5d46363b61ad2db9' + // to
'e56c' // value
+1 -28
View File
@@ -20,7 +20,7 @@ import { ApprovalFlag, DefunctVoter, Renouncing, SetIndex, Vote, VoteIndex, Vote
import { CreatedBlock, ImportedAux } from '@polkadot/types/interfaces/engine';
import { EthereumAccountId, EthereumLookupSource } from '@polkadot/types/interfaces/ethereum';
import { Account, Log, Vicinity } from '@polkadot/types/interfaces/evm';
import { EcdsaSignature, Ed25519Signature, Extrinsic, ExtrinsicEra, ExtrinsicPayload, ExtrinsicPayloadUnknown, ExtrinsicPayloadV1, ExtrinsicPayloadV2, ExtrinsicPayloadV3, ExtrinsicPayloadV4, ExtrinsicSignatureV1, ExtrinsicSignatureV2, ExtrinsicSignatureV3, ExtrinsicSignatureV4, ExtrinsicUnknown, ExtrinsicV1, ExtrinsicV2, ExtrinsicV3, ExtrinsicV4, ImmortalEra, MortalEra, MultiSignature, Signature, SignerPayload, Sr25519Signature } from '@polkadot/types/interfaces/extrinsics';
import { EcdsaSignature, Ed25519Signature, Extrinsic, ExtrinsicEra, ExtrinsicPayload, ExtrinsicPayloadUnknown, ExtrinsicPayloadV4, ExtrinsicSignatureV4, ExtrinsicUnknown, ExtrinsicV4, ImmortalEra, MortalEra, MultiSignature, Signature, SignerPayload, Sr25519Signature } from '@polkadot/types/interfaces/extrinsics';
import { AssetOptions, Owner, PermissionLatest, PermissionVersions, PermissionsV1 } from '@polkadot/types/interfaces/genericAsset';
import { AuthorityIndex, AuthorityList, AuthorityWeight, EncodedFinalityProofs, GrandpaEquivocation, GrandpaEquivocationProof, GrandpaEquivocationValue, GrandpaPrevote, JustificationNotification, KeyOwnerProof, NextAuthority, PendingPause, PendingResume, Precommits, Prevotes, ReportedRoundStates, RoundState, SetId, StoredPendingChange, StoredState } from '@polkadot/types/interfaces/grandpa';
import { IdentityFields, IdentityInfo, IdentityInfoAdditional, IdentityJudgement, RegistrarIndex, RegistrarInfo, Registration, RegistrationJudgement } from '@polkadot/types/interfaces/identity';
@@ -626,33 +626,6 @@ declare module '@polkadot/types/types/registry' {
ExtrinsicPayload: ExtrinsicPayload;
'Option<ExtrinsicPayload>': Option<ExtrinsicPayload>;
'Vec<ExtrinsicPayload>': Vec<ExtrinsicPayload>;
ExtrinsicV1: ExtrinsicV1;
'Option<ExtrinsicV1>': Option<ExtrinsicV1>;
'Vec<ExtrinsicV1>': Vec<ExtrinsicV1>;
ExtrinsicPayloadV1: ExtrinsicPayloadV1;
'Option<ExtrinsicPayloadV1>': Option<ExtrinsicPayloadV1>;
'Vec<ExtrinsicPayloadV1>': Vec<ExtrinsicPayloadV1>;
ExtrinsicSignatureV1: ExtrinsicSignatureV1;
'Option<ExtrinsicSignatureV1>': Option<ExtrinsicSignatureV1>;
'Vec<ExtrinsicSignatureV1>': Vec<ExtrinsicSignatureV1>;
ExtrinsicV2: ExtrinsicV2;
'Option<ExtrinsicV2>': Option<ExtrinsicV2>;
'Vec<ExtrinsicV2>': Vec<ExtrinsicV2>;
ExtrinsicPayloadV2: ExtrinsicPayloadV2;
'Option<ExtrinsicPayloadV2>': Option<ExtrinsicPayloadV2>;
'Vec<ExtrinsicPayloadV2>': Vec<ExtrinsicPayloadV2>;
ExtrinsicSignatureV2: ExtrinsicSignatureV2;
'Option<ExtrinsicSignatureV2>': Option<ExtrinsicSignatureV2>;
'Vec<ExtrinsicSignatureV2>': Vec<ExtrinsicSignatureV2>;
ExtrinsicV3: ExtrinsicV3;
'Option<ExtrinsicV3>': Option<ExtrinsicV3>;
'Vec<ExtrinsicV3>': Vec<ExtrinsicV3>;
ExtrinsicPayloadV3: ExtrinsicPayloadV3;
'Option<ExtrinsicPayloadV3>': Option<ExtrinsicPayloadV3>;
'Vec<ExtrinsicPayloadV3>': Vec<ExtrinsicPayloadV3>;
ExtrinsicSignatureV3: ExtrinsicSignatureV3;
'Option<ExtrinsicSignatureV3>': Option<ExtrinsicSignatureV3>;
'Vec<ExtrinsicSignatureV3>': Vec<ExtrinsicSignatureV3>;
ExtrinsicV4: ExtrinsicV4;
'Option<ExtrinsicV4>': Option<ExtrinsicV4>;
'Vec<ExtrinsicV4>': Vec<ExtrinsicV4>;
@@ -3,7 +3,6 @@
import Metadata from '@polkadot/metadata/Metadata';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import { hexToU8a } from '@polkadot/util';
import { TypeRegistry } from '../create';
import Extrinsic from './Extrinsic';
@@ -14,89 +13,6 @@ const metadata = new Metadata(registry, rpcMetadata);
registry.setMetadata(metadata);
describe('Extrinsic', (): void => {
describe('V1', (): void => {
it('decodes an actual transaction', (): void => {
const extrinsic = new Extrinsic(
registry,
'0x' +
'2502' +
'81' +
'ff' +
'bfc823aa75c30058eeec21abe2c2d6b7247418a4af89d67a2084c2ac864da080' +
'c0aa4df3b4926c3cd78bbdced31d8bdccb8604b779b71b90e58b2848df4a9ad6' +
'b0aa1aae6be7a05c9413a172b0325e4d214e5ff2b25098028b30f1a50be9c90e' +
'0c' + // nonce
'00' + // era
'0600' + // balances.transfer
'ff' +
'4a83f1c09be797bc3d9adce29818368b276a84e6b545ced492c25c948978d7f8' +
'e5c0'
);
expect(extrinsic.isSigned).toEqual(true);
expect(extrinsic.signer.toU8a()).toEqual(new Uint8Array([255, 191, 200, 35, 170, 117, 195, 0, 88, 238, 236, 33, 171, 226, 194, 214, 183, 36, 116, 24, 164, 175, 137, 214, 122, 32, 132, 194, 172, 134, 77, 160, 128]));
expect(extrinsic.signature.toHex()).toEqual('0xc0aa4df3b4926c3cd78bbdced31d8bdccb8604b779b71b90e58b2848df4a9ad6b0aa1aae6be7a05c9413a172b0325e4d214e5ff2b25098028b30f1a50be9c90e');
expect(extrinsic.nonce.toNumber()).toEqual(3);
expect(extrinsic.era.toU8a()).toEqual(new Uint8Array([0]));
expect(extrinsic.callIndex).toEqual(new Uint8Array([6, 0]));
expect(`${extrinsic.method.sectionName}.${extrinsic.method.methodName}`).toEqual('balances.transfer');
expect(extrinsic.args[0].toString()).toEqual('5DkQbYAExs3M2sZgT1Ec3mKfZnAQCL4Dt9beTCknkCUn5jzo');
});
});
describe('V2', (): void => {
it('decodes an actual transaction', (): void => {
const extrinsic = new Extrinsic(
registry,
'0x' +
'2902' + // yes, longer than in v1, 1 byte for the tip
'82' +
'ff' +
'bfc823aa75c30058eeec21abe2c2d6b7247418a4af89d67a2084c2ac864da080' +
'c0aa4df3b4926c3cd78bbdced31d8bdccb8604b779b71b90e58b2848df4a9ad6' +
'b0aa1aae6be7a05c9413a172b0325e4d214e5ff2b25098028b30f1a50be9c90e' +
'00' + // era
'0c' + // nonce
'08' + // tip
'0600' + // balances.transfer
'ff' +
'4a83f1c09be797bc3d9adce29818368b276a84e6b545ced492c25c948978d7f8' +
'e5c0'
);
expect(extrinsic.isSigned).toEqual(true);
expect(extrinsic.signer.toU8a()).toEqual(new Uint8Array([255, 191, 200, 35, 170, 117, 195, 0, 88, 238, 236, 33, 171, 226, 194, 214, 183, 36, 116, 24, 164, 175, 137, 214, 122, 32, 132, 194, 172, 134, 77, 160, 128]));
expect(extrinsic.signature.toHex()).toEqual('0xc0aa4df3b4926c3cd78bbdced31d8bdccb8604b779b71b90e58b2848df4a9ad6b0aa1aae6be7a05c9413a172b0325e4d214e5ff2b25098028b30f1a50be9c90e');
expect(extrinsic.era.toU8a()).toEqual(new Uint8Array([0]));
expect(extrinsic.nonce.toNumber()).toEqual(3);
expect(extrinsic.tip.toNumber()).toEqual(2);
expect(extrinsic.callIndex).toEqual(new Uint8Array([6, 0]));
expect(`${extrinsic.method.sectionName}.${extrinsic.method.methodName}`).toEqual('balances.transfer');
expect(extrinsic.args[0].toString()).toEqual('5DkQbYAExs3M2sZgT1Ec3mKfZnAQCL4Dt9beTCknkCUn5jzo');
});
it('constructs from itself', (): void => {
const input = '0x' +
'2902' +
'82' +
'ff' +
'bfc823aa75c30058eeec21abe2c2d6b7247418a4af89d67a2084c2ac864da080' +
'c0aa4df3b4926c3cd78bbdced31d8bdccb8604b779b71b90e58b2848df4a9ad6' +
'b0aa1aae6be7a05c9413a172b0325e4d214e5ff2b25098028b30f1a50be9c90e' +
'00' + // era
'00' + // nonce
'00' + // tip
'0600' + // balances.transfer
'ff' +
'4a83f1c09be797bc3d9adce29818368b276a84e6b545ced492c25c948978d7f8' +
'e5c0';
expect(
new Extrinsic(registry, new Extrinsic(registry, input)).toU8a()
).toEqual(hexToU8a(input));
});
});
describe('V4', (): void => {
it('decodes an actual transaction', (): void => {
const extrinsic = new Extrinsic(
+6 -9
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import { FunctionMetadataLatest } from '../interfaces/metadata/types';
import { EcdsaSignature, Ed25519Signature, ExtrinsicUnknown, ExtrinsicV1, ExtrinsicV2, ExtrinsicV3, ExtrinsicV4, Sr25519Signature } from '../interfaces/extrinsics';
import { EcdsaSignature, Ed25519Signature, ExtrinsicUnknown, ExtrinsicV4, Sr25519Signature } from '../interfaces/extrinsics';
import { Address, Balance, Call, Index } from '../interfaces/runtime';
import { AnyJson, AnyU8a, ArgsDef, Codec, ExtrinsicPayloadValue, IExtrinsic, IKeyringPair, InterfaceTypes, Registry, SignatureOptions } from '../types';
@@ -10,9 +10,6 @@ import { assert, isHex, isU8a, u8aConcat, u8aToHex, u8aToU8a } from '@polkadot/u
import Base from '../codec/Base';
import Compact from '../codec/Compact';
import { ExtrinsicValueV1 } from './v1/Extrinsic';
import { ExtrinsicValueV2 } from './v2/Extrinsic';
import { ExtrinsicValueV3 } from './v3/Extrinsic';
import { ExtrinsicValueV4 } from './v4/Extrinsic';
import ExtrinsicEra from './ExtrinsicEra';
import { BIT_SIGNED, BIT_UNSIGNED, DEFAULT_VERSION, UNMASK_VERSION } from './constants';
@@ -24,14 +21,14 @@ interface CreateOptions {
// NOTE The following 2 types, as well as the VERSION structure and the latest export
// is to be changed with the addition of a new extrinsic version
type ExtrinsicVx = ExtrinsicV1 | ExtrinsicV2 | ExtrinsicV3 | ExtrinsicV4;
type ExtrinsicValue = ExtrinsicValueV1 | ExtrinsicValueV2 | ExtrinsicValueV3 | ExtrinsicValueV4;
type ExtrinsicVx = ExtrinsicV4;
type ExtrinsicValue = ExtrinsicValueV4;
const VERSIONS: (keyof InterfaceTypes)[] = [
'ExtrinsicUnknown', // v0 is unknown
'ExtrinsicV1',
'ExtrinsicV2',
'ExtrinsicV3',
'ExtrinsicUnknown',
'ExtrinsicUnknown',
'ExtrinsicUnknown',
'ExtrinsicV4'
];
@@ -20,15 +20,15 @@ describe('ExtrinsicPayload', (): void => {
};
it('creates and can re-create from itself (U8a)', (): void => {
const a = new ExtrinsicPayload(registry, TEST, { version: 3 });
const b = new ExtrinsicPayload(registry, a.toU8a(), { version: 3 });
const a = new ExtrinsicPayload(registry, TEST, { version: 4 });
const b = new ExtrinsicPayload(registry, a.toU8a(), { version: 4 });
expect(a).toEqual(b);
});
it('creates and can re-create from itself (hex)', (): void => {
const a = new ExtrinsicPayload(registry, TEST, { version: 3 });
const b = new ExtrinsicPayload(registry, a.toHex(), { version: 3 });
const a = new ExtrinsicPayload(registry, TEST, { version: 4 });
const b = new ExtrinsicPayload(registry, a.toHex(), { version: 4 });
expect(a).toEqual(b);
});
@@ -36,7 +36,7 @@ describe('ExtrinsicPayload', (): void => {
it('handles toU8a(true) correctly', (): void => {
expect(
u8aToHex(
new ExtrinsicPayload(registry, TEST, { version: 3 }).toU8a(true)
new ExtrinsicPayload(registry, TEST, { version: 4 }).toU8a(true)
)
).toEqual(
// no method length prefix
@@ -47,7 +47,7 @@ describe('ExtrinsicPayload', (): void => {
it('handles toU8a(false) correctly', (): void => {
expect(
u8aToHex(
new ExtrinsicPayload(registry, TEST, { version: 3 }).toU8a()
new ExtrinsicPayload(registry, TEST, { version: 4 }).toU8a()
)
).toEqual(
// with method length prefix
@@ -1,7 +1,7 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ExtrinsicPayloadV1, ExtrinsicPayloadV2, ExtrinsicPayloadV3, ExtrinsicPayloadV4 } from '../interfaces/extrinsics';
import { ExtrinsicPayloadV4 } from '../interfaces/extrinsics';
import { Balance, Hash, Index } from '../interfaces/runtime';
import { AnyJson, BareOpts, ExtrinsicPayloadValue, IKeyringPair, InterfaceTypes, Registry } from '../types';
@@ -19,13 +19,13 @@ interface ExtrinsicPayloadOptions {
}
// all our known types that can be returned
type ExtrinsicPayloadVx = ExtrinsicPayloadV1 | ExtrinsicPayloadV2 | ExtrinsicPayloadV3 | ExtrinsicPayloadV4;
type ExtrinsicPayloadVx = ExtrinsicPayloadV4;
const VERSIONS: (keyof InterfaceTypes)[] = [
'ExtrinsicPayloadUnknown', // v0 is unknown
'ExtrinsicPayloadV1',
'ExtrinsicPayloadV2',
'ExtrinsicPayloadV3',
'ExtrinsicPayloadUnknown',
'ExtrinsicPayloadUnknown',
'ExtrinsicPayloadUnknown',
'ExtrinsicPayloadV4'
];
@@ -68,7 +68,7 @@ export default class ExtrinsicPayload extends Base<ExtrinsicPayloadVx> {
*/
public get genesisHash (): Hash {
// NOTE only v3+
return (this._raw as ExtrinsicPayloadV3).genesisHash || this.registry.createType('Hash');
return this._raw.genesisHash || this.registry.createType('Hash');
}
/**
@@ -90,7 +90,7 @@ export default class ExtrinsicPayload extends Base<ExtrinsicPayloadVx> {
*/
public get specVersion (): u32 {
// NOTE only v3+
return (this._raw as ExtrinsicPayloadV3).specVersion || this.registry.createType('u32');
return this._raw.specVersion || this.registry.createType('u32');
}
/**
@@ -98,7 +98,7 @@ export default class ExtrinsicPayload extends Base<ExtrinsicPayloadVx> {
*/
public get tip (): Compact<Balance> {
// NOTE from v2+
return (this._raw as ExtrinsicPayloadV2).tip || this.registry.createType('Compact<Balance>');
return this._raw.tip || this.registry.createType('Compact<Balance>');
}
/**
@@ -106,7 +106,7 @@ export default class ExtrinsicPayload extends Base<ExtrinsicPayloadVx> {
*/
public get transactionVersion (): u32 {
// NOTE only v4+
return (this._raw as ExtrinsicPayloadV4).transactionVersion || this.registry.createType('u32');
return this._raw.transactionVersion || this.registry.createType('u32');
}
/**
@@ -25,7 +25,7 @@ describe('SignerPayload', (): void => {
specVersion: '0x00000006',
tip: '0x00000000000000000000000000005678',
transactionVersion: '0x00000007',
version: 3
version: 4
};
it('creates a valid JSON output', (): void => {
@@ -40,7 +40,7 @@ describe('SignerPayload', (): void => {
nonce: 0x1234,
signedExtensions: ['CheckNonce'],
tip: 0x5678,
version: 3
version: 4
}).toPayload()
).toEqual({
address: '5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFabHE',
@@ -54,7 +54,7 @@ describe('SignerPayload', (): void => {
specVersion: '0x00000000',
tip: '0x00000000000000000000000000005678',
transactionVersion: '0x00000000',
version: 3
version: 4
});
});
+1 -3
View File
@@ -7,9 +7,7 @@ export const BIT_UNSIGNED = 0;
export const EMPTY_U8A = new Uint8Array();
// TODO We really want to swap this to V3, however all the test data is setup
// for V1, so this will take some time to convert... "some" time :)
export const DEFAULT_VERSION = 1;
export const DEFAULT_VERSION = 4;
export const IMMORTAL_ERA = new Uint8Array([0]);
-3
View File
@@ -8,7 +8,4 @@ export { default as GenericExtrinsicPayloadUnknown } from './ExtrinsicPayloadUnk
export { default as GenericExtrinsicUnknown } from './ExtrinsicUnknown';
export { default as GenericSignerPayload } from './SignerPayload';
export * from './v1';
export * from './v2';
export * from './v3';
export * from './v4';
@@ -1,106 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ExtrinsicSignatureV1 } from '../../interfaces/extrinsics';
import { Address, Call } from '../../interfaces/runtime';
import { ExtrinsicPayloadValue, IExtrinsicImpl, IKeyringPair, Registry, SignatureOptions } from '../../types';
import { ExtrinsicOptions } from '../types';
import { isU8a } from '@polkadot/util';
import Struct from '../../codec/Struct';
export interface ExtrinsicValueV1 {
method?: Call;
signature?: ExtrinsicSignatureV1;
}
const TRANSACTION_VERSION = 1;
/**
* @name GenericExtrinsicV1
* @description
* The first generation of compact extrinsics
*/
export default class ExtrinsicV1 extends Struct implements IExtrinsicImpl {
constructor (registry: Registry, value?: Uint8Array | ExtrinsicValueV1, { isSigned }: Partial<ExtrinsicOptions> = {}) {
super(registry, {
signature: 'ExtrinsicSignatureV1',
// eslint-disable-next-line sort-keys
method: 'Call'
}, ExtrinsicV1.decodeExtrinsic(registry, value, isSigned));
}
/** @internal */
public static decodeExtrinsic (registry: Registry, value?: Uint8Array | ExtrinsicValueV1, isSigned = false): ExtrinsicValueV1 {
if (value instanceof ExtrinsicV1) {
return value;
} else if (isU8a(value)) {
// here we decode manually since we need to pull through the version information
const signature = registry.createType('ExtrinsicSignatureV1', value, { isSigned });
const method = registry.createType('Call', value.subarray(signature.encodedLength));
return {
method,
signature
};
}
return value || {};
}
/**
* @description The length of the value when encoded as a Uint8Array
*/
public get encodedLength (): number {
return this.toU8a().length;
}
/**
* @description The [[Call]] this extrinsic wraps
*/
public get method (): Call {
return this.get('method') as Call;
}
/**
* @description The [[ExtrinsicSignatureV1]]
*/
public get signature (): ExtrinsicSignatureV1 {
return this.get('signature') as ExtrinsicSignatureV1;
}
/**
* @description The version for the signature
*/
public get version (): number {
return TRANSACTION_VERSION;
}
/**
* @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);
return this;
}
/**
* @description Sign the extrinsic with a specific keypair
*/
public sign (account: IKeyringPair, options: SignatureOptions): ExtrinsicV1 {
this.signature.sign(this.method, account, options);
return this;
}
/**
* @describe Adds a fake signature to the extrinsic
*/
public signFake (signer: Address | Uint8Array | string, options: SignatureOptions): ExtrinsicV1 {
this.signature.signFake(this.method, signer, options);
return this;
}
}
@@ -1,71 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ExtrinsicEra } from '../../interfaces/extrinsics';
import { Hash, Index } from '../../interfaces/runtime';
import { ExtrinsicPayloadValue, IKeyringPair, Registry } from '../../types';
import Compact from '../../codec/Compact';
import Struct from '../../codec/Struct';
import Bytes from '../../primitive/Bytes';
import { sign } from '../util';
/**
* @name GenericExtrinsicPayloadV1
* @description
* A signing payload for an [[Extrinsic]]. For the final encoding, it is variable length based
* on the contents included
*
* 1-8 bytes: The Transaction Compact<Index/Nonce> as provided in the transaction itself.
* 2+ bytes: The Function Descriptor as provided in the transaction itself.
* 1/2 bytes: The Transaction Era as provided in the transaction itself.
* 32 bytes: The hash of the authoring block implied by the Transaction Era and the current block.
*/
export default class ExtrinsicPayloadV1 extends Struct {
constructor (registry: Registry, value?: ExtrinsicPayloadValue | Uint8Array | string) {
super(registry, {
nonce: 'Compact<Index>',
// eslint-disable-next-line sort-keys
method: 'Bytes',
// eslint-disable-next-line sort-keys
era: 'ExtrinsicEra',
// eslint-disable-next-line sort-keys
blockHash: 'Hash'
}, value);
}
/**
* @description The block [[Hash]] the signature applies to (mortal/immortal)
*/
public get blockHash (): Hash {
return this.get('blockHash') as Hash;
}
/**
* @description The [[Bytes]] contained in the payload
*/
public get method (): Bytes {
return this.get('method') as Bytes;
}
/**
* @description The [[ExtrinsicEra]]
*/
public get era (): ExtrinsicEra {
return this.get('era') as ExtrinsicEra;
}
/**
* @description The [[Index]]
*/
public get nonce (): Compact<Index> {
return this.get('nonce') as Compact<Index>;
}
/**
* @description Sign the payload with the keypair
*/
public sign (signerPair: IKeyringPair): Uint8Array {
return sign(this.registry, signerPair, this.toU8a({ method: true }));
}
}
@@ -1,169 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ExtrinsicEra, Signature } from '../../interfaces/extrinsics';
import { Address, Balance, Call, Index } from '../../interfaces/runtime';
import { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, Registry, SignatureOptions } from '../../types';
import { ExtrinsicSignatureOptions } from '../types';
import Compact from '../../codec/Compact';
import Struct from '../../codec/Struct';
import { EMPTY_U8A, IMMORTAL_ERA } from '../constants';
import ExtrinsicPayloadV1 from './ExtrinsicPayload';
/**
* @name GenericExtrinsicSignatureV1
* @description
* A container for the [[Signature]] associated with a specific [[Extrinsic]]
*/
export default class ExtrinsicSignatureV1 extends Struct implements IExtrinsicSignature {
// Signature Information.
// 1/3/5/9/33 bytes: The signing account identity, in Address format
// 64 bytes: The sr25519/ed25519 signature of the Signing Payload
// 1-8 bytes: The Compact<Nonce> of the signing account
// 1/2 bytes: The Transaction Era
constructor (registry: Registry, value?: ExtrinsicSignatureV1 | Uint8Array, { isSigned }: ExtrinsicSignatureOptions = {}) {
super(registry, {
signer: 'Address',
// eslint-disable-next-line sort-keys
signature: 'Signature',
// eslint-disable-next-line sort-keys
nonce: 'Compact<Index>',
// eslint-disable-next-line sort-keys
era: 'ExtrinsicEra'
}, ExtrinsicSignatureV1.decodeExtrinsicSignature(value, isSigned));
}
/** @internal */
public static decodeExtrinsicSignature (value: ExtrinsicSignatureV1 | Uint8Array | undefined, isSigned = false): ExtrinsicSignatureV1 | Uint8Array {
if (!value) {
return EMPTY_U8A;
} else if (value instanceof ExtrinsicSignatureV1) {
return value;
}
return isSigned
? value
: EMPTY_U8A;
}
/**
* @description The length of the value when encoded as a Uint8Array
*/
public get encodedLength (): number {
return this.isSigned
? super.encodedLength
: 0;
}
/**
* @description `true` if the signature is valid
*/
public get isSigned (): boolean {
return !this.signature.isEmpty;
}
/**
* @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 actual [[Signature]] hash
*/
public get signature (): Signature {
return this.get('signature') as Signature;
}
/**
* @description The [[Address]] that signed
*/
public get signer (): Address {
return this.get('signer') as Address;
}
/**
* @description Forwards compat
*/
public get tip (): Compact<Balance> {
return this.registry.createType('Compact<Balance>', 0);
}
private _injectSignature (signer: Address, signature: Signature, { era, nonce }: ExtrinsicPayloadV1): IExtrinsicSignature {
this.set('era', era);
this.set('nonce', nonce);
this.set('signer', signer);
this.set('signature', signature);
return this;
}
/**
* @description Adds a raw signature
*/
public addSignature (signer: Address | Uint8Array | string, signature: Uint8Array | string, payload: ExtrinsicPayloadValue | Uint8Array | string): IExtrinsicSignature {
return this._injectSignature(
this.registry.createType('Address', signer),
this.registry.createType('Signature', signature),
new ExtrinsicPayloadV1(this.registry, payload)
);
}
/**
* @description Creates a payload from the supplied options
*/
public createPayload (method: Call, { blockHash, era, genesisHash, nonce }: SignatureOptions): ExtrinsicPayloadV1 {
return new ExtrinsicPayloadV1(this.registry, {
blockHash,
era: era || IMMORTAL_ERA,
genesisHash,
method: method.toHex(),
nonce,
// unused for v1, added for compat
specVersion: 0,
tip: 0,
transactionVersion: 0
});
}
/**
* @description Generate a payload and applies the signature from a keypair
*/
public sign (method: Call, account: IKeyringPair, options: SignatureOptions): IExtrinsicSignature {
const signer = this.registry.createType('Address', account.addressRaw);
const payload = this.createPayload(method, options);
const signature = this.registry.createType('Signature', payload.sign(account));
return this._injectSignature(signer, signature, payload);
}
/**
* @description Generate a payload and applies a fake signature
*/
public signFake (method: Call, address: Address | Uint8Array | string, options: SignatureOptions): IExtrinsicSignature {
const signer = this.registry.createType('Address', address);
const payload = this.createPayload(method, options);
const signature = this.registry.createType('Signature', new Uint8Array(64).fill(0x42));
return this._injectSignature(signer, signature, payload);
}
/**
* @description Encodes the value as a Uint8Array as per the SCALE specifications
* @param isBare true when the value has none of the type-specific prefixes (internal)
*/
public toU8a (isBare?: boolean): Uint8Array {
return this.isSigned
? super.toU8a(isBare)
: EMPTY_U8A;
}
}
-6
View File
@@ -1,6 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as GenericExtrinsicV1 } from './Extrinsic';
export { default as GenericExtrinsicPayloadV1 } from './ExtrinsicPayload';
export { default as GenericExtrinsicSignatureV1 } from './ExtrinsicSignature';
@@ -1,78 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import BN from 'bn.js';
import Decorated from '@polkadot/metadata/Decorated';
import Metadata from '@polkadot/metadata/Metadata';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import testingPairs from '@polkadot/keyring/testingPairs';
import { TypeRegistry } from '../../create';
import Extrinsic from './Extrinsic';
const registry = new TypeRegistry();
const metadata = new Metadata(registry, rpcMetadata);
const decorated = new Decorated(registry, metadata);
const keyring = testingPairs({ type: 'ed25519' }, false);
registry.setMetadata(metadata);
describe('ExtrinsicV2', (): void => {
it('constructs a sane Uint8Array (default)', (): void => {
expect(
new Extrinsic(registry).toU8a()
).toEqual(new Uint8Array([
0, 0, // index
0, 0, 0, 0 // fillBlock Perbill
]));
});
it('creates a unsigned extrinsic', (): void => {
expect(
new Extrinsic(
registry,
decorated.tx.balances.transfer(keyring.bob.publicKey, 6969n)
).toHex()
).toEqual(
'0x' +
'0600' + // balance.transfer
'ff' +
'd7568e5f0a7eda67a82691ff379ac4bba4f9c9b859fe779b5d46363b61ad2db9' +
'e56c'
);
});
it('creates a signed extrinsic', (): void => {
expect(
new Extrinsic(
registry,
decorated.tx.balances.transfer(keyring.bob.publicKey, 6969n)
).sign(keyring.alice, {
blockHash: '0xec7afaf1cca720ce88c1d1b689d81f0583cc15a97d621cf046dd9abf605ef22f',
genesisHash: '0xdcd1346701ca8396496e52aa2785b1748deb6db09551b72159dcb3e08991025b',
nonce: 1,
runtimeVersion: {
apis: [],
authoringVersion: new BN(123),
implName: 'test',
implVersion: new BN(123),
specName: 'test',
specVersion: new BN(123),
transactionVersion: new BN(123)
},
tip: 2
}).toHex()
).toEqual(
'0x' +
'ff' +
'd172a74cda4c865912c32ba0a80a57ae69abae410e5ccb59dee84e2f4432db4f' +
'4f47f2d47095239adcb8b725c2c950348c0f65a5019b91e0946636c6c2424cdc' +
'6c0cece073e18b40ba13d2dd3afcc0daa0f223fa6a8f59d1e025a2dde1d1200a' +
'000408' + // era. nonce, tip
'0600' +
'ff' +
'd7568e5f0a7eda67a82691ff379ac4bba4f9c9b859fe779b5d46363b61ad2db9' +
'e56c'
);
});
});
@@ -1,108 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ExtrinsicSignatureV2 } from '../../interfaces/extrinsics';
import { Address, Call } from '../../interfaces/runtime';
import { ExtrinsicPayloadValue, IExtrinsicImpl, IKeyringPair, Registry, SignatureOptions } from '../../types';
import { ExtrinsicOptions } from '../types';
import { isU8a } from '@polkadot/util';
import Struct from '../../codec/Struct';
const TRANSACTION_VERSION = 2;
export interface ExtrinsicValueV2 {
method?: Call;
signature?: ExtrinsicSignatureV2;
}
/**
* @name GenericExtrinsicV2
* @description
* The second generation of compact extrinsics
*/
export default class ExtrinsicV2 extends Struct implements IExtrinsicImpl {
constructor (registry: Registry, value?: Uint8Array | ExtrinsicValueV2 | Call, { isSigned }: Partial<ExtrinsicOptions> = {}) {
super(registry, {
signature: 'ExtrinsicSignatureV2',
// eslint-disable-next-line sort-keys
method: 'Call'
}, ExtrinsicV2.decodeExtrinsic(registry, value, isSigned));
}
/** @internal */
public static decodeExtrinsic (registry: Registry, value?: Call | Uint8Array | ExtrinsicValueV2, isSigned = false): ExtrinsicValueV2 {
if (value instanceof ExtrinsicV2) {
return value;
} else if (value instanceof registry.createClass('Call')) {
return { method: value };
} else if (isU8a(value)) {
// here we decode manually since we need to pull through the version information
const signature = registry.createType('ExtrinsicSignatureV2', value, { isSigned });
const method = registry.createType('Call', value.subarray(signature.encodedLength));
return {
method,
signature
};
}
return value || {};
}
/**
* @description The length of the value when encoded as a Uint8Array
*/
public get encodedLength (): number {
return this.toU8a().length;
}
/**
* @description The [[Call]] this extrinsic wraps
*/
public get method (): Call {
return this.get('method') as Call;
}
/**
* @description The [[ExtrinsicSignatureV2]]
*/
public get signature (): ExtrinsicSignatureV2 {
return this.get('signature') as ExtrinsicSignatureV2;
}
/**
* @description The version for the signature
*/
public get version (): number {
return TRANSACTION_VERSION;
}
/**
* @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);
return this;
}
/**
* @description Sign the extrinsic with a specific keypair
*/
public sign (account: IKeyringPair, options: SignatureOptions): ExtrinsicV2 {
this.signature.sign(this.method, account, options);
return this;
}
/**
* @describe Adds a fake signature to the extrinsic
*/
public signFake (signer: Address | Uint8Array | string, options: SignatureOptions): ExtrinsicV2 {
this.signature.signFake(this.method, signer, options);
return this;
}
}
@@ -1,73 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ExtrinsicEra } from '../../interfaces/extrinsics';
import { Balance, Hash, Index } from '../../interfaces/runtime';
import { ExtrinsicPayloadValue, IKeyringPair, Registry } from '../../types';
import Compact from '../../codec/Compact';
import Struct from '../../codec/Struct';
import Bytes from '../../primitive/Bytes';
import { sign } from '../util';
/**
* @name GenericExtrinsicPayloadV2
* @description
* A signing payload for an [[Extrinsic]]. For the final encoding, it is variable length based
* on the contents included
*/
export default class ExtrinsicPayloadV2 extends Struct {
constructor (registry: Registry, value?: ExtrinsicPayloadValue | Uint8Array | string) {
super(registry, {
method: 'Bytes',
// eslint-disable-next-line sort-keys
era: 'ExtrinsicEra',
nonce: 'Compact<Index>',
tip: 'Compact<Balance>',
// eslint-disable-next-line sort-keys
blockHash: 'Hash'
}, value);
}
/**
* @description The block [[Hash]] the signature applies to (mortal/immortal)
*/
public get blockHash (): Hash {
return this.get('blockHash') as Hash;
}
/**
* @description The [[ExtrinsicEra]]
*/
public get era (): ExtrinsicEra {
return this.get('era') as ExtrinsicEra;
}
/**
* @description The [[Bytes]] contained in the payload
*/
public get method (): Bytes {
return this.get('method') as Bytes;
}
/**
* @description The [[Index]]
*/
public get nonce (): Compact<Index> {
return this.get('nonce') as Compact<Index>;
}
/**
* @description The tip [[Balance]]
*/
public get tip (): Compact<Balance> {
return this.get('tip') as Compact<Balance>;
}
/**
* @description Sign the payload with the keypair
*/
public sign (signerPair: IKeyringPair): Uint8Array {
return sign(this.registry, signerPair, this.toU8a({ method: true }));
}
}
@@ -1,29 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { TypeRegistry } from '../../create';
import ExtrinsicSignature from './ExtrinsicSignature';
describe('ExtrinsicSignatureV2', (): void => {
const registry = new TypeRegistry();
it('encodes to a sane Uint8Array', (): void => {
const u8a = new Uint8Array([
// signer as an AccountIndex
0x09,
// signature
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
// extra stuff
0x00, // immortal,
0x04, // nonce, compact
0x08 // tip, compact
]);
expect(
new ExtrinsicSignature(registry, u8a, { isSigned: true }).toU8a()
).toEqual(u8a);
});
});
@@ -1,165 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ExtrinsicEra, Signature } from '../../interfaces/extrinsics';
import { Address, Balance, Call, Index } from '../../interfaces/runtime';
import { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, Registry, SignatureOptions } from '../../types';
import { ExtrinsicSignatureOptions } from '../types';
import Compact from '../../codec/Compact';
import Struct from '../../codec/Struct';
import { EMPTY_U8A, IMMORTAL_ERA } from '../constants';
import ExtrinsicPayloadV2 from './ExtrinsicPayload';
/**
* @name GenericExtrinsicSignatureV2
* @description
* A container for the [[Signature]] associated with a specific [[Extrinsic]]
*/
export default class ExtrinsicSignatureV2 extends Struct implements IExtrinsicSignature {
constructor (registry: Registry, value: ExtrinsicSignatureV2 | Uint8Array | undefined, { isSigned }: ExtrinsicSignatureOptions = {}) {
super(registry, {
signer: 'Address',
// eslint-disable-next-line sort-keys
signature: 'Signature',
// eslint-disable-next-line sort-keys
era: 'ExtrinsicEra',
nonce: 'Compact<Index>',
tip: 'Compact<Balance>'
}, ExtrinsicSignatureV2.decodeExtrinsicSignature(value, isSigned));
}
/** @internal */
public static decodeExtrinsicSignature (value: ExtrinsicSignatureV2 | Uint8Array | undefined, isSigned = false): ExtrinsicSignatureV2 | Uint8Array {
if (!value) {
return EMPTY_U8A;
} else if (value instanceof ExtrinsicSignatureV2) {
return value;
}
return isSigned
? value
: EMPTY_U8A;
}
/**
* @description The length of the value when encoded as a Uint8Array
*/
public get encodedLength (): number {
return this.isSigned
? super.encodedLength
: 0;
}
/**
* @description `true` if the signature is valid
*/
public get isSigned (): boolean {
return !this.signature.isEmpty;
}
/**
* @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 actual [[Signature]] hash
*/
public get signature (): Signature {
return this.get('signature') as Signature;
}
/**
* @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>;
}
protected _injectSignature (signer: Address, signature: Signature, { era, nonce, tip }: ExtrinsicPayloadV2): IExtrinsicSignature {
this.set('era', era);
this.set('nonce', nonce);
this.set('signer', signer);
this.set('signature', signature);
this.set('tip', tip);
return this;
}
/**
* @description Adds a raw signature
*/
public addSignature (signer: Address | Uint8Array | string, signature: Uint8Array | string, payload: ExtrinsicPayloadValue | Uint8Array | string): IExtrinsicSignature {
return this._injectSignature(
this.registry.createType('Address', signer),
this.registry.createType('Signature', signature),
new ExtrinsicPayloadV2(this.registry, payload)
);
}
/**
* @description Creates a payload from the supplied options
*/
public createPayload (method: Call, { blockHash, era, genesisHash, nonce, tip }: SignatureOptions): ExtrinsicPayloadV2 {
return new ExtrinsicPayloadV2(this.registry, {
blockHash,
era: era || IMMORTAL_ERA,
genesisHash,
method: method.toHex(),
nonce,
// unused for v2
specVersion: 0,
tip: tip || 0,
transactionVersion: 0
});
}
/**
* @description Generate a payload and applies the signature from a keypair
*/
public sign (method: Call, account: IKeyringPair, options: SignatureOptions): IExtrinsicSignature {
const signer = this.registry.createType('Address', account.addressRaw);
const payload = this.createPayload(method, options);
const signature = this.registry.createType('Signature', payload.sign(account));
return this._injectSignature(signer, signature, payload);
}
/**
* @description Generate a payload and applies a fake signature
*/
public signFake (method: Call, address: Address | Uint8Array | string, options: SignatureOptions): IExtrinsicSignature {
const signer = this.registry.createType('Address', address);
const payload = this.createPayload(method, options);
const signature = this.registry.createType('Signature', new Uint8Array(64).fill(0x42));
return this._injectSignature(signer, signature, payload);
}
/**
* @description Encodes the value as a Uint8Array as per the SCALE specifications
* @param isBare true when the value has none of the type-specific prefixes (internal)
*/
public toU8a (isBare?: boolean): Uint8Array {
return this.isSigned
? super.toU8a(isBare)
: EMPTY_U8A;
}
}
-6
View File
@@ -1,6 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as GenericExtrinsicV2 } from './Extrinsic';
export { default as GenericExtrinsicPayloadV2 } from './ExtrinsicPayload';
export { default as GenericExtrinsicSignatureV2 } from './ExtrinsicSignature';
@@ -1,78 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import BN from 'bn.js';
import Decorated from '@polkadot/metadata/Decorated';
import Metadata from '@polkadot/metadata/Metadata';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import testingPairs from '@polkadot/keyring/testingPairs';
import { TypeRegistry } from '../../create';
import Extrinsic from './Extrinsic';
const registry = new TypeRegistry();
const metadata = new Metadata(registry, rpcMetadata);
const decorated = new Decorated(registry, metadata);
const keyring = testingPairs({ type: 'ed25519' }, false);
registry.setMetadata(metadata);
describe('ExtrinsicV3', (): void => {
it('constructs a sane Uint8Array (default)', (): void => {
expect(
new Extrinsic(registry).toU8a()
).toEqual(new Uint8Array([
0, 0, // index
0, 0, 0, 0 // fillBlock Perbill
]));
});
it('creates a unsigned extrinsic', (): void => {
expect(
new Extrinsic(
registry,
decorated.tx.balances.transfer(keyring.bob.publicKey, 6969n)
).toHex()
).toEqual(
'0x' +
'0600' + // balance.transfer
'ff' +
'd7568e5f0a7eda67a82691ff379ac4bba4f9c9b859fe779b5d46363b61ad2db9' +
'e56c'
);
});
it('creates a signed extrinsic', (): void => {
expect(
new Extrinsic(
registry,
decorated.tx.balances.transfer(keyring.bob.publicKey, 6969n)
).sign(keyring.alice, {
blockHash: '0xec7afaf1cca720ce88c1d1b689d81f0583cc15a97d621cf046dd9abf605ef22f',
genesisHash: '0xdcd1346701ca8396496e52aa2785b1748deb6db09551b72159dcb3e08991025b',
nonce: 1,
runtimeVersion: {
apis: [],
authoringVersion: new BN(123),
implName: 'test',
implVersion: new BN(123),
specName: 'test',
specVersion: new BN(123),
transactionVersion: new BN(123)
},
tip: 2
}).toHex()
).toEqual(
'0x' +
'ff' +
'd172a74cda4c865912c32ba0a80a57ae69abae410e5ccb59dee84e2f4432db4f' +
'b8065808da3d11ddb4167afb156eafb51e8104ba792589bb443653a7fab82b90' +
'c6530e838df06bfc8befcbbcfca7e219350cff865439b815b10b8e64ae1e9b01' +
'000408' + // era. nonce, tip
'0600' +
'ff' +
'd7568e5f0a7eda67a82691ff379ac4bba4f9c9b859fe779b5d46363b61ad2db9' +
'e56c'
);
});
});
@@ -1,108 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ExtrinsicSignatureV3 } from '../../interfaces/extrinsics';
import { Address, Call } from '../../interfaces/runtime';
import { ExtrinsicPayloadValue, IExtrinsicImpl, IKeyringPair, Registry, SignatureOptions } from '../../types';
import { ExtrinsicOptions } from '../types';
import { isU8a } from '@polkadot/util';
import Struct from '../../codec/Struct';
const TRANSACTION_VERSION = 3;
export interface ExtrinsicValueV3 {
method?: Call;
signature?: ExtrinsicSignatureV3;
}
/**
* @name GenericExtrinsicV3
* @description
* The third generation of compact extrinsics
*/
export default class ExtrinsicV3 extends Struct implements IExtrinsicImpl {
constructor (registry: Registry, value?: Uint8Array | ExtrinsicValueV3 | Call, { isSigned }: Partial<ExtrinsicOptions> = {}) {
super(registry, {
signature: 'ExtrinsicSignatureV3',
// eslint-disable-next-line sort-keys
method: 'Call'
}, ExtrinsicV3.decodeExtrinsic(registry, value, isSigned));
}
/** @internal */
public static decodeExtrinsic (registry: Registry, value?: Call | Uint8Array | ExtrinsicValueV3, isSigned = false): ExtrinsicValueV3 {
if (value instanceof ExtrinsicV3) {
return value;
} else if (value instanceof registry.createClass('Call')) {
return { method: value };
} else if (isU8a(value)) {
// here we decode manually since we need to pull through the version information
const signature = registry.createType('ExtrinsicSignatureV3', value, { isSigned });
const method = registry.createType('Call', value.subarray(signature.encodedLength));
return {
method,
signature
};
}
return value || {};
}
/**
* @description The length of the value when encoded as a Uint8Array
*/
public get encodedLength (): number {
return this.toU8a().length;
}
/**
* @description The [[Call]] this extrinsic wraps
*/
public get method (): Call {
return this.get('method') as Call;
}
/**
* @description The [[ExtrinsicSignatureV3]]
*/
public get signature (): ExtrinsicSignatureV3 {
return this.get('signature') as ExtrinsicSignatureV3;
}
/**
* @description The version for the signature
*/
public get version (): number {
return TRANSACTION_VERSION;
}
/**
* @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);
return this;
}
/**
* @description Sign the extrinsic with a specific keypair
*/
public sign (account: IKeyringPair, options: SignatureOptions): ExtrinsicV3 {
this.signature.sign(this.method, account, options);
return this;
}
/**
* @describe Adds a fake signature to the extrinsic
*/
public signFake (signer: Address | Uint8Array | string, options: SignatureOptions): ExtrinsicV3 {
this.signature.signFake(this.method, signer, options);
return this;
}
}
@@ -1,92 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ExtrinsicEra } from '../../interfaces/extrinsics';
import { Balance, Hash, Index } from '../../interfaces/runtime';
import { ExtrinsicPayloadValue, IKeyringPair, Registry } from '../../types';
import Compact from '../../codec/Compact';
import Struct from '../../codec/Struct';
import Bytes from '../../primitive/Bytes';
import u32 from '../../primitive/U32';
import { sign } from '../util';
/**
* @name GenericExtrinsicPayloadV3
* @description
* A signing payload for an [[Extrinsic]]. For the final encoding, it is variable length based
* on the contents included
*/
export default class ExtrinsicPayloadV3 extends Struct {
constructor (registry: Registry, value?: ExtrinsicPayloadValue | Uint8Array | string) {
super(registry, {
method: 'Bytes',
// eslint-disable-next-line sort-keys
era: 'ExtrinsicEra',
nonce: 'Compact<Index>',
tip: 'Compact<Balance>',
// eslint-disable-next-line sort-keys
specVersion: 'u32',
// eslint-disable-next-line sort-keys
genesisHash: 'Hash',
// eslint-disable-next-line sort-keys
blockHash: 'Hash'
}, value);
}
/**
* @description The block [[Hash]] the signature applies to (mortal/immortal)
*/
public get blockHash (): Hash {
return this.get('blockHash') as Hash;
}
/**
* @description The [[ExtrinsicEra]]
*/
public get era (): ExtrinsicEra {
return this.get('era') as ExtrinsicEra;
}
/**
* @description The genesis [[Hash]] the signature applies to (mortal/immortal)
*/
public get genesisHash (): Hash {
return this.get('genesisHash') as Hash;
}
/**
* @description The [[Bytes]] contained in the payload
*/
public get method (): Bytes {
return this.get('method') as Bytes;
}
/**
* @description The [[Index]]
*/
public get nonce (): Compact<Index> {
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]]
*/
public get tip (): Compact<Balance> {
return this.get('tip') as Compact<Balance>;
}
/**
* @description Sign the payload with the keypair
*/
public sign (signerPair: IKeyringPair): Uint8Array {
return sign(this.registry, signerPair, this.toU8a({ method: true }));
}
}
@@ -1,29 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { TypeRegistry } from '../../create';
import ExtrinsicSignature from './ExtrinsicSignature';
describe('ExtrinsicSignatureV3', (): void => {
const registry = new TypeRegistry();
it('encodes to a sane Uint8Array', (): void => {
const u8a = new Uint8Array([
// signer as an AccountIndex
0x09,
// signature
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
// extra stuff
0x00, // immortal,
0x04, // nonce, compact
0x08 // tip, compact
]);
expect(
new ExtrinsicSignature(registry, u8a, { isSigned: true }).toU8a()
).toEqual(u8a);
});
});
@@ -1,65 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { Address, Call } from '../../interfaces/runtime';
import { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, SignatureOptions } from '../../types';
import { IMMORTAL_ERA } from '../constants';
import ExtrinsicSignatureV2 from '../v2/ExtrinsicSignature';
import ExtrinsicPayloadV3 from './ExtrinsicPayload';
/**
* @name GenericExtrinsicSignatureV3
* @description
* A container for the [[Signature]] associated with a specific [[Extrinsic]]
*/
export default class ExtrinsicSignatureV3 extends ExtrinsicSignatureV2 {
/**
* @description Adds a raw signature
*/
public addSignature (signer: Address | Uint8Array | string, signature: Uint8Array | string, payload: ExtrinsicPayloadValue | Uint8Array | string): IExtrinsicSignature {
return this._injectSignature(
this.registry.createType('Address', signer),
this.registry.createType('Signature', signature),
new ExtrinsicPayloadV3(this.registry, payload)
);
}
/**
* @description Creates a payload from the supplied options
*/
public createPayload (method: Call, { blockHash, era, genesisHash, nonce, runtimeVersion: { specVersion }, tip }: SignatureOptions): ExtrinsicPayloadV3 {
return new ExtrinsicPayloadV3(this.registry, {
blockHash,
era: era || IMMORTAL_ERA,
genesisHash,
method: method.toHex(),
nonce,
specVersion,
tip: tip || 0,
transactionVersion: 0
});
}
/**
* @description Generate a payload and applies the signature from a keypair
*/
public sign (method: Call, account: IKeyringPair, options: SignatureOptions): IExtrinsicSignature {
const signer = this.registry.createType('Address', account.addressRaw);
const payload = this.createPayload(method, options);
const signature = this.registry.createType('Signature', payload.sign(account));
return this._injectSignature(signer, signature, payload);
}
/**
* @description Generate a payload and applies a fake signature
*/
public signFake (method: Call, address: Address | Uint8Array | string, options: SignatureOptions): IExtrinsicSignature {
const signer = this.registry.createType('Address', address);
const payload = this.createPayload(method, options);
const signature = this.registry.createType('Signature', new Uint8Array(64).fill(0x42));
return this._injectSignature(signer, signature, payload);
}
}
-6
View File
@@ -1,6 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as GenericExtrinsicV3 } from './Extrinsic';
export { default as GenericExtrinsicPayloadV3 } from './ExtrinsicPayload';
export { default as GenericExtrinsicSignatureV3 } from './ExtrinsicSignature';
@@ -12,15 +12,6 @@ export default {
Extrinsic: 'GenericExtrinsic',
ExtrinsicEra: 'GenericExtrinsicEra',
ExtrinsicPayload: 'GenericExtrinsicPayload',
ExtrinsicV1: 'GenericExtrinsicV1',
ExtrinsicPayloadV1: 'GenericExtrinsicPayloadV1',
ExtrinsicSignatureV1: 'GenericExtrinsicSignatureV1',
ExtrinsicV2: 'GenericExtrinsicV2',
ExtrinsicPayloadV2: 'GenericExtrinsicPayloadV2',
ExtrinsicSignatureV2: 'GenericExtrinsicSignatureV2',
ExtrinsicV3: 'GenericExtrinsicV3',
ExtrinsicPayloadV3: 'GenericExtrinsicPayloadV3',
ExtrinsicSignatureV3: 'GenericExtrinsicSignatureV3',
ExtrinsicV4: 'GenericExtrinsicV4',
ExtrinsicPayloadV4: 'GenericExtrinsicPayloadV4',
ExtrinsicSignatureV4: 'GenericExtrinsicSignatureV4',
@@ -2,7 +2,7 @@
/* eslint-disable */
import { Enum, U8aFixed } from '@polkadot/types/codec';
import { GenericExtrinsic, GenericExtrinsicEra, GenericExtrinsicPayload, GenericExtrinsicPayloadUnknown, GenericExtrinsicPayloadV1, GenericExtrinsicPayloadV2, GenericExtrinsicPayloadV3, GenericExtrinsicPayloadV4, GenericExtrinsicSignatureV1, GenericExtrinsicSignatureV2, GenericExtrinsicSignatureV3, GenericExtrinsicSignatureV4, GenericExtrinsicUnknown, GenericExtrinsicV1, GenericExtrinsicV2, GenericExtrinsicV3, GenericExtrinsicV4, GenericImmortalEra, GenericMortalEra, GenericSignerPayload } from '@polkadot/types/extrinsic';
import { GenericExtrinsic, GenericExtrinsicEra, GenericExtrinsicPayload, GenericExtrinsicPayloadUnknown, GenericExtrinsicPayloadV4, GenericExtrinsicSignatureV4, GenericExtrinsicUnknown, GenericExtrinsicV4, GenericImmortalEra, GenericMortalEra, GenericSignerPayload } from '@polkadot/types/extrinsic';
import { H512 } from '@polkadot/types/interfaces/runtime';
/** @name EcdsaSignature */
@@ -23,42 +23,15 @@ export interface ExtrinsicPayload extends GenericExtrinsicPayload {}
/** @name ExtrinsicPayloadUnknown */
export interface ExtrinsicPayloadUnknown extends GenericExtrinsicPayloadUnknown {}
/** @name ExtrinsicPayloadV1 */
export interface ExtrinsicPayloadV1 extends GenericExtrinsicPayloadV1 {}
/** @name ExtrinsicPayloadV2 */
export interface ExtrinsicPayloadV2 extends GenericExtrinsicPayloadV2 {}
/** @name ExtrinsicPayloadV3 */
export interface ExtrinsicPayloadV3 extends GenericExtrinsicPayloadV3 {}
/** @name ExtrinsicPayloadV4 */
export interface ExtrinsicPayloadV4 extends GenericExtrinsicPayloadV4 {}
/** @name ExtrinsicSignatureV1 */
export interface ExtrinsicSignatureV1 extends GenericExtrinsicSignatureV1 {}
/** @name ExtrinsicSignatureV2 */
export interface ExtrinsicSignatureV2 extends GenericExtrinsicSignatureV2 {}
/** @name ExtrinsicSignatureV3 */
export interface ExtrinsicSignatureV3 extends GenericExtrinsicSignatureV3 {}
/** @name ExtrinsicSignatureV4 */
export interface ExtrinsicSignatureV4 extends GenericExtrinsicSignatureV4 {}
/** @name ExtrinsicUnknown */
export interface ExtrinsicUnknown extends GenericExtrinsicUnknown {}
/** @name ExtrinsicV1 */
export interface ExtrinsicV1 extends GenericExtrinsicV1 {}
/** @name ExtrinsicV2 */
export interface ExtrinsicV2 extends GenericExtrinsicV2 {}
/** @name ExtrinsicV3 */
export interface ExtrinsicV3 extends GenericExtrinsicV3 {}
/** @name ExtrinsicV4 */
export interface ExtrinsicV4 extends GenericExtrinsicV4 {}
@@ -1,62 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import Metadata from '@polkadot/metadata/Metadata';
import metadataStatic from '@polkadot/metadata/Metadata/static';
import { TypeRegistry } from '../../create';
import immortalTxs from '../../json/SignedBlock.004.immortal.json';
import mortalTxs from '../../json/SignedBlock.004.mortal.json';
import knownMehods from '../../json/SignedBlock.005.json';
const registry = new TypeRegistry();
const metadata = new Metadata(registry, metadataStatic);
registry.setMetadata(metadata);
describe('SignedBlock', (): void => {
it('decodes a full block', (): void => {
const s = registry.createType('SignedBlock', knownMehods.result);
expect(
s.block.header.stateRoot.toString()
).toEqual('0xc7803b39c1b30a87566ec9d95890db76cf2eee7034faee4c8a0997759e7bcb7e');
expect(s.block.header.digest.logs.length).toBe(2);
expect(s.block.header.digest.logs[0].type).toBe('PreRuntime');
expect(s.block.header.digest.logs[0].value.toHuman()).toEqual([
'BABE',
'0xa5cb8138000000000000000000000000549baa911a66f7bab6318a6930380bfd015713f77b6775d2df467d37dadd224dda0a80881cfbddc580d45b3b7358f28e4990d950df4508590543d39d635b3402822279397c1d55449b201710c706ce5de3fd3cb2e269bea6ba89c71e4446fd06'
]);
});
// Test to replicate https://github.com/polkadot-js/api/issues/1212
it('decodes to known extrinsics', (): void => {
const s = registry.createType('SignedBlock', knownMehods.result);
const indexes = s.block.extrinsics.map(({ method: { callIndex } }): Uint8Array => callIndex);
expect(indexes).toEqual([
new Uint8Array([0x03, 0x00]),
new Uint8Array([0x0c, 0x00])
]);
});
describe('eras', (): void => {
it('can decode immortals', (): void => {
const s = registry.createType('SignedBlock', immortalTxs.result);
const immortalTx = s.block.extrinsics[0];
expect(immortalTx.method.methodName).toEqual('transfer');
expect(immortalTx.method.sectionName).toEqual('balances');
});
it('can decode mortals', (): void => {
const s = registry.createType('SignedBlock', mortalTxs.result);
const mortalTx = s.block.extrinsics[0];
expect(mortalTx.method.methodName).toEqual('transfer');
expect(mortalTx.method.sectionName).toEqual('balances');
});
});
});