Skip to content

Commit b22620b

Browse files
authored
Adjust ExtrinsicV5 to fit current spec (#6029)
* Adjust ExtrinsicV5 to fit current spec * Remove signed from `Extrinsic` * Fix tests and error on signed v5 * Set sign functionality to error for V5 * Removing signing from payload * Update error messaging * Disable all signing functionality * linter * Fix signature tests
1 parent 40ac28b commit b22620b

File tree

11 files changed

+64
-220
lines changed

11 files changed

+64
-220
lines changed

packages/types/src/extrinsic/Extrinsic.spec.ts

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -57,36 +57,19 @@ describe('Extrinsic', (): void => {
5757
registry.setMetadata(metadata);
5858

5959
describe('SignedExtrinsic', () => {
60-
it('Should work when the version and preamble is passed in', () => {
61-
const extrinsic = new Extrinsic(
60+
it('Should error with a signed extrinsic, when the version is passed in', () => {
61+
expect(() => new Extrinsic(
6262
registry,
6363
'0x51028500d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d011e0b7d9438899333c50121f8e10144952d51c3bb8d0ea11dd1f24940d8ff615ad351d95ed9f41f078748ed7cf182864a20b38eebfaef6629433365eb90c0148c007502000000000603008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a480b00a0724e1809',
64-
{ preamble: 'signed', version: 5 }
65-
);
66-
67-
expect(extrinsic.signer.toString()).toEqual('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY');
68-
expect(extrinsic.era.toHuman()).toEqual({ MortalEra: { period: '64', phase: '39' } });
69-
expect(extrinsic.nonce.toNumber()).toEqual(0);
70-
expect(extrinsic.tip.toHuman()).toEqual('0');
71-
expect(extrinsic.callIndex).toEqual(new Uint8Array([6, 3]));
72-
expect(extrinsic.args[0].toHex()).toEqual('0x008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48');
73-
expect(extrinsic.args[1].toHuman()).toEqual('10,000,000,000,000');
64+
{ version: 5 }
65+
)).toThrow('Signed Extrinsics are currently only available for ExtrinsicV4');
7466
});
7567

76-
it('Should work when the version and preamble is not passed in', () => {
77-
const extrinsic = new Extrinsic(
68+
it('Should error when the version and preamble is not passed in, and its a signed extrinsic', () => {
69+
expect(() => new Extrinsic(
7870
registry,
7971
'0x51028500d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d011e0b7d9438899333c50121f8e10144952d51c3bb8d0ea11dd1f24940d8ff615ad351d95ed9f41f078748ed7cf182864a20b38eebfaef6629433365eb90c0148c007502000000000603008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a480b00a0724e1809'
80-
);
81-
82-
expect(extrinsic.version).toEqual(133);
83-
expect(extrinsic.signer.toString()).toEqual('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY');
84-
expect(extrinsic.era.toHuman()).toEqual({ MortalEra: { period: '64', phase: '39' } });
85-
expect(extrinsic.nonce.toNumber()).toEqual(0);
86-
expect(extrinsic.tip.toHuman()).toEqual('0');
87-
expect(extrinsic.callIndex).toEqual(new Uint8Array([6, 3]));
88-
expect(extrinsic.args[0].toHex()).toEqual('0x008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48');
89-
expect(extrinsic.args[1].toHuman()).toEqual('10,000,000,000,000');
72+
)).toThrow('Signed Extrinsics are currently only available for ExtrinsicV4');
9073
});
9174
});
9275

packages/types/src/extrinsic/Extrinsic.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import type { ExtrinsicValueV5 } from './v5/Extrinsic.js';
1616
import { AbstractBase } from '@polkadot/types-codec';
1717
import { compactAddLength, compactFromU8a, compactToU8a, isHex, isU8a, objectProperty, objectSpread, u8aConcat, u8aToHex, u8aToU8a } from '@polkadot/util';
1818

19-
import { BARE_EXTRINSIC, BIT_SIGNED, BIT_UNSIGNED, DEFAULT_PREAMBLE, GENERAL_EXTRINSIC, LATEST_EXTRINSIC_VERSION, LOWEST_SUPPORTED_EXTRINSIC_FORMAT_VERSION, SIGNED_EXTRINSIC, TYPE_MASK, VERSION_MASK } from './constants.js';
19+
import { BARE_EXTRINSIC, BIT_SIGNED, BIT_UNSIGNED, DEFAULT_PREAMBLE, GENERAL_EXTRINSIC, LATEST_EXTRINSIC_VERSION, LOWEST_SUPPORTED_EXTRINSIC_FORMAT_VERSION, TYPE_MASK, VERSION_MASK } from './constants.js';
2020

2121
interface CreateOptions {
2222
version?: number;
@@ -40,22 +40,18 @@ const VERSIONS = [
4040

4141
const PREAMBLE = {
4242
bare: 'ExtrinsicV5',
43-
general: 'GeneralExtrinsic',
44-
signed: 'ExtrinsicV5'
43+
general: 'GeneralExtrinsic'
4544
};
4645

4746
const PreambleMask = {
4847
bare: BARE_EXTRINSIC,
49-
general: GENERAL_EXTRINSIC,
50-
signed: SIGNED_EXTRINSIC
48+
general: GENERAL_EXTRINSIC
5149
};
5250

5351
const preambleUnMask: Record<string, Preamble> = {
5452
0: 'bare',
5553
// eslint-disable-next-line sort-keys
56-
64: 'general',
57-
// eslint-disable-next-line sort-keys
58-
128: 'signed'
54+
64: 'general'
5955
};
6056

6157
export { LATEST_EXTRINSIC_VERSION };
@@ -295,7 +291,11 @@ abstract class ExtrinsicBase<A extends AnyTuple> extends AbstractBase<ExtrinsicV
295291
if (this.type <= LOWEST_SUPPORTED_EXTRINSIC_FORMAT_VERSION) {
296292
return this.type | (this.isSigned ? BIT_SIGNED : BIT_UNSIGNED);
297293
} else {
298-
return this.type | (this.isSigned ? PreambleMask.signed : this.isGeneral() ? PreambleMask.general : PreambleMask.bare);
294+
if (this.isSigned) {
295+
throw new Error('Signed Extrinsics are currently only available for ExtrinsicV4');
296+
}
297+
298+
return this.type | (this.isGeneral() ? PreambleMask.general : PreambleMask.bare);
299299
}
300300
}
301301

packages/types/src/extrinsic/ExtrinsicPayload.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ const VERSIONS = [
3636
const PREAMBLES = {
3737
bare: 'ExtrinsicPayloadV5',
3838
// Not supported yet
39-
general: 'ExtrinsicPayloadV5',
40-
signed: 'ExtrinsicPayloadV5'
39+
general: 'ExtrinsicPayloadV5'
4140
};
4241

4342
/** @internal */

packages/types/src/extrinsic/constants.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ export const TYPE_MASK = 0b11000000;
2222

2323
export const BARE_EXTRINSIC = 0b00000000;
2424

25-
export const SIGNED_EXTRINSIC = 0b10000000;
26-
2725
export const GENERAL_EXTRINSIC = 0b01000000;
2826

2927
export const LOWEST_SUPPORTED_EXTRINSIC_FORMAT_VERSION = 4;

packages/types/src/extrinsic/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ export interface ExtrinsicExtraValue {
2222
tip?: AnyNumber;
2323
}
2424

25-
export type Preamble = 'signed' | 'bare' | 'general';
25+
export type Preamble = 'bare' | 'general';

packages/types/src/extrinsic/util.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,6 @@ export function sign (registry: Registry, signerPair: IKeyringPair, u8a: Uint8Ar
1414
return signerPair.sign(encoded, options);
1515
}
1616

17-
// a helper function for both types of payloads, Raw and metadata-known
18-
export function signV5 (registry: Registry, signerPair: IKeyringPair, u8a: Uint8Array, options?: SignOptions): Uint8Array {
19-
const encoded = registry.hash(u8a);
20-
21-
return signerPair.sign(encoded, options);
22-
}
23-
2417
export function signGeneral (registry: Registry, u8a: Uint8Array): Uint8Array {
2518
const encoded = registry.hash(u8a);
2619

packages/types/src/extrinsic/v5/Extrinsic.spec.ts

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ describe('ExtrinsicV5', (): void => {
4848
);
4949
});
5050

51-
it('creates a signed extrinsic', (): void => {
51+
it('Errors when creating a signed Extrinsic', (): void => {
5252
expect(
53-
new Extrinsic(
53+
() => new Extrinsic(
5454
registry,
5555
tx['balances']['transferAllowDeath'](keyring.bob.publicKey, 6969n)
5656
).sign(keyring.alice, {
@@ -69,19 +69,6 @@ describe('ExtrinsicV5', (): void => {
6969
},
7070
tip: 2
7171
}).toHex()
72-
).toEqual(
73-
'0x' +
74-
'00' +
75-
'd172a74cda4c865912c32ba0a80a57ae69abae410e5ccb59dee84e2f4432db4f' +
76-
'00' + // ed25519
77-
'84181ebef350cc212e70e042b6ebcd33ca955bf9497711a64aa7c64e2b8c2732' +
78-
'ab837715364eab7be5cc76f74eefa36d3ba9ee698264ed28a286c8360fc9aa0c' +
79-
'00' + // TransactionExtension version
80-
'0004080000' + // era. nonce, tip, mode
81-
'0600' +
82-
'00' +
83-
'd7568e5f0a7eda67a82691ff379ac4bba4f9c9b859fe779b5d46363b61ad2db9' +
84-
'e56c'
85-
);
72+
).toThrow('Extrinsic: ExtrinsicV5 does not include signing support');
8673
});
8774
});

packages/types/src/extrinsic/v5/Extrinsic.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -89,28 +89,28 @@ export class GenericExtrinsicV5 extends Struct implements IExtrinsicV5Impl {
8989

9090
/**
9191
* @description Add an [[ExtrinsicSignatureV5]] to the extrinsic (already generated)
92+
*
93+
* [Disabled for ExtrinsicV5]
9294
*/
93-
public addSignature (signer: Address | Uint8Array | string, signature: Uint8Array | HexString, payload: ExtrinsicPayloadValue | Uint8Array | HexString): GenericExtrinsicV5 {
94-
this.signature.addSignature(signer, signature, payload);
95-
96-
return this;
95+
public addSignature (_signer: Address | Uint8Array | string, _signature: Uint8Array | HexString, _payload: ExtrinsicPayloadValue | Uint8Array | HexString): GenericExtrinsicV5 {
96+
throw new Error('Extrinsic: ExtrinsicV5 does not include signing support');
9797
}
9898

9999
/**
100100
* @description Sign the extrinsic with a specific keypair
101+
*
102+
* [Disabled for ExtrinsicV5]
101103
*/
102-
public sign (account: IKeyringPair, options: SignatureOptions): GenericExtrinsicV5 {
103-
this.signature.sign(this.method, account, options);
104-
105-
return this;
104+
public sign (_account: IKeyringPair, _options: SignatureOptions): GenericExtrinsicV5 {
105+
throw new Error('Extrinsic: ExtrinsicV5 does not include signing support');
106106
}
107107

108108
/**
109109
* @describe Adds a fake signature to the extrinsic
110+
*
111+
* [Disabled for ExtrinsicV5]
110112
*/
111-
public signFake (signer: Address | Uint8Array | string, options: SignatureOptions): GenericExtrinsicV5 {
112-
this.signature.signFake(this.method, signer, options);
113-
114-
return this;
113+
public signFake (_signer: Address | Uint8Array | string, _options: SignatureOptions): GenericExtrinsicV5 {
114+
throw new Error('Extrinsic: ExtrinsicV5 does not include signing support');
115115
}
116116
}

packages/types/src/extrinsic/v5/ExtrinsicPayload.ts

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright 2017-2024 @polkadot/types authors & contributors
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import type { SignOptions } from '@polkadot/keyring/types';
54
import type { Hash, MultiLocation } from '@polkadot/types/interfaces';
65
import type { Bytes } from '@polkadot/types-codec';
76
import type { Inspect, Registry } from '@polkadot/types-codec/types';
@@ -10,33 +9,22 @@ import type { BlockHash } from '../../interfaces/chain/index.js';
109
import type { ExtrinsicEra } from '../../interfaces/extrinsics/index.js';
1110
import type { ExtrinsicPayloadValue, ICompact, IKeyringPair, INumber, IOption } from '../../types/index.js';
1211

13-
import { Enum, Struct } from '@polkadot/types-codec';
12+
import { Struct } from '@polkadot/types-codec';
1413
import { objectSpread } from '@polkadot/util';
1514

16-
import { signV5 } from '../util.js';
17-
1815
/**
1916
* @name GenericExtrinsicPayloadV5
2017
* @description
2118
* A signing payload for an [[Extrinsic]]. For the final encoding, it is
2219
* variable length based on the contents included
2320
*/
2421
export class GenericExtrinsicPayloadV5 extends Struct {
25-
#signOptions: SignOptions;
26-
2722
constructor (registry: Registry, value?: ExtrinsicPayloadValue | Uint8Array | HexString) {
2823
super(registry, objectSpread(
2924
{ method: 'Bytes' },
3025
registry.getSignedExtensionTypes(),
3126
registry.getSignedExtensionExtra()
3227
), value);
33-
34-
// Do detection for the type of extrinsic, in the case of MultiSignature
35-
// this is an enum, in the case of AnySignature, this is a Hash only
36-
// (which may be 64 or 65 bytes)
37-
this.#signOptions = {
38-
withType: registry.createTypeUnsafe('ExtrinsicSignature', []) instanceof Enum
39-
};
4028
}
4129

4230
/**
@@ -118,13 +106,10 @@ export class GenericExtrinsicPayloadV5 extends Struct {
118106

119107
/**
120108
* @description Sign the payload with the keypair
109+
*
110+
* [Disabled for ExtrinsicV5]
121111
*/
122-
public sign (signerPair: IKeyringPair): Uint8Array {
123-
// NOTE The `toU8a({ method: true })` argument is absolutely critical, we
124-
// don't want the method (Bytes) to have the length prefix included. This
125-
// means that the data-as-signed is un-decodable, but is also doesn't need
126-
// the extra information, only the pure data (and is not decoded) ...
127-
// The same applies to V1..V3, if we have a V6, carry this comment
128-
return signV5(this.registry, signerPair, this.toU8a({ method: true }), this.#signOptions);
112+
public sign (_signerPair: IKeyringPair): Uint8Array {
113+
throw new Error('Extrinsic: ExtrinsicV5 does not include signing support');
129114
}
130115
}

packages/types/src/extrinsic/v5/ExtrinsicSignature.spec.ts

Lines changed: 8 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -61,25 +61,15 @@ describe('ExtrinsicSignatureV4', (): void => {
6161
registry.setMetadata(metadata);
6262

6363
expect(
64-
new ExtrinsicSignature(registry).signFake(
64+
() => new ExtrinsicSignature(registry).signFake(
6565
registry.createType('Call'),
6666
pairs.alice.publicKey,
6767
signOptions
6868
).toHex()
69-
).toEqual(
70-
'0x' +
71-
'00' + // MultiAddress
72-
'd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d' +
73-
'01' +
74-
'0101010101010101010101010101010101010101010101010101010101010101' +
75-
'0101010101010101010101010101010101010101010101010101010101010101' +
76-
'00' + // TransactionExtension version
77-
'00a5010000' +
78-
'00' // Mode
79-
);
69+
).toThrow('Extrinsic: ExtrinsicV5 does not include signing support');
8070
});
8171

82-
it('fake signs default (AccountId address)', (): void => {
72+
it('Errors on fake sign', (): void => {
8373
const registry = new TypeRegistry();
8474
const metadata = new Metadata(registry, metadataStatic);
8575

@@ -90,76 +80,26 @@ describe('ExtrinsicSignatureV4', (): void => {
9080
});
9181

9282
expect(
93-
new ExtrinsicSignature(registry).signFake(
83+
() => new ExtrinsicSignature(registry).signFake(
9484
registry.createType('Call'),
9585
pairs.alice.address,
9686
signOptions
9787
).toHex()
98-
).toEqual(
99-
'0x' +
100-
// Address = AccountId, no prefix
101-
'd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d' +
102-
// This is a prefix-less signature, anySignture as opposed to Multi above
103-
'0101010101010101010101010101010101010101010101010101010101010101' +
104-
'0101010101010101010101010101010101010101010101010101010101010101' +
105-
'00' + // TransactionExtension version
106-
'00a5010000' +
107-
'00' // mode
108-
);
88+
).toThrow('Extrinsic: ExtrinsicV5 does not include signing support');
10989
});
11090

111-
it('fake signs with non-enum signature', (): void => {
112-
const registry = new TypeRegistry();
113-
const metadata = new Metadata(registry, metadataStatic);
114-
115-
registry.setMetadata(metadata);
116-
registry.register({
117-
Address: 'AccountId',
118-
ExtrinsicSignature: '[u8;65]'
119-
});
120-
121-
expect(
122-
new ExtrinsicSignature(registry).signFake(
123-
registry.createType('Call'),
124-
pairs.alice.address,
125-
signOptions
126-
).toHex()
127-
).toEqual(
128-
'0x' +
129-
// Address = AccountId, no prefix
130-
'd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d' +
131-
// 65 bytes here
132-
'01' +
133-
'0101010101010101010101010101010101010101010101010101010101010101' +
134-
'0101010101010101010101010101010101010101010101010101010101010101' +
135-
'00' + // TransactionExtension version
136-
'00a5010000' +
137-
'00' // mode
138-
);
139-
});
140-
141-
it('injects a signature', (): void => {
91+
it('Errors on injecting a signature', (): void => {
14292
const registry = new TypeRegistry();
14393
const metadata = new Metadata(registry, metadataStatic);
14494

14595
registry.setMetadata(metadata);
14696

14797
expect(
148-
new ExtrinsicSignature(registry).addSignature(
98+
() => new ExtrinsicSignature(registry).addSignature(
14999
pairs.alice.publicKey,
150100
new Uint8Array(65).fill(1),
151101
new Uint8Array(0)
152102
).toHex()
153-
).toEqual(
154-
'0x' +
155-
'00' + // MultiAddress
156-
'd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d' +
157-
'01' +
158-
'0101010101010101010101010101010101010101010101010101010101010101' +
159-
'0101010101010101010101010101010101010101010101010101010101010101' +
160-
'00' + // TransactionExtension version
161-
'00000000' +
162-
'00' // mode
163-
);
103+
).toThrow('Extrinsic: ExtrinsicV5 does not include signing support');
164104
});
165105
});

0 commit comments

Comments
 (0)