Configurable extrinsic signature (#2845)
* Configurable extrinsic signature * With Address override as well
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
// Copyright 2017-2020 @polkadot/typegen authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires,sort-keys */
|
||||
|
||||
let main;
|
||||
|
||||
@@ -14,13 +15,13 @@ try {
|
||||
['module-resolver', {
|
||||
alias: {
|
||||
'^@polkadot/api-derive(.*)': './packages/api-derive/src\\1',
|
||||
// eslint-disable-next-line sort-keys
|
||||
'^@polkadot/api/package.json': './packages/api/package.json',
|
||||
'^@polkadot/api(.*)': './packages/api/src/\\1',
|
||||
'^@polkadot/metadata(.*)': './packages/metadata/src\\1',
|
||||
'^@polkadot/rpc-core(.*)': './packages/rpc-core/src\\1',
|
||||
'^@polkadot/rpc-provider(.*)': './packages/rpc-provider/src\\1',
|
||||
'^@polkadot/types-known(.*)': './packages/types-known/src\\1',
|
||||
// eslint-disable-next-line sort-keys
|
||||
'^@polkadot/types/package.json': './packages/types/package.json',
|
||||
'^@polkadot/types(.*)': './packages/types/src\\1'
|
||||
}
|
||||
}]
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
// Copyright 2017-2020 @polkadot/typegen authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires,sort-keys */
|
||||
|
||||
let main;
|
||||
|
||||
@@ -15,7 +16,7 @@ try {
|
||||
alias: {
|
||||
'^@polkadot/metadata(.*)': './packages/metadata/src\\1',
|
||||
'^@polkadot/types-known(.*)': './packages/types-known/src\\1',
|
||||
// eslint-disable-next-line sort-keys
|
||||
'^@polkadot/types/package.json': './packages/types/package.json',
|
||||
'^@polkadot/types(.*)': './packages/types/src\\1'
|
||||
}
|
||||
}]
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
// Copyright 2017-2020 @polkadot/typegen authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires,sort-keys */
|
||||
|
||||
let main;
|
||||
|
||||
@@ -16,7 +17,7 @@ try {
|
||||
'^@polkadot/metadata(.*)': './packages/metadata/src\\1',
|
||||
'^@polkadot/typegen(.*)': './packages/typegen/src\\1',
|
||||
'^@polkadot/types-known(.*)': './packages/types-known/src\\1',
|
||||
// eslint-disable-next-line sort-keys
|
||||
'^@polkadot/types/package.json': './packages/types/package.json',
|
||||
'^@polkadot/types(.*)': './packages/types/src\\1'
|
||||
}
|
||||
}]
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
// Copyright 2017-2020 @polkadot/typegen authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires,sort-keys */
|
||||
|
||||
let main;
|
||||
|
||||
@@ -15,7 +16,7 @@ try {
|
||||
alias: {
|
||||
'^@polkadot/metadata(.*)': './packages/metadata/src\\1',
|
||||
'^@polkadot/types-known(.*)': './packages/types-known/src\\1',
|
||||
// eslint-disable-next-line sort-keys
|
||||
'^@polkadot/types/package.json': './packages/types/package.json',
|
||||
'^@polkadot/types(.*)': './packages/types/src\\1'
|
||||
}
|
||||
}]
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
// Copyright 2017-2020 @polkadot/typegen authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires,sort-keys */
|
||||
|
||||
let main;
|
||||
|
||||
@@ -15,7 +16,7 @@ try {
|
||||
alias: {
|
||||
'^@polkadot/metadata(.*)': './packages/metadata/src\\1',
|
||||
'^@polkadot/types-known(.*)': './packages/types-known/src\\1',
|
||||
// eslint-disable-next-line sort-keys
|
||||
'^@polkadot/types/package.json': './packages/types/package.json',
|
||||
'^@polkadot/types(.*)': './packages/types/src\\1'
|
||||
}
|
||||
}]
|
||||
|
||||
@@ -21,7 +21,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, ExtrinsicPayloadV4, ExtrinsicSignatureV4, ExtrinsicUnknown, ExtrinsicV4, ImmortalEra, MortalEra, MultiSignature, Signature, SignerPayload, Sr25519Signature } from '@polkadot/types/interfaces/extrinsics';
|
||||
import { AnySignature, EcdsaSignature, Ed25519Signature, Extrinsic, ExtrinsicEra, ExtrinsicPayload, ExtrinsicPayloadUnknown, ExtrinsicPayloadV4, ExtrinsicSignature, 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';
|
||||
@@ -715,6 +715,9 @@ declare module '@polkadot/types/types/registry' {
|
||||
ExtrinsicPayload: ExtrinsicPayload;
|
||||
'Option<ExtrinsicPayload>': Option<ExtrinsicPayload>;
|
||||
'Vec<ExtrinsicPayload>': Vec<ExtrinsicPayload>;
|
||||
ExtrinsicSignature: ExtrinsicSignature;
|
||||
'Option<ExtrinsicSignature>': Option<ExtrinsicSignature>;
|
||||
'Vec<ExtrinsicSignature>': Vec<ExtrinsicSignature>;
|
||||
ExtrinsicV4: ExtrinsicV4;
|
||||
'Option<ExtrinsicV4>': Option<ExtrinsicV4>;
|
||||
'Vec<ExtrinsicV4>': Vec<ExtrinsicV4>;
|
||||
@@ -736,6 +739,9 @@ declare module '@polkadot/types/types/registry' {
|
||||
MortalEra: MortalEra;
|
||||
'Option<MortalEra>': Option<MortalEra>;
|
||||
'Vec<MortalEra>': Vec<MortalEra>;
|
||||
AnySignature: AnySignature;
|
||||
'Option<AnySignature>': Option<AnySignature>;
|
||||
'Vec<AnySignature>': Vec<AnySignature>;
|
||||
MultiSignature: MultiSignature;
|
||||
'Option<MultiSignature>': Option<MultiSignature>;
|
||||
'Vec<MultiSignature>': Vec<MultiSignature>;
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
// Copyright 2017-2020 @polkadot/types authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { SignOptions } from '@polkadot/keyring/types';
|
||||
import { ExtrinsicEra } from '../../interfaces/extrinsics';
|
||||
import { Balance, Hash, Index } from '../../interfaces/runtime';
|
||||
import { ExtrinsicPayloadValue, IKeyringPair, Registry } from '../../types';
|
||||
|
||||
import { Compact } from '../../codec/Compact';
|
||||
import { Enum } from '../../codec/Enum';
|
||||
import { Struct } from '../../codec/Struct';
|
||||
import { Bytes } from '../../primitive/Bytes';
|
||||
import { u32 } from '../../primitive/U32';
|
||||
@@ -18,12 +20,20 @@ import { sign } from '../util';
|
||||
* on the contents included
|
||||
*/
|
||||
export class GenericExtrinsicPayloadV4 extends Struct {
|
||||
#signOptions: SignOptions;
|
||||
|
||||
constructor (registry: Registry, value?: ExtrinsicPayloadValue | Uint8Array | string) {
|
||||
super(registry, {
|
||||
method: 'Bytes',
|
||||
...registry.getSignedExtensionTypes(),
|
||||
...registry.getSignedExtensionExtra()
|
||||
}, value);
|
||||
|
||||
// Do detection for the type of extrinsic, in the case of MultiSignature this is an
|
||||
// enum, in the case of AnySignature, this is a Hash only (may be 64 or 65 bytes)
|
||||
this.#signOptions = {
|
||||
withType: registry.createType('ExtrinsicSignature') instanceof Enum
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,6 +100,6 @@ export class GenericExtrinsicPayloadV4 extends Struct {
|
||||
// to have the length prefix included. This means that the data-as-signed is un-decodable,
|
||||
// but is also doesn't need the extra information, only the pure data (and is not decoded)
|
||||
// ... The same applies to V1..V3, if we have a V5, carry move this comment to latest
|
||||
return sign(this.registry, signerPair, this.toU8a({ method: true }), { withType: true });
|
||||
return sign(this.registry, signerPair, this.toU8a({ method: true }), this.#signOptions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,35 @@
|
||||
// Copyright 2017-2020 @polkadot/types authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { createTestPairs } from '@polkadot/keyring/testingPairs';
|
||||
import { Metadata } from '@polkadot/metadata';
|
||||
import metadataStatic from '@polkadot/metadata/static';
|
||||
import { BN_ZERO } from '@polkadot/util';
|
||||
|
||||
import { TypeRegistry } from '../../create';
|
||||
import { GenericExtrinsicSignatureV4 as ExtrinsicSignature } from '.';
|
||||
|
||||
describe('ExtrinsicSignatureV4', (): void => {
|
||||
const registry = new TypeRegistry();
|
||||
const signOptions = {
|
||||
blockHash: '0x1234567890123456789012345678901234567890123456789012345678901234',
|
||||
genesisHash: '0x1234567890123456789012345678901234567890123456789012345678901234',
|
||||
nonce: '0x69',
|
||||
runtimeVersion: {
|
||||
apis: [],
|
||||
authoringVersion: BN_ZERO,
|
||||
implName: String('test'),
|
||||
implVersion: BN_ZERO,
|
||||
specName: String('test'),
|
||||
specVersion: BN_ZERO,
|
||||
transactionVersion: BN_ZERO
|
||||
}
|
||||
};
|
||||
|
||||
describe('ExtrinsicSignatureV4', (): void => {
|
||||
const pairs = createTestPairs({ type: 'ed25519' });
|
||||
|
||||
it('encodes to a sane Uint8Array (default)', (): void => {
|
||||
const registry = new TypeRegistry();
|
||||
|
||||
it('encodes to a sane Uint8Array', (): void => {
|
||||
const u8a = new Uint8Array([
|
||||
// signer as an AccountIndex
|
||||
0x09,
|
||||
@@ -28,4 +50,56 @@ describe('ExtrinsicSignatureV4', (): void => {
|
||||
new ExtrinsicSignature(registry, u8a, { isSigned: true }).toU8a()
|
||||
).toEqual(u8a);
|
||||
});
|
||||
|
||||
it('fake signs default', (): void => {
|
||||
const registry = new TypeRegistry();
|
||||
const metadata = new Metadata(registry, metadataStatic);
|
||||
|
||||
registry.setMetadata(metadata);
|
||||
|
||||
expect(
|
||||
new ExtrinsicSignature(registry, undefined).signFake(
|
||||
registry.createType('Call'),
|
||||
pairs.alice.address,
|
||||
signOptions
|
||||
).toHex()
|
||||
).toEqual(
|
||||
'0x' +
|
||||
'ff' +
|
||||
'd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d' +
|
||||
'01' +
|
||||
'4242424242424242424242424242424242424242424242424242424242424242' +
|
||||
'4242424242424242424242424242424242424242424242424242424242424242' +
|
||||
'00a50100'
|
||||
);
|
||||
});
|
||||
|
||||
it('fake signs default', (): void => {
|
||||
const registry = new TypeRegistry();
|
||||
const metadata = new Metadata(registry, metadataStatic);
|
||||
|
||||
registry.setMetadata(metadata);
|
||||
registry.register({
|
||||
Address: 'AccountId',
|
||||
ExtrinsicSignature: 'AnySignature'
|
||||
});
|
||||
|
||||
expect(
|
||||
new ExtrinsicSignature(registry, undefined).signFake(
|
||||
registry.createType('Call'),
|
||||
pairs.alice.address,
|
||||
signOptions
|
||||
).toHex()
|
||||
).toEqual(
|
||||
'0x' +
|
||||
// Address = AccountId
|
||||
// 'ff' +
|
||||
'd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d' +
|
||||
// This is a prefix-less signature, anySignture as opposed to Multi above
|
||||
// '01' +
|
||||
'4242424242424242424242424242424242424242424242424242424242424242' +
|
||||
'4242424242424242424242424242424242424242424242424242424242424242' +
|
||||
'00a50100'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2017-2020 @polkadot/types authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { EcdsaSignature, Ed25519Signature, ExtrinsicEra, MultiSignature, Sr25519Signature } from '../../interfaces/extrinsics';
|
||||
import { EcdsaSignature, Ed25519Signature, ExtrinsicEra, ExtrinsicSignature, Sr25519Signature } from '../../interfaces/extrinsics';
|
||||
import { Address, Balance, Call, Index } from '../../interfaces/runtime';
|
||||
import { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, Registry, SignatureOptions } from '../../types';
|
||||
import { ExtrinsicSignatureOptions } from '../types';
|
||||
@@ -9,23 +9,33 @@ import { ExtrinsicSignatureOptions } from '../types';
|
||||
import { u8aConcat } from '@polkadot/util';
|
||||
|
||||
import { Compact } from '../../codec/Compact';
|
||||
import { Enum } from '../../codec/Enum';
|
||||
import { Struct } from '../../codec/Struct';
|
||||
import { EMPTY_U8A, IMMORTAL_ERA } from '../constants';
|
||||
import { GenericExtrinsicPayloadV4 } from './ExtrinsicPayload';
|
||||
|
||||
const FAKE_NONE = new Uint8Array();
|
||||
const FAKE_SOME = new Uint8Array([1]);
|
||||
|
||||
/**
|
||||
* @name GenericExtrinsicSignatureV4
|
||||
* @description
|
||||
* A container for the [[Signature]] associated with a specific [[Extrinsic]]
|
||||
*/
|
||||
export class GenericExtrinsicSignatureV4 extends Struct implements IExtrinsicSignature {
|
||||
#fakePrefix: Uint8Array;
|
||||
|
||||
constructor (registry: Registry, value: GenericExtrinsicSignatureV4 | Uint8Array | undefined, { isSigned }: ExtrinsicSignatureOptions = {}) {
|
||||
super(registry, {
|
||||
signer: 'Address',
|
||||
// eslint-disable-next-line sort-keys
|
||||
signature: 'MultiSignature',
|
||||
signature: 'ExtrinsicSignature',
|
||||
...registry.getSignedExtensionTypes()
|
||||
}, GenericExtrinsicSignatureV4.decodeExtrinsicSignature(value, isSigned));
|
||||
|
||||
this.#fakePrefix = registry.createType('ExtrinsicSignature') instanceof Enum
|
||||
? FAKE_SOME
|
||||
: FAKE_NONE;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -75,14 +85,15 @@ export class GenericExtrinsicSignatureV4 extends Struct implements IExtrinsicSig
|
||||
* @description The actual [[EcdsaSignature]], [[Ed25519Signature]] or [[Sr25519Signature]]
|
||||
*/
|
||||
public get signature (): EcdsaSignature | Ed25519Signature | Sr25519Signature {
|
||||
return this.multiSignature.value as Sr25519Signature;
|
||||
// the second case here is when we don't have an enum signature, treat as raw
|
||||
return (this.multiSignature.value || this.multiSignature) as Sr25519Signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The raw [[MultiSignature]]
|
||||
* @description The raw [[ExtrinsicSignature]]
|
||||
*/
|
||||
public get multiSignature (): MultiSignature {
|
||||
return this.get('signature') as MultiSignature;
|
||||
public get multiSignature (): ExtrinsicSignature {
|
||||
return this.get('signature') as ExtrinsicSignature;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,7 +110,7 @@ export class GenericExtrinsicSignatureV4 extends Struct implements IExtrinsicSig
|
||||
return this.get('tip') as Compact<Balance>;
|
||||
}
|
||||
|
||||
protected _injectSignature (signer: Address, signature: MultiSignature, { era, nonce, tip }: GenericExtrinsicPayloadV4): IExtrinsicSignature {
|
||||
protected _injectSignature (signer: Address, signature: ExtrinsicSignature, { era, nonce, tip }: GenericExtrinsicPayloadV4): IExtrinsicSignature {
|
||||
this.set('era', era);
|
||||
this.set('nonce', nonce);
|
||||
this.set('signer', signer);
|
||||
@@ -115,7 +126,7 @@ export class GenericExtrinsicSignatureV4 extends Struct implements IExtrinsicSig
|
||||
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('MultiSignature', signature),
|
||||
this.registry.createType('ExtrinsicSignature', signature),
|
||||
new GenericExtrinsicPayloadV4(this.registry, payload)
|
||||
);
|
||||
}
|
||||
@@ -142,7 +153,7 @@ export class GenericExtrinsicSignatureV4 extends Struct implements IExtrinsicSig
|
||||
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('MultiSignature', payload.sign(account));
|
||||
const signature = this.registry.createType('ExtrinsicSignature', payload.sign(account));
|
||||
|
||||
return this._injectSignature(signer, signature, payload);
|
||||
}
|
||||
@@ -153,7 +164,7 @@ export class GenericExtrinsicSignatureV4 extends Struct implements IExtrinsicSig
|
||||
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('MultiSignature', u8aConcat(new Uint8Array([1]), new Uint8Array(64).fill(0x42)));
|
||||
const signature = this.registry.createType('ExtrinsicSignature', u8aConcat(this.#fakePrefix, new Uint8Array(64).fill(0x42)));
|
||||
|
||||
return this._injectSignature(signer, signature, payload);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ export default {
|
||||
Extrinsic: 'GenericExtrinsic',
|
||||
ExtrinsicEra: 'GenericExtrinsicEra',
|
||||
ExtrinsicPayload: 'GenericExtrinsicPayload',
|
||||
ExtrinsicSignature: 'MultiSignature',
|
||||
ExtrinsicV4: 'GenericExtrinsicV4',
|
||||
ExtrinsicPayloadV4: 'GenericExtrinsicPayloadV4',
|
||||
ExtrinsicSignatureV4: 'GenericExtrinsicSignatureV4',
|
||||
@@ -23,6 +24,7 @@ export default {
|
||||
MortalEra: 'GenericMortalEra',
|
||||
|
||||
// signatures & signer
|
||||
AnySignature: 'H512',
|
||||
MultiSignature: {
|
||||
_enum: {
|
||||
Ed25519: 'Ed25519Signature',
|
||||
|
||||
@@ -5,6 +5,9 @@ import { Enum, U8aFixed } from '@polkadot/types/codec';
|
||||
import { GenericExtrinsic, GenericExtrinsicEra, GenericExtrinsicPayload, GenericExtrinsicPayloadUnknown, GenericExtrinsicPayloadV4, GenericExtrinsicSignatureV4, GenericExtrinsicUnknown, GenericExtrinsicV4, GenericImmortalEra, GenericMortalEra, GenericSignerPayload } from '@polkadot/types/extrinsic';
|
||||
import { H512 } from '@polkadot/types/interfaces/runtime';
|
||||
|
||||
/** @name AnySignature */
|
||||
export interface AnySignature extends H512 {}
|
||||
|
||||
/** @name EcdsaSignature */
|
||||
export interface EcdsaSignature extends U8aFixed {}
|
||||
|
||||
@@ -26,6 +29,9 @@ export interface ExtrinsicPayloadUnknown extends GenericExtrinsicPayloadUnknown
|
||||
/** @name ExtrinsicPayloadV4 */
|
||||
export interface ExtrinsicPayloadV4 extends GenericExtrinsicPayloadV4 {}
|
||||
|
||||
/** @name ExtrinsicSignature */
|
||||
export interface ExtrinsicSignature extends MultiSignature {}
|
||||
|
||||
/** @name ExtrinsicSignatureV4 */
|
||||
export interface ExtrinsicSignatureV4 extends GenericExtrinsicSignatureV4 {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user