Pass Extrinsic version, allow ExtrinsicUnknown override (#1348)
* Pass Extrinsic version, allow ExtrinsicUnknown override * ExtrinsicUnknown should throw
This commit is contained in:
@@ -16,7 +16,11 @@ import * as definitions from './interfaces/definitions';
|
||||
// specifically for the types that _should_ throw in the constrtuctor, i.e
|
||||
// `usize` is not allowed (runtime incompat) and `origin` is not passed through
|
||||
// to any calls. All other types _must_ pass and allow for empty defaults
|
||||
const UNCONSTRUCTABLE = ['genericorigin', 'origin', 'usize'];
|
||||
const UNCONSTRUCTABLE = [
|
||||
'ExtrinsicUnknown', 'GenericExtrinsicUnknown',
|
||||
'GenericOrigin', 'Origin',
|
||||
'usize'
|
||||
].map((v): string => v.toLowerCase());
|
||||
|
||||
function testTypes (type: string, typeNames: string[]): void {
|
||||
describe(type, (): void => {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import { Compact, Option, Vec } from './codec';
|
||||
import { Bytes, Data, Fixed64, H160, H256, H512, Null, StorageData, StorageHasher, StorageKey, Text, Type, bool, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from './primitive';
|
||||
import { AccountId, AccountIdOf, AccountIndex, Address, AssetId, Balance, BalanceOf, Block, BlockNumber, Call, Consensus, ConsensusEngineId, Digest, DigestItem, Ed25519Signature, Extrinsic, ExtrinsicEra, ExtrinsicPayload, Hash, Header, ImmortalEra, Index, Justification, KeyTypeId, KeyValue, LockIdentifier, Moment, MortalEra, Origin, Perbill, Permill, Phantom, PhantomData, PreRuntime, Seal, SealV0, Signature, SignedBlock, Sr25519Signature, ValidatorId, Weight, WeightMultiplier } from './interfaces/runtime';
|
||||
import { AccountId, AccountIdOf, AccountIndex, Address, AssetId, Balance, BalanceOf, Block, BlockNumber, Call, Consensus, ConsensusEngineId, Digest, DigestItem, Ed25519Signature, Extrinsic, ExtrinsicEra, ExtrinsicPayload, ExtrinsicUnknown, Hash, Header, ImmortalEra, Index, Justification, KeyTypeId, KeyValue, LockIdentifier, Moment, MortalEra, Origin, Perbill, Permill, Phantom, PhantomData, PreRuntime, Seal, SealV0, Signature, SignedBlock, Sr25519Signature, ValidatorId, Weight, WeightMultiplier } from './interfaces/runtime';
|
||||
import { InclusionHeight, Uncle, UncleEntryItem } from './interfaces/authorship';
|
||||
import { RawAuraPreDigest } from './interfaces/aura';
|
||||
import { BabeAuthorityWeight, BabeBlockWeight, BabeWeight, RawBabePreDigest, RawBabePreDigestPrimary, RawBabePreDigestSecondary, SlotNumber } from './interfaces/babe';
|
||||
@@ -167,6 +167,9 @@ export interface InterfaceRegistry {
|
||||
ExtrinsicPayload: ExtrinsicPayload;
|
||||
'Option<ExtrinsicPayload>': Option<ExtrinsicPayload>;
|
||||
'Vec<ExtrinsicPayload>': Vec<ExtrinsicPayload>;
|
||||
ExtrinsicUnknown: ExtrinsicUnknown;
|
||||
'Option<ExtrinsicUnknown>': Option<ExtrinsicUnknown>;
|
||||
'Vec<ExtrinsicUnknown>': Vec<ExtrinsicUnknown>;
|
||||
Hash: Hash;
|
||||
'Option<Hash>': Option<Hash>;
|
||||
'Vec<Hash>': Vec<Hash>;
|
||||
|
||||
@@ -20,6 +20,7 @@ export default {
|
||||
Extrinsic: 'GenericExtrinsic',
|
||||
ExtrinsicEra: 'GenericExtrinsicEra',
|
||||
ExtrinsicPayload: 'GenericExtrinsicPayload',
|
||||
ExtrinsicUnknown: 'GenericExtrinsicUnknown',
|
||||
Hash: 'H256',
|
||||
Header: {
|
||||
parentHash: 'Hash',
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import { Codec } from '../../types';
|
||||
import { Compact, Struct } from '../../codec';
|
||||
import { Bytes, Fixed64, GenericAccountId, GenericAccountIndex, GenericAddress, GenericBlock, GenericCall, GenericConsensusEngineId, GenericDigest, GenericDigestItem, GenericExtrinsic, GenericExtrinsicEra, GenericExtrinsicPayload, GenericImmortalEra, GenericMortalEra, GenericOrigin, H256, H512, Null, StorageData, StorageKey, u128, u32, u64 } from '../../primitive';
|
||||
import { Bytes, Fixed64, GenericAccountId, GenericAccountIndex, GenericAddress, GenericBlock, GenericCall, GenericConsensusEngineId, GenericDigest, GenericDigestItem, GenericExtrinsic, GenericExtrinsicEra, GenericExtrinsicPayload, GenericExtrinsicUnknown, GenericImmortalEra, GenericMortalEra, GenericOrigin, H256, H512, Null, StorageData, StorageKey, u128, u32, u64 } from '../../primitive';
|
||||
|
||||
/** GenericAccountId */
|
||||
export type AccountId = GenericAccountId;
|
||||
@@ -59,6 +59,9 @@ export type ExtrinsicEra = GenericExtrinsicEra;
|
||||
/** GenericExtrinsicPayload */
|
||||
export type ExtrinsicPayload = GenericExtrinsicPayload;
|
||||
|
||||
/** GenericExtrinsicUnknown */
|
||||
export type ExtrinsicUnknown = GenericExtrinsicUnknown;
|
||||
|
||||
/** H256 */
|
||||
export type Hash = H256;
|
||||
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { FunctionMetadataV7 } from '../../interfaces/metadata/types';
|
||||
import { Address, Balance, Call, Index } from '../../interfaces/runtime';
|
||||
import { Address, Balance, Call, ExtrinsicUnknown, Index } from '../../interfaces/runtime';
|
||||
import { AnyU8a, ArgsDef, Codec, ExtrinsicPayloadValue, IExtrinsic, IHash, IKeyringPair, SignatureOptions } from '../../types';
|
||||
import { ExtrinsicOptions } from './types';
|
||||
|
||||
import { assert, isHex, isU8a, u8aConcat, u8aToHex, u8aToU8a } from '@polkadot/util';
|
||||
|
||||
import { ClassOf } from '../../codec/create';
|
||||
import { createType, ClassOf } from '../../codec/create';
|
||||
import Base from '../../codec/Base';
|
||||
import Compact from '../../codec/Compact';
|
||||
import ExtrinsicV1, { ExtrinsicValueV1 } from './v1/Extrinsic';
|
||||
@@ -17,9 +18,13 @@ import ExtrinsicV3, { ExtrinsicValueV3 } from './v3/Extrinsic';
|
||||
import ExtrinsicEra from './ExtrinsicEra';
|
||||
import { BIT_SIGNED, BIT_UNSIGNED, DEFAULT_VERSION, UNMASK_VERSION } from './constants';
|
||||
|
||||
// We use this type internally to cast the raw value since ExtrinsicUnknown does not actually properly
|
||||
// implement an Extrinsic - by design, it just throws on construction, allowing for overrides
|
||||
type ExtrinsicVx = ExtrinsicV1 | ExtrinsicV2 | ExtrinsicV3;
|
||||
|
||||
type ExtrinsicValue = ExtrinsicValueV1 | ExtrinsicValueV2 | ExtrinsicValueV3;
|
||||
|
||||
interface ExtrinsicOptions {
|
||||
interface CreateOptions {
|
||||
version?: number;
|
||||
}
|
||||
|
||||
@@ -35,28 +40,29 @@ interface ExtrinsicOptions {
|
||||
* - signed, to create a transaction
|
||||
* - left as is, to create an inherent
|
||||
*/
|
||||
export default class Extrinsic extends Base<ExtrinsicV1 | ExtrinsicV2 | ExtrinsicV3> implements IExtrinsic {
|
||||
public constructor (value: Extrinsic | ExtrinsicValue | AnyU8a | Call | undefined, { version }: ExtrinsicOptions = {}) {
|
||||
export default class Extrinsic extends Base<ExtrinsicVx | ExtrinsicUnknown> implements IExtrinsic {
|
||||
public constructor (value: Extrinsic | ExtrinsicValue | AnyU8a | Call | undefined, { version }: CreateOptions = {}) {
|
||||
super(Extrinsic.decodeExtrinsic(value, version));
|
||||
}
|
||||
|
||||
private static newFromValue (value: any, version: number): ExtrinsicV1 | ExtrinsicV2 | ExtrinsicV3 {
|
||||
private static newFromValue (value: any, version: number): ExtrinsicVx | ExtrinsicUnknown {
|
||||
if (value instanceof Extrinsic) {
|
||||
return value.raw;
|
||||
}
|
||||
|
||||
const isSigned = (version & BIT_SIGNED) === BIT_SIGNED;
|
||||
const type = version & UNMASK_VERSION;
|
||||
const options: ExtrinsicOptions = { isSigned, version };
|
||||
|
||||
switch (type) {
|
||||
case 1: return new ExtrinsicV1(value, { isSigned });
|
||||
case 2: return new ExtrinsicV2(value, { isSigned });
|
||||
case 3: return new ExtrinsicV3(value, { isSigned });
|
||||
default: throw new Error(`Unsupported extrinsic version ${type}`);
|
||||
case 1: return new ExtrinsicV1(value, options);
|
||||
case 2: return new ExtrinsicV2(value, options);
|
||||
case 3: return new ExtrinsicV3(value, options);
|
||||
default: return createType('ExtrinsicUnknown', value, options);
|
||||
}
|
||||
}
|
||||
|
||||
public static decodeExtrinsic (value: Extrinsic | ExtrinsicValue | AnyU8a | Call | undefined, version: number = DEFAULT_VERSION): ExtrinsicV1 | ExtrinsicV2 | ExtrinsicV3 {
|
||||
public static decodeExtrinsic (value: Extrinsic | ExtrinsicValue | AnyU8a | Call | undefined, version: number = DEFAULT_VERSION): ExtrinsicVx | ExtrinsicUnknown {
|
||||
if (Array.isArray(value) || isHex(value)) {
|
||||
// Instead of the block below, it should simply be:
|
||||
// return Extrinsic.decodeExtrinsic(hexToU8a(value as string));
|
||||
@@ -91,7 +97,7 @@ export default class Extrinsic extends Base<ExtrinsicV1 | ExtrinsicV2 | Extrinsi
|
||||
return Extrinsic.newFromValue(value, version);
|
||||
}
|
||||
|
||||
private static decodeU8a (value: Uint8Array): ExtrinsicV1 | ExtrinsicV2 | ExtrinsicV3 {
|
||||
private static decodeU8a (value: Uint8Array): ExtrinsicVx | ExtrinsicUnknown {
|
||||
return Extrinsic.newFromValue(value.subarray(1), value[0]);
|
||||
}
|
||||
|
||||
@@ -127,7 +133,7 @@ export default class Extrinsic extends Base<ExtrinsicV1 | ExtrinsicV2 | Extrinsi
|
||||
* @description The era for thios extrinsic
|
||||
*/
|
||||
public get era (): ExtrinsicEra {
|
||||
return this.raw.signature.era;
|
||||
return (this.raw as ExtrinsicVx).signature.era;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,7 +154,7 @@ export default class Extrinsic extends Base<ExtrinsicV1 | ExtrinsicV2 | Extrinsi
|
||||
* @description `true` id the extrinsic is signed
|
||||
*/
|
||||
public get isSigned (): boolean {
|
||||
return this.raw.signature.isSigned;
|
||||
return (this.raw as ExtrinsicVx).signature.isSigned;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,42 +175,42 @@ export default class Extrinsic extends Base<ExtrinsicV1 | ExtrinsicV2 | Extrinsi
|
||||
* @description The [[Call]] this extrinsic wraps
|
||||
*/
|
||||
public get method (): Call {
|
||||
return this.raw.method;
|
||||
return (this.raw as ExtrinsicVx).method;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The nonce for this extrinsic
|
||||
*/
|
||||
public get nonce (): Compact<Index> {
|
||||
return this.raw.signature.nonce;
|
||||
return (this.raw as ExtrinsicVx).signature.nonce;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The [[ExtrinsicSignature]]
|
||||
*/
|
||||
public get signature (): IHash {
|
||||
return this.raw.signature.signature;
|
||||
return (this.raw as ExtrinsicVx).signature.signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The [[Address]] that signed
|
||||
*/
|
||||
public get signer (): Address {
|
||||
return this.raw.signature.signer;
|
||||
return (this.raw as ExtrinsicVx).signature.signer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Forwards compat
|
||||
*/
|
||||
public get tip (): Compact<Balance> {
|
||||
return this.raw.signature.tip;
|
||||
return (this.raw as ExtrinsicVx).signature.tip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the raw transaction version (not flagged with signing information)
|
||||
*/
|
||||
public get type (): number {
|
||||
return this.raw.version;
|
||||
return (this.raw as ExtrinsicVx).version;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -238,7 +244,7 @@ export default class Extrinsic extends Base<ExtrinsicV1 | ExtrinsicV2 | Extrinsi
|
||||
};
|
||||
}
|
||||
|
||||
this.raw.addSignature(signer, signature, payload);
|
||||
(this.raw as ExtrinsicVx).addSignature(signer, signature, payload);
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -247,7 +253,7 @@ export default class Extrinsic extends Base<ExtrinsicV1 | ExtrinsicV2 | Extrinsi
|
||||
* @description Sign the extrinsic with a specific keypair
|
||||
*/
|
||||
public sign (account: IKeyringPair, options: SignatureOptions): Extrinsic {
|
||||
this.raw.sign(account, options);
|
||||
(this.raw as ExtrinsicVx).sign(account, options);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// 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 { ExtrinsicOptions } from './types';
|
||||
|
||||
import Struct from '../../codec/Struct';
|
||||
import { UNMASK_VERSION } from './constants';
|
||||
|
||||
/**
|
||||
* @name ExtrinsicUnknown
|
||||
* @description
|
||||
* A default handler for extrinsics where the version is not known (default throw)
|
||||
*/
|
||||
export default class ExtrinsicUnknown extends Struct {
|
||||
public constructor (value?: any, { isSigned = false, version = 0 }: Partial<ExtrinsicOptions> = {}) {
|
||||
super({});
|
||||
|
||||
throw new Error(`Unsupported ${isSigned ? '' : 'un'}signed extrinsic version ${version & UNMASK_VERSION}`);
|
||||
}
|
||||
}
|
||||
@@ -5,3 +5,4 @@
|
||||
export { default as GenericExtrinsic } from './Extrinsic';
|
||||
export { default as GenericExtrinsicEra, MortalEra as GenericMortalEra, ImmortalEra as GenericImmortalEra } from './ExtrinsicEra';
|
||||
export { default as GenericExtrinsicPayload } from './ExtrinsicPayload';
|
||||
export { default as GenericExtrinsicUnknown } from './ExtrinsicUnknown';
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
import { AnyNumber } from '../../types';
|
||||
|
||||
export interface ExtrinsicOptions {
|
||||
isSigned?: boolean;
|
||||
isSigned: boolean;
|
||||
version: number;
|
||||
}
|
||||
|
||||
export interface ExtrinsicSignatureOptions {
|
||||
|
||||
@@ -25,7 +25,7 @@ const TRANSACTION_VERSION = 1;
|
||||
* The first generation of compact extrinsics
|
||||
*/
|
||||
export default class ExtrinsicV1 extends Struct implements IExtrinsicImpl {
|
||||
public constructor (value?: Uint8Array | ExtrinsicValueV1, { isSigned }: ExtrinsicOptions = {}) {
|
||||
public constructor (value?: Uint8Array | ExtrinsicValueV1, { isSigned }: Partial<ExtrinsicOptions> = {}) {
|
||||
super({
|
||||
signature: ExtrinsicSignatureV1,
|
||||
method: 'Call'
|
||||
|
||||
@@ -25,7 +25,7 @@ export interface ExtrinsicValueV2 {
|
||||
* The second generation of compact extrinsics
|
||||
*/
|
||||
export default class ExtrinsicV2 extends Struct implements IExtrinsicImpl {
|
||||
public constructor (value?: Uint8Array | ExtrinsicValueV2 | Call, { isSigned }: ExtrinsicOptions = {}) {
|
||||
public constructor (value?: Uint8Array | ExtrinsicValueV2 | Call, { isSigned }: Partial<ExtrinsicOptions> = {}) {
|
||||
super({
|
||||
signature: ExtrinsicSignatureV2,
|
||||
method: 'Call'
|
||||
|
||||
@@ -22,10 +22,10 @@ export interface ExtrinsicValueV3 {
|
||||
/**
|
||||
* @name ExtrinsicV3
|
||||
* @description
|
||||
* The second generation of compact extrinsics
|
||||
* The third generation of compact extrinsics
|
||||
*/
|
||||
export default class ExtrinsicV3 extends Struct implements IExtrinsicImpl {
|
||||
public constructor (value?: Uint8Array | ExtrinsicValueV3 | Call, { isSigned }: ExtrinsicOptions = {}) {
|
||||
public constructor (value?: Uint8Array | ExtrinsicValueV3 | Call, { isSigned }: Partial<ExtrinsicOptions> = {}) {
|
||||
super({
|
||||
signature: ExtrinsicSignatureV3,
|
||||
method: 'Call'
|
||||
|
||||
Reference in New Issue
Block a user