Skip to content

Commit 0e632f7

Browse files
committed
derive one key per type
1 parent bc7877e commit 0e632f7

6 files changed

Lines changed: 154 additions & 93 deletions

File tree

javascript/packages/orchestrator/src/chainSpec.ts

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -165,20 +165,48 @@ export function getNodeKey(node: Node, useStash = true): GenesisNodeKey {
165165
address,
166166
address,
167167
{
168-
grandpa: ed_account.address,
169-
babe: sr_account.address,
170-
im_online: sr_account.address,
171-
parachain_validator: sr_account.address,
172-
authority_discovery: sr_account.address,
173-
para_validator: sr_account.address,
174-
para_assignment: sr_account.address,
175-
beefy: encodeAddress(ec_account.publicKey),
176-
aura: sr_account.address,
177-
nimbus: sr_account.address,
168+
grandpa: node.accounts["gran"]
169+
? node.accounts["gran"].address
170+
: ed_account.address,
171+
babe: node.accounts["babe"]
172+
? node.accounts["babe"].address
173+
: sr_account.address,
174+
im_online: node.accounts["imon"]
175+
? node.accounts["imon"].address
176+
: sr_account.address,
177+
parachain_validator: node.accounts["para"]
178+
? node.accounts["para"].address
179+
: sr_account.address,
180+
authority_discovery: node.accounts["audi"]
181+
? node.accounts["audi"].address
182+
: sr_account.address,
183+
para_validator: node.accounts["para"]
184+
? node.accounts["para"].address
185+
: sr_account.address,
186+
para_assignment: node.accounts["asgn"]
187+
? node.accounts["asgn"].address
188+
: sr_account.address,
189+
beefy: encodeAddress(
190+
node.accounts["beef"]
191+
? node.accounts["beef"].publicKey
192+
: ec_account.publicKey,
193+
),
194+
aura: node.accounts["aura"]
195+
? node.accounts["aura"].address
196+
: sr_account.address,
197+
nimbus: node.accounts["nmbs"]
198+
? node.accounts["nmbs"].address
199+
: sr_account.address,
178200
vrf: sr_account.address,
179-
mixnet: sr_account.address,
180-
bcsv: sr_account.address,
181-
ftsv: ed_account.address,
201+
mixnet: node.accounts["mixn"]
202+
? node.accounts["mixn"].address
203+
: sr_account.address,
204+
bcsv: node.accounts["bcsv"]
205+
? node.accounts["bcsv"].address
206+
: sr_account.address,
207+
ftsv: node.accounts["ftsv"]
208+
? node.accounts["ftsv"].address
209+
: ed_account.address,
182210
},
183211
];
184212

