Skip to content

Commit d35920d

Browse files
committed
[Issue-4365] feat: add ecdsa scheme for polkadot migration
1 parent 7c4f5c4 commit d35920d

File tree

5 files changed

+122
-44
lines changed

5 files changed

+122
-44
lines changed

packages/extension-base/src/background/KoniTypes.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1426,8 +1426,20 @@ export interface LedgerNetwork {
14261426
slip44: number;
14271427
}
14281428

1429+
export const enum LEDGER_SCHEME {
1430+
ED25519 = 0,
1431+
/**
1432+
* @deprecated This is deprecated and will be removed in future versions.
1433+
*/
1434+
SR25519 = 1,
1435+
ECDSA = 2
1436+
}
1437+
14291438
export interface MigrationLedgerNetwork extends Omit<LedgerNetwork, 'isGeneric' | 'isEthereum' | 'isDevMode' | 'icon' > {
1430-
ss58_addr_type: number
1439+
ss58_addr_type: number;
1440+
1441+
/** Signature scheme */
1442+
scheme: LEDGER_SCHEME;
14311443
}
14321444

14331445
/// Qr Sign

packages/extension-koni-ui/src/connector/Ledger/SubstrateGenericLedger.ts

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
// Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors
22
// SPDX-License-Identifier: Apache-2.0
33

4+
import { LEDGER_SCHEME } from '@subwallet/extension-base/background/KoniTypes';
45
import { wrapBytes } from '@subwallet/extension-dapp';
56
import { PolkadotGenericApp } from '@zondax/ledger-substrate';
7+
import { GenericeResponseAddress } from '@zondax/ledger-substrate/dist/common';
68

79
import { LEDGER_SUCCESS_CODE } from '@polkadot/hw-ledger/constants';
810
import { AccountOptions, LedgerAddress, LedgerSignature, LedgerVersion } from '@polkadot/hw-ledger/types';
911
import { transports } from '@polkadot/hw-ledger-transports';
10-
import { hexAddPrefix, hexStripPrefix, u8aToHex } from '@polkadot/util';
12+
import { hexAddPrefix, hexStripPrefix, u8aConcat, u8aToHex } from '@polkadot/util';
1113

1214
import { BaseLedger } from './BaseLedger';
1315

