Configurable extrinsic signature (#2845)

* Configurable extrinsic signature

* With Address override as well
This commit is contained in:
Jaco Greeff
2020-11-12 19:31:55 +01:00
committed by GitHub
parent 4dd0372702
commit 4db33b6caf
11 changed files with 140 additions and 26 deletions
@@ -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'
}
}]
+7 -1
View File
@@ -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 {}