javascript/packages/orchestrator/src/configGenerator.ts

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import {
3131
UNDYING_COLLATOR_BIN,
3232
ZOMBIE_WRAPPER,
3333
} from "./constants";
34-
import { generateKeyForNode } from "./keys";
34+
import { generateKeyForNode, generateKeyTypeMap } from "./keys";
3535
import { CHAIN, decorate, whichChain } from "./chain-decorators";
3636
import { ComputedNetwork, LaunchConfig, ParachainConfig } from "./configTypes";
3737
import {
@@ -655,7 +655,15 @@ async function getCollatorNodeFromConfig(
655655
const seed = canUseSanitizedNameAsSeed(parachain.id, sanitizedName)
656656
? sanitizedName
657657
: collatorName;
658-
const accountsForNode = await decoratedKeysGenerator(seed);
658+
659+
const keystoreKeyTypes =
660+
collatorConfig.keystore_key_types || DEFAULT_KEYSTORE_KEY_TYPES;
661+
const keyMap = generateKeyTypeMap(
662+
keystoreKeyTypes,
663+
para == CHAIN.AssetHubPolkadot,
664+
);
665+
666+
const accountsForNode = await decoratedKeysGenerator(seed, keyMap);
659667

660668
const provider = networkSpec.settings.provider;
661669
const ports = await getPorts(provider, collatorConfig);
@@ -690,8 +698,8 @@ async function getCollatorNodeFromConfig(
690698
image: collatorConfig.image || DEFAULT_COLLATOR_IMAGE,
691699
command: collatorBinary,
692700
commandWithArgs: collatorConfig.command_with_args,
693-
keystoreKeyTypes:
694-
collatorConfig.keystore_key_types || DEFAULT_KEYSTORE_KEY_TYPES,
701+
keystoreKeyTypes,
702+
keyMap,
695703
args: args || [],
696704
chain,
697705
bootnodes,
@@ -765,7 +773,14 @@ async function getNodeFromConfig(
765773
const isValidator = node.validator !== false;
766774

767775
const nodeName = getUniqueName(node.name);
768-
const accountsForNode = await generateKeyForNode(nodeName);
776+
777+
const keystoreKeyTypes =
778+
node.keystore_key_types ||
779+
networkSpec.relaychain.defaultKeystoreKeyTypes ||
780+
DEFAULT_KEYSTORE_KEY_TYPES;
781+
const keyMap = generateKeyTypeMap(keystoreKeyTypes);
782+
783+
const accountsForNode = await generateKeyForNode(nodeName, keyMap);
769784

770785
const provider = networkSpec.settings.provider;
771786
const ports = await getPorts(provider, node);
@@ -787,10 +802,8 @@ async function getNodeFromConfig(
787802
invulnerable: node.invulnerable,
788803
balance: node.balance || DEFAULT_BALANCE,
789804
args: uniqueArgs,
790-
keystoreKeyTypes:
791-
node.keystore_key_types ||
792-
networkSpec.relaychain.defaultKeystoreKeyTypes ||
793-
DEFAULT_KEYSTORE_KEY_TYPES,
805+
keystoreKeyTypes,
806+
keyMap,
794807
env,
795808
bootnodes: relayChainBootnodes,
796809
telemetryUrl: networkSpec.settings?.telemetry

javascript/packages/orchestrator/src/constants.ts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -115,19 +115,20 @@ const ARGS_TO_REMOVE: { [key: string]: number } = {
115115
const TOKEN_PLACEHOLDER = /{{ZOMBIE:(.*?):(.*?)}}/gi;
116116

117117
const DEFAULT_KEYSTORE_KEY_TYPES: string[] = [
118-
"aura",
119-
"babe",
120-
"imon",
121-
"gran",
122-
"audi",
123-
"asgn",
124-
"para",
125-
"beef",
126-
"nmbs",
127-
"rand",
128-
"rate",
129-
"bcsv",
130-
"ftsv",
118+
"aura_sr",
119+
"babe_sr",
120+
"imon_sr",
121+
"gran_ed",
122+
"audi_sr",
123+
"asgn_sr",
124+
"para_sr",
125+
"beef_ec",
126+
"nmbs_sr", // Nimbus
127+
"rand_sr", // Randomness (Moonbeam)
128+
"rate_ed", // Equilibrium rate module
129+
"mixn_sr", // Mixnet
130+
"bcsv_sr", // BlockchainSrvc (StorageHub)
131+
"ftsv_ed", // FileTransferSrvc (StorageHub)
131132
];
132133

133134
export {

javascript/packages/orchestrator/src/keys.ts

Lines changed: 74 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,29 @@ export async function generateKeyFromSeed(seed: string): Promise<any> {
2020
return sr_keyring.createFromUri(`//${seed}`);
2121
}
2222

23-
export async function generateKeyForNode(nodeName?: string): Promise<any> {
23+
export async function generateKeyForNode(
24+
nodeName?: string,
25+
keyMap?: KeyTypesMap,
26+
): Promise<any> {
2427
await cryptoWaitReady();
2528

2629
const mnemonic = mnemonicGenerate();
2730
const seed = nodeName
2831
? `//${nameCase(nodeName)}`
2932
: u8aToHex(mnemonicToMiniSecret(mnemonic));
3033

34+
// Create keyrings
3135
const sr_keyring = new Keyring({ type: "sr25519" });
36+
const ed_keyring = new Keyring({ type: "ed25519" });
37+
const ec_keyring = new Keyring({ type: "ecdsa" });
38+
3239
const sr_account = sr_keyring.createFromUri(`${seed}`);
3340
const sr_stash = sr_keyring.createFromUri(`${seed}//stash`);
34-
35-
const ed_keyring = new Keyring({ type: "ed25519" });
3641
const ed_account = ed_keyring.createFromUri(`${seed}`);
37-
38-
const ec_keyring = new Keyring({ type: "ecdsa" });
3942
const ec_account = ec_keyring.createFromUri(`${seed}`);
4043

41-
// return the needed info
42-
return {
44+
// create the base info
45+
const keysForNode: any = {
4346
seed,
4447
mnemonic,
4548
sr_account: {
@@ -58,72 +61,92 @@ export async function generateKeyForNode(nodeName?: string): Promise<any> {
5861
publicKey: u8aToHex(ec_account.publicKey),
5962
},
6063
};
64+
65+
// and customize
66+
if (keyMap) {
67+
for (const [key, schema] of Object.entries(keyMap)) {
68+
const key_seed = `${seed}//${key}`;
69+
const acc =
70+
schema == "ec"
71+
? ec_keyring.createFromUri(`${key_seed}`)
72+
: schema == "ed"
73+
? ed_keyring.createFromUri(`${key_seed}`)
74+
: sr_keyring.createFromUri(`${key_seed}`);
75+
76+
keysForNode[key] = {
77+
address: acc.address,
78+
publicKey: u8aToHex(acc.publicKey),
79+
seed: key_seed,
80+
schema,
81+
};
82+
}
83+
}
84+
85+
console.log("keysForNode", keysForNode);
86+
return keysForNode;
6187
}
6288

63-
export async function generateKeystoreFiles(
64-
node: Node,
65-
path: string,
66-
isAssetHubPolkadot = false,
67-
): Promise<string[]> {
68-
const keystoreDir = `${path}/keystore`;
69-
await makeDir(keystoreDir);
89+
export interface DefaultKeystoreKeyTypes {
90+
[key: string]: string;
91+
}
7092

71-
const paths: string[] = [];
93+
// map short name with key schema (e.g "aura" -> "ed")
94+
export interface KeyTypesMap {
95+
[key: string]: string;
96+
}
7297

73-
interface DefaultKeystoreKeyTypes {
74-
[key: string]: string;
75-
}
76-
let keystore_key_types: DefaultKeystoreKeyTypes = {};
77-
78-
const default_keystore_key_types: DefaultKeystoreKeyTypes = {
79-
aura: isAssetHubPolkadot
80-
? node.accounts.ed_account.publicKey
81-
: node.accounts.sr_account.publicKey,
82-
babe: node.accounts.sr_account.publicKey,
83-
imon: node.accounts.sr_account.publicKey,
84-
gran: node.accounts.ed_account.publicKey,
85-
audi: node.accounts.sr_account.publicKey,
86-
asgn: node.accounts.sr_account.publicKey,
87-
para: node.accounts.sr_account.publicKey,
88-
beef: node.accounts.ec_account.publicKey,
89-
nmbs: node.accounts.sr_account.publicKey, // Nimbus
90-
rand: node.accounts.sr_account.publicKey, // Randomness (Moonbeam)
91-
rate: node.accounts.ed_account.publicKey, // Equilibrium rate module
92-
mixn: node.accounts.sr_account.publicKey, // Mixnet
93-
bcsv: node.accounts.sr_account.publicKey, // BlockchainSrvc (StorageHub)
94-
ftsv: node.accounts.ed_account.publicKey, // FileTransferSrvc (StorageHub)
95-
};
98+
export function generateKeyTypeMap(
99+
keystoreKeyTypes: string[] | undefined,
100+
isAssetHubPolkadot = false,
101+
): KeyTypesMap {
102+
const keyMap: KeyTypesMap = {};
96103

97104
// 2 ways keys can be defined:
98-
node.keystoreKeyTypes?.forEach((key_spec) => {
99-
// short: by only 4 letter key type with defaulted scheme e.g. "audi", if default scheme doesn't exist it is "ed"
105+
keystoreKeyTypes?.forEach((key_spec) => {
106+
// short: by only 4 letter key type with defaulted scheme e.g. "audi", default schema is "sr"
100107
if (key_spec.length === 4) {
101-
keystore_key_types[key_spec] =
102-
default_keystore_key_types[key_spec] ||
103-
node.accounts.sr_account.publicKey;
108+
keyMap[key_spec] = "sr";
104109
}
105110

106111
// long: 4 letter key type with scheme separated by underscore e.g. "audi_sr"
107112
const [key_type, key_scheme] = key_spec.split("_");
108113
if (key_type.length === 4) {
109114
if (key_scheme === "ed") {
110-
keystore_key_types[key_type] = node.accounts.ed_account.publicKey;
115+
keyMap[key_type] = "ed";
111116
} else if (key_scheme === "ec") {
112-
keystore_key_types[key_type] = node.accounts.ec_account.publicKey;
117+
keyMap[key_type] = "ec";
113118
} else if (key_scheme === "sr") {
114-
keystore_key_types[key_type] = node.accounts.sr_account.publicKey;
119+
keyMap[key_type] = "sr";
115120
}
116121
}
117122
});
118123

119-
if (Object.keys(keystore_key_types).length === 0)
120-
keystore_key_types = default_keystore_key_types;
124+
// ensure aura has the correct key
125+
keyMap["aura"] = isAssetHubPolkadot ? "ed" : "sr";
126+
127+
return keyMap;
128+
}
129+
export async function generateKeystoreFiles(
130+
node: Node,
131+
path: string,
132+
keyMap: KeyTypesMap,
133+
// isAssetHubPolkadot = false,
134+
): Promise<string[]> {
135+
const keystoreDir = `${path}/keystore`;
136+
await makeDir(keystoreDir);
137+
138+
const paths: string[] = [];
121139

122-
for (const [k, v] of Object.entries(keystore_key_types)) {
123-
const filename = Buffer.from(k).toString("hex") + v.replace(/^0x/, "");
140+
for (const [k, v] of Object.entries(keyMap)) {
141+
// check if we have the account to use by key or by schema
142+
const acc = node.accounts[k]
143+
? node.accounts[k]
144+
: node.accounts[`${v}_account`];
145+
const filename =
146+
Buffer.from(k).toString("hex") + acc.publicKey.replace(/^0x/, "");
124147
const keystoreFilePath = `${keystoreDir}/${filename}`;
125148
paths.push(keystoreFilePath);
126-
await fs.promises.writeFile(keystoreFilePath, `"${node.accounts.seed}"`);
149+
await fs.promises.writeFile(keystoreFilePath, `"${acc.seed}"`);
127150
}
128151

129152
return paths;

javascript/packages/orchestrator/src/sharedTypes.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { CHAIN } from "./chain-decorators";
2+
import { KeyTypesMap } from "./keys";
23

34
export enum SubstrateCliArgsVersion {
45
V0 = 0,
@@ -91,6 +92,7 @@ export interface Node extends NodeCommonTypes, Ports {
9192
substrateCliArgsVersion?: SubstrateCliArgsVersion;
9293
delayNetworkSettings?: DelayNetworkSettings;
9394
keystoreKeyTypes?: string[];
95+
keyMap?: KeyTypesMap;
9496
}
9597

9698
export interface Ports {

javascript/packages/orchestrator/src/spawner.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,10 @@ export const spawnNode = async (
8484

8585
await makeDir(nodeFilesPath, true);
8686

87-
const isAssetHubPolkadot =
88-
parachain &&
89-
(parachain.chain?.includes("statemint") ||
90-
parachain.chain?.includes("asset-hub-polkadot") ||
91-
parachain.chainSpecPath?.includes("statemint") ||
92-
parachain.chainSpecPath?.includes("asset-hub-polkadot"));
9387
const keystoreFiles = await generateKeystoreFiles(
9488
node,
9589
nodeFilesPath,
96-
isAssetHubPolkadot,
90+
node.keyMap!,
9791
);
9892
keystoreLocalDir = path.dirname(keystoreFiles[0]);
9993
}

0 commit comments

Comments
 (0)