@@ -24,6 +26,8 @@ export async function loadWasm () {
2426

2527
export class SubstrateGenericLedger extends BaseLedger<PolkadotGenericApp> {
2628
protected ss58_addr_type = 42;
29+
protected scheme = LEDGER_SCHEME.ED25519;
30+
2731
getVersion (): Promise<LedgerVersion> {
2832
return this.withApp(async (app): Promise<LedgerVersion> => {
2933
const { deviceLocked: locked, major, minor, patch, testMode } = await app.getVersion();
@@ -47,42 +51,66 @@ export class SubstrateGenericLedger extends BaseLedger<PolkadotGenericApp> {
4751
getAddress (confirm?: boolean, accountOffset?: number, addressOffset?: number, accountOptions?: Partial<AccountOptions>): Promise<LedgerAddress> {
4852
return this.withApp(async (app): Promise<LedgerAddress> => {
4953
const path = this.serializePath(accountOffset, addressOffset, accountOptions);
50-
const { address, pubKey } = await this.wrapError(app.getAddressEd25519(path, this.ss58_addr_type, confirm));
54+
let result: GenericeResponseAddress;
55+
56+
if (this.scheme === LEDGER_SCHEME.ECDSA) {
57+
console.log(this.scheme, path);
58+
result = await this.wrapError(app.getAddressEcdsa(path, confirm));
59+
} else {
60+
result = await this.wrapError(app.getAddressEd25519(path, this.ss58_addr_type, confirm));
61+
}
5162

5263
return {
53-
address,
54-
publicKey: hexAddPrefix(pubKey)
64+
address: result.address,
65+
publicKey: hexAddPrefix(result.pubKey)
5566
};
5667
});
5768
}
5869

5970
async signTransaction (message: Uint8Array, metadata: Uint8Array, accountOffset?: number, addressOffset?: number, accountOptions?: Partial<AccountOptions>): Promise<LedgerSignature> {
6071
return this.withApp(async (app): Promise<LedgerSignature> => {
6172
const path = this.serializePath(accountOffset, addressOffset, accountOptions);
62-
const rs = await this.wrapError((app.signWithMetadataEd25519(path, Buffer.from(message), Buffer.from(metadata))));
6373

64-
return {
65-
signature: hexAddPrefix(u8aToHex(rs.signature))
66-
};
74+
if (this.scheme === LEDGER_SCHEME.ECDSA) {
75+
const { r, s, v } = await this.wrapError(app.signWithMetadataEcdsa(path, Buffer.from(message), Buffer.from(metadata)));
76+
77+
return {
78+
signature: hexAddPrefix(u8aToHex(u8aConcat(r, s, v)))
79+
};
80+
} else {
81+
const rs = await this.wrapError((app.signWithMetadataEd25519(path, Buffer.from(message), Buffer.from(metadata))));
82+
83+
return {
84+
signature: hexAddPrefix(u8aToHex(rs.signature))
85+
};
86+
}
6787
});
6888
}
6989

7090
async signMessage (message: Uint8Array, accountOffset?: number, addressOffset?: number, accountOptions?: Partial<AccountOptions>): Promise<LedgerSignature> {
7191
return this.withApp(async (app): Promise<LedgerSignature> => {
7292
const path = this.serializePath(accountOffset, addressOffset, accountOptions);
7393

74-
const rs = await this.wrapError(app.signRawEd25519(path, Buffer.from(wrapBytes(message))));
94+
if (this.scheme === LEDGER_SCHEME.ECDSA) {
95+
const { r, s, v } = await this.wrapError(app.signRawEcdsa(path, Buffer.from(message)));
7596

76-
const raw = hexStripPrefix(u8aToHex(rs.signature));
77-
const firstByte = raw.slice(0, 2);
78-
// Source: https://github.com/polkadot-js/common/blob/a82ebdf6f9d78791bd1f21cd3c534deee37e0840/packages/keyring/src/pair/index.ts#L29-L34
79-
const isExtraByte = firstByte === '00';
80-
// Remove first byte (signature_type) from signature
81-
const signature = isExtraByte ? hexAddPrefix(raw.slice(2)) : hexAddPrefix(raw);
82-
83-
return {
84-
signature
85-
};
97+
return {
98+
signature: hexAddPrefix(u8aToHex(u8aConcat(r, s, v)))
99+
};
100+
} else {
101+
const rs = await this.wrapError(app.signRawEd25519(path, Buffer.from(wrapBytes(message))));
102+
103+
const raw = hexStripPrefix(u8aToHex(rs.signature));
104+
const firstByte = raw.slice(0, 2);
105+
// Source: https://github.com/polkadot-js/common/blob/a82ebdf6f9d78791bd1f21cd3c534deee37e0840/packages/keyring/src/pair/index.ts#L29-L34
106+
const isExtraByte = firstByte === '00';
107+
// Remove first byte (signature_type) from signature
108+
const signature = isExtraByte ? hexAddPrefix(raw.slice(2)) : hexAddPrefix(raw);
109+
110+
return {
111+
signature
112+
};
113+
}
86114
});
87115
}
88116

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
// Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors
22
// SPDX-License-Identifier: Apache-2.0
33

4+
import { LEDGER_SCHEME } from '@subwallet/extension-base/background/KoniTypes';
45
import { LedgerTypes } from '@subwallet/extension-koni-ui/types';
56

67
import { SubstrateGenericLedger } from './SubstrateGenericLedger';
78

89
export class SubstrateMigrationLedger extends SubstrateGenericLedger {
9-
constructor (transport: LedgerTypes, slip44: number, ss58AddrType?: number) {
10+
constructor (transport: LedgerTypes, slip44: number, ss58AddrType?: number, scheme?: LEDGER_SCHEME) {
1011
super(transport, slip44);
1112

1213
if (ss58AddrType) {
1314
this.ss58_addr_type = ss58AddrType;
1415
}
16+
17+
if (scheme) {
18+
this.scheme = scheme;
19+
}
1520
}
1621
}

packages/extension-koni-ui/src/constants/ledger.ts

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
import { ChainInfoMap } from '@subwallet/chain-list';
5-
import { LedgerNetwork, MigrationLedgerNetwork } from '@subwallet/extension-base/background/KoniTypes';
5+
import { LEDGER_SCHEME, LedgerNetwork, MigrationLedgerNetwork } from '@subwallet/extension-base/background/KoniTypes';
66

77
export const SUBSTRATE_GENERIC_KEY = 'substrate_generic';
88
export const SUBSTRATE_MIGRATION_KEY = 'substrate_migration';
@@ -292,7 +292,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
292292
slug: ChainInfoMap.statemint.slug,
293293
slip44: 354,
294294
ss58_addr_type: 0,
295-
isHide: true
295+
isHide: true,
296+
scheme: LEDGER_SCHEME.ED25519
296297
},
297298
{
298299
accountName: 'Statemine',
@@ -302,7 +303,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
302303
network: 'statemine',
303304
slug: ChainInfoMap.statemine.slug,
304305
slip44: 434,
305-
ss58_addr_type: 2
306+
ss58_addr_type: 2,
307+
scheme: LEDGER_SCHEME.ED25519
306308
},
307309
{
308310
accountName: 'Kusama',
@@ -312,7 +314,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
312314
network: 'kusama',
313315
slug: ChainInfoMap.kusama.slug,
314316
slip44: 434,
315-
ss58_addr_type: 2
317+
ss58_addr_type: 2,
318+
scheme: LEDGER_SCHEME.ED25519
316319
},
317320
{
318321
accountName: 'Acala',
@@ -322,7 +325,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
322325
network: 'acala',
323326
slug: ChainInfoMap.acala.slug,
324327
slip44: 787,
325-
ss58_addr_type: 10
328+
ss58_addr_type: 10,
329+
scheme: LEDGER_SCHEME.ED25519
326330
},
327331
{
328332
accountName: 'Aleph Zero',
@@ -332,7 +336,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
332336
network: 'aleph-node',
333337
slug: ChainInfoMap.aleph.slug,
334338
slip44: 643,
335-
ss58_addr_type: 42
339+
ss58_addr_type: 42,
340+
scheme: LEDGER_SCHEME.ED25519
336341
},
337342
{
338343
accountName: 'Ajuna',
@@ -343,7 +348,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
343348
slug: ChainInfoMap.ajunaPolkadot.slug,
344349
slip44: 354,
345350
ss58_addr_type: 1328,
346-
isHide: true
351+
isHide: true,
352+
scheme: LEDGER_SCHEME.ED25519
347353
},
348354
{
349355
accountName: 'Bifrost',
@@ -353,7 +359,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
353359
network: 'ajuna',
354360
slug: ChainInfoMap.bifrost_dot.slug,
355361
slip44: 788,
356-
ss58_addr_type: 6
362+
ss58_addr_type: 6,
363+
scheme: LEDGER_SCHEME.ED25519
357364
},
358365
{
359366
accountName: 'Astar',
@@ -363,7 +370,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
363370
network: 'astar',
364371
slug: ChainInfoMap.astar.slug,
365372
slip44: 810,
366-
ss58_addr_type: 5
373+
ss58_addr_type: 5,
374+
scheme: LEDGER_SCHEME.ED25519
367375
},
368376
{
369377
accountName: 'Karura',
@@ -373,7 +381,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
373381
network: 'karura',
374382
slug: ChainInfoMap.karura.slug,
375383
slip44: 686,
376-
ss58_addr_type: 8
384+
ss58_addr_type: 8,
385+
scheme: LEDGER_SCHEME.ED25519
377386
},
378387
{
379388
accountName: 'Edgeware',
@@ -383,7 +392,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
383392
network: 'edgeware',
384393
slug: ChainInfoMap.edgeware.slug,
385394
slip44: 523,
386-
ss58_addr_type: 7
395+
ss58_addr_type: 7,
396+
scheme: LEDGER_SCHEME.ED25519
387397
},
388398
{
389399
accountName: 'XX Network',
@@ -393,7 +403,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
393403
network: 'xxnetwork',
394404
slug: ChainInfoMap.xx_network.slug,
395405
slip44: 1955,
396-
ss58_addr_type: 55
406+
ss58_addr_type: 55,
407+
scheme: LEDGER_SCHEME.ED25519
397408
},
398409
{
399410
accountName: 'Polymesh',
@@ -403,7 +414,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
403414
network: 'polymesh',
404415
slug: ChainInfoMap.polymesh.slug,
405416
slip44: 595,
406-
ss58_addr_type: 12
417+
ss58_addr_type: 12,
418+
scheme: LEDGER_SCHEME.ED25519
407419
},
408420
{
409421
accountName: 'Polkadex',
@@ -413,7 +425,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
413425
network: 'polkadex',
414426
slug: ChainInfoMap.polkadex.slug,
415427
slip44: 799,
416-
ss58_addr_type: 88
428+
ss58_addr_type: 88,
429+
scheme: LEDGER_SCHEME.ED25519
417430
},
418431
{
419432
accountName: 'Centrifuge',
@@ -423,7 +436,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
423436
network: 'centrifuge',
424437
slug: ChainInfoMap.centrifuge.slug,
425438
slip44: 747,
426-
ss58_addr_type: 36
439+
ss58_addr_type: 36,
440+
scheme: LEDGER_SCHEME.ED25519
427441
},
428442
{
429443
accountName: 'Darwinia',
@@ -434,7 +448,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
434448
slug: ChainInfoMap.darwinia2.slug,
435449
slip44: 354,
436450
ss58_addr_type: 18,
437-
isHide: true
451+
isHide: true,
452+
scheme: LEDGER_SCHEME.ED25519
438453
},
439454
{
440455
accountName: 'Hydration',
@@ -445,7 +460,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
445460
slug: ChainInfoMap.hydradx_main.slug,
446461
slip44: 354,
447462
ss58_addr_type: 63,
448-
isHide: true
463+
isHide: true,
464+
scheme: LEDGER_SCHEME.ED25519
449465
},
450466
{
451467
accountName: 'Khala',
@@ -455,7 +471,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
455471
network: 'khala',
456472
slug: ChainInfoMap.khala.slug,
457473
slip44: 434,
458-
ss58_addr_type: 30
474+
ss58_addr_type: 30,
475+
scheme: LEDGER_SCHEME.ED25519
459476
},
460477
{
461478
accountName: 'Nodle',
@@ -465,7 +482,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
465482
network: 'nodle',
466483
slug: ChainInfoMap.nodle.slug,
467484
slip44: 1003,
468-
ss58_addr_type: 37
485+
ss58_addr_type: 37,
486+
scheme: LEDGER_SCHEME.ED25519
469487
},
470488
{
471489
accountName: 'Parallel',
@@ -476,7 +494,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
476494
slug: ChainInfoMap.parallel.slug,
477495
slip44: 354,
478496
ss58_addr_type: 172,
479-
isHide: true
497+
isHide: true,
498+
scheme: LEDGER_SCHEME.ED25519
480499
},
481500
{
482501
accountName: 'Phala',
@@ -487,7 +506,8 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
487506
slug: ChainInfoMap.phala.slug,
488507
slip44: 354,
489508
ss58_addr_type: 30,
490-
isHide: true
509+
isHide: true,
510+
scheme: LEDGER_SCHEME.ED25519
491511
},
492512
{
493513
accountName: 'Pendulum',
@@ -498,7 +518,20 @@ export const PredefinedMigrationLedgerNetwork: MigrationLedgerNetwork[] = [
498518
slug: ChainInfoMap.pendulum.slug,
499519
slip44: 354,
500520
ss58_addr_type: 56,
501-
isHide: true
521+
isHide: true,
522+
scheme: LEDGER_SCHEME.ED25519
523+
},
524+
525+
{
526+
accountName: 'Mythos',
527+
appName: 'mythos',
528+
networkName: 'Mythos network',
529+
genesisHash: ChainInfoMap.mythos.substrateInfo?.genesisHash || '0xf6ee56e9c5277df5b4ce6ae9983ee88f3cbed27d31beeb98f9f84f997a1ab0b9',
530+
network: 'mythos',
531+
slug: ChainInfoMap.mythos.slug,
532+
slip44: 60,
533+
ss58_addr_type: 42,
534+
scheme: LEDGER_SCHEME.ECDSA
502535
}
503536
// {
504537
// accountName: 'Unique',

packages/extension-koni-ui/src/hooks/ledger/useLedger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ const retrieveLedger = (chainSlug: string, ledgerChains: LedgerNetwork[], migrat
7272

7373
assert(def, 'There is no known Ledger app available for this chain');
7474

75-
return new SubstrateMigrationLedger('webusb', def.slip44, def.ss58_addr_type);
75+
return new SubstrateMigrationLedger('webusb', def.slip44, def.ss58_addr_type, def.scheme);
7676
} else {
7777
return new SubstrateGenericLedger('webusb', def.slip44);
7878
}

0 commit comments

Comments
 (0)