Skip to content

Commit 792142d

Browse files
authored
key-migration: control key scripts (#2294)
# Goal The goal of this PR is to create scripts to be able to fetch control keys Related to #2277 # Details - added a tool to be able to fetch all msa ids and their control keys from `publicKeyToMsaId` storage - added a tool to be able to fetch all msa ids and their control keys from offchain indexer - the output is in compatible so that after sorting we can compare them for any discrepancies - added a tool to be able to fetch all token keys # Control Keys with Tokens The script should be executed close to the migration to get the latest state but for now we have these control keys with tokens on main-net. ``` "0xca94146d680192fbeff69aa6080e2f9daff8d8d238b9a76f136e35d5d3083d3c" "0x748a616c3171d049c7f331df9918e010ff27625d22c016ce6a6d3c2f24004166" "0x54fa640b48cbfdea066434189cecdd11f76c26b2499ece246fc1c69ea0e74761" "0x94c602c107c5c11a5e9fed59f65140701bb48678a10e667c32c8a03914a0ac0c" "0x5e1fb4d1e2faebbf2ffa2cb50718b57064cfd3c6b1445948f87fcef923108f4d" "0x068cbd7799b593960797a2c698f7943dd60ec8720bb28ed4019f0387444a7862" "0xaed8aa458599d23d83ba2bd13d5e9afb4aacb826e54d6876a41e01c65f72da4e" "0xae139214802b320dff4f202d37554e6899d37c5913927b9af440f783f8ec5a38" "0x58083af872b860bb71a359b92f1d2c67b9c5c970a64b5f264130e02533b0f372" "0x861b30dae9083e3bebaf427d08ec20b4b71282a987342c226cfc3bfbdeabaf61" ```
1 parent 9ecfa09 commit 792142d

File tree

6 files changed

+1128
-0
lines changed

6 files changed

+1128
-0
lines changed

tools/eth-migration/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Eth migrations tools
2+
Some scripts and tools to facilitate the key migration
3+
4+
## Get Onchain msa id and keys
5+
`npm run control-keys --silent`
6+
7+
8+
## Get Offchain Indexed msa id and keys
9+
`npm run offchain-keys --silent`
10+
11+
### Sort and Compare to see any discrepancies
12+
1. `sort -t',' -k1,1n -k2,2 onchain-keys.txt >> onchain-keys-sorted.txt`
13+
2. `sort -t',' -k1,1n -k2,2 offchain-keys.txt >> offchain-keys-sorted.txt`
14+
3. `diff onchain-keys-sorted.txt offchain-keys-sorted.txt`
15+
16+
## Get Token keys
17+
`npm run token-keys --silent`
18+
19+
### Select token keys which are also control keys
20+
`jq -c 'select(.msaId != 0)' tokens-keys.txt`
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Only way to silence PolkadotJS API warnings we don't want
2+
console.warn = () => {};
3+
4+
import { ApiPromise, WsProvider } from "@polkadot/api";
5+
6+
const SOURCE_URL = process.env["FREQUENCY_URL"] || "wss://1.rpc.frequency.xyz";
7+
const BATCH_SIZE = 1000;
8+
9+
const options = {
10+
rpc: {
11+
msa: {
12+
getKeysByMsaId: {
13+
description: 'Fetch Keys for an MSA Id',
14+
params: [
15+
{
16+
name: 'msa_id',
17+
type: 'MessageSourceId',
18+
},
19+
],
20+
type: 'Option<KeyInfoResponse>',
21+
},
22+
},
23+
},
24+
types: {
25+
MessageSourceId: 'u64',
26+
KeyInfoResponse: {
27+
msa_keys: 'Vec<AccountId>',
28+
msa_id: 'MessageSourceId',
29+
},
30+
},
31+
};
32+
33+
export async function fetchControlKeysFromState(sourceUrl) {
34+
// Connect to the state source
35+
const sourceProvider = new WsProvider(sourceUrl);
36+
const sourceApi = await ApiPromise.create({provider: sourceProvider, ...options});
37+
38+
let startKey;
39+
let result;
40+
do {
41+
result = await sourceApi.query.msa.publicKeyToMsaId.entriesPaged({
42+
args: [],
43+
pageSize: BATCH_SIZE,
44+
startKey
45+
});
46+
47+
result.forEach(([key, value]) => {
48+
if (!value.isSome) {
49+
console.error(`No MsaId for ${key.args[0].toHex()}`);
50+
} else {
51+
console.log(`${value.unwrap().toString()},${key.args[0].toHex()}`);
52+
}
53+
});
54+
55+
if (result.length > 0) {
56+
startKey = result[result.length - 1][0];
57+
}
58+
} while (result.length > 0);
59+
}
60+
61+
async function main() {
62+
try {
63+
await fetchControlKeysFromState(SOURCE_URL);
64+
process.exit(0);
65+
} catch (error) {
66+
console.error("Error:", error);
67+
process.exit(1);
68+
}
69+
}
70+
71+
main();
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Only way to silence PolkadotJS API warnings we don't want
2+
console.warn = () => {};
3+
4+
import { ApiPromise, WsProvider } from "@polkadot/api";
5+
6+
const SOURCE_URL = process.env["FREQUENCY_URL"] || "wss://1.rpc.frequency.xyz";
7+
const PROMISE_BATCH_SIZE = 500;
8+
9+
const options = {
10+
rpc: {
11+
msa: {
12+
getKeysByMsaId: {
13+
description: 'Fetch Keys for an MSA Id',
14+
params: [
15+
{
16+
name: 'msa_id',
17+
type: 'MessageSourceId',
18+
},
19+
],
20+
type: 'Option<KeyInfoResponse>',
21+
},
22+
},
23+
},
24+
types: {
25+
MessageSourceId: 'u64',
26+
KeyInfoResponse: {
27+
msa_keys: 'Vec<AccountId>',
28+
msa_id: 'MessageSourceId',
29+
},
30+
},
31+
};
32+
33+
export async function fetchControlKeysFromOffchainRpc(sourceUrl) {
34+
// Connect to the state source
35+
const sourceProvider = new WsProvider(sourceUrl);
36+
const sourceApi = await ApiPromise.create({provider: sourceProvider, ...options});
37+
38+
// Get the max schema id
39+
let msaMaxId = (await sourceApi.query.msa.currentMsaIdentifierMaximum()).toNumber();
40+
let promises = [];
41+
let id = 1;
42+
let batchNumber = 0;
43+
for (; id <= msaMaxId ; id++){
44+
promises.push(sourceApi.rpc.msa.getKeysByMsaId(id));
45+
if (id % PROMISE_BATCH_SIZE === 0 && promises.length > 0) {
46+
printRpcResults(await Promise.all(promises), batchNumber);
47+
promises = [];
48+
msaMaxId = (await sourceApi.query.msa.currentMsaIdentifierMaximum()).toNumber();
49+
batchNumber++;
50+
}
51+
}
52+
53+
if (promises.length > 0) {
54+
printRpcResults(await Promise.all(promises), batchNumber);
55+
}
56+
}
57+
58+
function printRpcResults(results, batchNumber) {
59+
let index = 0;
60+
for (const r of results) {
61+
if (!r.isSome) {
62+
console.error(`No keys for MsaId: ${(batchNumber * PROMISE_BATCH_SIZE + index +1)}!`);
63+
} else {
64+
const keys = r.unwrap();
65+
for (const key of keys.msa_keys){
66+
console.log(`${keys.msa_id},${key.toHex()}`);
67+
}
68+
}
69+
index ++;
70+
}
71+
}
72+
73+
74+
75+
async function main() {
76+
try {
77+
await fetchControlKeysFromOffchainRpc(SOURCE_URL);
78+
process.exit(0);
79+
} catch (error) {
80+
console.error("Error:", error);
81+
process.exit(1);
82+
}
83+
}
84+
85+
main();
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Only way to silence PolkadotJS API warnings we don't want
2+
console.warn = () => {};
3+
4+
import { ApiPromise, WsProvider } from "@polkadot/api";
5+
6+
const SOURCE_URL = process.env["FREQUENCY_URL"] || "wss://1.rpc.frequency.xyz";
7+
const BATCH_SIZE = 1000;
8+
9+
const options = {
10+
rpc: {
11+
msa: {
12+
getKeysByMsaId: {
13+
description: 'Fetch Keys for an MSA Id',
14+
params: [
15+
{
16+
name: 'msa_id',
17+
type: 'MessageSourceId',
18+
},
19+
],
20+
type: 'Option<KeyInfoResponse>',
21+
},
22+
},
23+
},
24+
types: {
25+
MessageSourceId: 'u64',
26+
KeyInfoResponse: {
27+
msa_keys: 'Vec<AccountId>',
28+
msa_id: 'MessageSourceId',
29+
},
30+
},
31+
};
32+
33+
// {
34+
// "publicKey": "0x488e14e049fd59b77e5821c4bb71fc9c4b8ced4c19ed27b3949e91b6274f1400",
35+
// "msaId": 1,
36+
// "values": {
37+
// "nonce": 0,
38+
// "consumers": 0,
39+
// "providers": 1,
40+
// "sufficients": 0,
41+
// "data": {
42+
// "free": 5000000000,
43+
// "reserved": 0,
44+
// "frozen": 0,
45+
// "flags": "0x80000000000000000000000000000000"
46+
// }
47+
// }
48+
// }
49+
export async function fetchTokenKeysFromState(sourceUrl) {
50+
// Connect to the state source
51+
const sourceProvider = new WsProvider(sourceUrl);
52+
const sourceApi = await ApiPromise.create({provider: sourceProvider, ...options});
53+
54+
let result;
55+
do {
56+
result = await sourceApi.query.system.account.entriesPaged({ args: [], pageSize: BATCH_SIZE, startKey: result && result[result.length - 1][0] });
57+
let msaResult = await sourceApi.query.msa.publicKeyToMsaId.multi(result.map(([key, _]) => key.args[0]));
58+
result.forEach(([key, account], index) => {
59+
const obj = {
60+
publicKey: key.args[0].toHex(),
61+
msaId: msaResult[index].isSome ? msaResult[index].unwrap().toNumber() : 0,
62+
values: account,
63+
}
64+
console.log(`${JSON.stringify(obj)}`);
65+
});
66+
} while (result.length === BATCH_SIZE);
67+
}
68+
69+
async function main() {
70+
try {
71+
await fetchTokenKeysFromState(SOURCE_URL);
72+
process.exit(0);
73+
} catch (error) {
74+
console.error("Error:", error);
75+
process.exit(1);
76+
}
77+
}
78+
79+
main();

0 commit comments

Comments
 (0)