difftreelog
Merge pull request #852 from UniqueNetwork/feat/improvements-to-identity-setter
in: master
3 files changed
tests/package.jsondiffbeforeafterboth--- a/tests/package.json
+++ b/tests/package.json
@@ -32,6 +32,7 @@
"fix": "eslint --ext .ts,.js src/ --fix",
"setup": "ts-node ./src/util/globalSetup.ts",
"setIdentities": "ts-node ./src/util/identitySetter.ts",
+ "checkRelayIdentities": "ts-node ./src/util/relayIdentitiesChecker.ts",
"test": "yarn setup && mocha --timeout 9999999 -r ts-node/register './src/**/*.*test.ts'",
"testParallelFull": "yarn testParallel && yarn testSequential",
"testParallel": "yarn setup && mocha --parallel --timeout 9999999 -r ts-node/register './src/**/*.test.ts'",
tests/src/util/identitySetter.tsdiffbeforeafterboth--- a/tests/src/util/identitySetter.ts
+++ b/tests/src/util/identitySetter.ts
@@ -1,6 +1,9 @@
// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
// SPDX-License-Identifier: Apache-2.0
//
+// Pulls identities and sub-identities from a chain and then uses sudo to force upload them into another.
+// Only changed or previously non-existent data are inserted.
+//
// Usage: `yarn setIdentities [relay WS URL] [parachain WS URL] [sudo key]`
// Example: `yarn setIdentities wss://polkadot-rpc.dwellir.com ws://localhost:9944 escape pattern miracle train sudden cart adapt embark wedding alien lamp mesh`
@@ -12,15 +15,22 @@
const paraUrl = process.argv[3] ?? 'ws://localhost:9944';
const key = process.argv.length > 4 ? process.argv.slice(4).join(' ') : '//Alice';
-function extractAccountId(key: any): string {
+export function extractAccountId(key: any): string {
return (key as any).toHuman()[0];
}
-function extractIdentity(key: any, value: any): [string, any] {
- return [extractAccountId(key), (value as any).unwrap()];
+export function extractIdentityInfo(value: any): object {
+ const heart = (value as any).unwrap();
+ const identity = heart.toJSON();
+ identity.judgements = heart.judgements.toHuman();
+ return identity;
+}
+
+export function extractIdentity(key: any, value: any): [string, any] {
+ return [extractAccountId(key), extractIdentityInfo(value)];
}
-async function getIdentities(helper: ChainHelperBase, noneCasePredicate?: (key: any, value: any) => void) {
+export async function getIdentities(helper: ChainHelperBase, noneCasePredicate?: (key: any, value: any) => void) {
const identities: [string, any][] = [];
for(const [key, v] of await helper.getApi().query.identity.identityOf.entries()) {
const value = v as any;
@@ -33,41 +43,64 @@
return identities;
}
-function constructSubInfo(identityAccount: string, subQuery: any, supers: any[], ss58?: number): [string, any] {
+// whether the existing chain data is more important than the coming
+function isCurrentChainDataPriority(helper: ChainHelperBase, currentChainId: number | undefined, relayChainId: number) {
+ if (!currentChainId) return false;
+ // information has come from local chain, and is automatically superior
+ if (currentChainId == helper.chain.getChainProperties().ss58Format) return true;
+ // the lower the id, the more important it is (Polkadot has ss58 prefix = 0, Kusama has ss58 prefix = 2)
+ return currentChainId < relayChainId;
+}
+
+// construct an object with all data necessary for insertion from storage query results
+export function constructSubInfo(identityAccount: string, subQuery: any, supers: any[], ss58?: number): [string, any] {
const deposit = subQuery.toJSON()[0];
const subIdentities = subQuery.toHuman()[1];
subIdentities.map((sub: string) => supers.find((sup: any) => sup[0] === sub));
- // supers.find((x: any) => x[0] === subIdentities[0])![1].toHuman();
+
return [
encodeAddress(identityAccount, ss58), [
deposit,
- subIdentities.map((sub: string) => [
- encodeAddress(sub, ss58),
- supers.find((sup: any) => sup[0] === sub)![1].toJSON()[1],
- ]),
+ subIdentities.map((sub: string): [string, object] | null => {
+ const sup = supers.find((sup: any) => sup[0] === sub);
+ if (!sup) {
+ console.error(`Error: Could not find info on super for \nsub-identity account\t${sub} of \nsuper account \t\t${identityAccount}, skipping.`);
+ return null;
+ }
+ return [encodeAddress(sub, ss58), sup[1].toJSON()[1]];
+ }).filter((x: any) => x),
],
];
}
-async function getSubs(helper: ChainHelperBase) {
+export async function getSubs(helper: ChainHelperBase) {
return (await helper.getApi().query.identity.subsOf.entries()).map(([key, value]) => [extractAccountId(key), value as any]);
}
-async function getSupers(helper: ChainHelperBase) {
+export async function getSupers(helper: ChainHelperBase) {
return (await helper.getApi().query.identity.superOf.entries()).map(([key, value]) => [extractAccountId(key), value as any]);
}
// The utility for pulling identity and sub-identity data
const forceInsertIdentities = async (): Promise<void> => {
+ let relaySS58Prefix = 0;
const identitiesOnRelay: any[] = [];
const subsOnRelay: any[] = [];
const identitiesToRemove: string[] = [];
await usingPlaygrounds(async helper => {
try {
+ relaySS58Prefix = helper.chain.getChainProperties().ss58Format;
// iterate over every identity
for(const [key, value] of await getIdentities(helper, (key, _value) => identitiesToRemove.push((key as any).toHuman()[0]))) {
// if any of the judgements resulted in a good confirmed outcome, keep this identity
- if (value.toHuman().judgements.filter((x: any) => x[1] == 'Reasonable' || x[1] == 'KnownGood').length == 0) continue;
+ let knownGood = false, reasonable = false;
+ for (const [_id, judgement] of value.judgements) {
+ if (judgement == 'KnownGood') knownGood = true;
+ if (judgement == 'Reasonable') reasonable = true;
+ }
+ if (!(reasonable || knownGood)) continue;
+ // replace the registrator id with the relay chain's ss58 format
+ value.judgements = [[helper.chain.getChainProperties().ss58Format, knownGood ? 'KnownGood' : 'Reasonable']];
identitiesOnRelay.push([key, value]);
}
@@ -100,28 +133,29 @@
const ss58Format = helper.chain.getChainProperties().ss58Format;
const paraIdentities = await getIdentities(helper);
const identitiesToAdd: any[] = [];
+ const paraAccountsRegistrators: {[name: string]: number} = {};
// cross-reference every account for changes
for (const [key, value] of identitiesOnRelay) {
const encodedKey = encodeAddress(key, ss58Format);
+ // only update if the identity info does not exist or is changed
const identity = paraIdentities.find(i => i[0] === encodedKey);
if (identity) {
- // only update if the identity info does not exist or is changed
- if (JSON.stringify(value) === JSON.stringify(identity[1])) {
+ const registratorId = identity[1].judgements[0][0];
+ paraAccountsRegistrators[encodedKey] = registratorId;
+ if (isCurrentChainDataPriority(helper, registratorId, value.judgements[0][0])
+ || JSON.stringify(value.info) === JSON.stringify(identity[1].info)) {
continue;
}
}
+
identitiesToAdd.push([key, value]);
// exercise caution - in case we have an identity and the realy doesn't, it might mean one of two things:
// 1) it was deleted on the relay;
// 2) it is our own identity, we don't want to delete it.
// identitiesToRemove.push((key as any).toHuman()[0]);
}
-
- const paraSubs = await getSubs(helper);
- const supersOfSubs = await getSupers(helper);
- const subsToUpdate: any[] = [];
if (identitiesToRemove.length != 0)
await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceRemoveIdentities', [identitiesToRemove]);
@@ -132,15 +166,23 @@
+ ` and found ${identitiesToRemove.length} identities for potential removal.`
+ ` Now there are ${(await helper.getApi().query.identity.identityOf.keys()).length}.`);
+ // fill sub-identities
+ const paraSubs = await getSubs(helper);
+ const supersOfSubs = await getSupers(helper);
+ const subsToUpdate: any[] = [];
+
for (const [key, value] of subsOnRelay) {
const encodedKey = encodeAddress(key, ss58Format);
const sub = paraSubs.find(i => i[0] === encodedKey);
if (sub) {
// only update if the sub-identity info does not exist or is changed
- if (JSON.stringify(value) === JSON.stringify(constructSubInfo(sub[0], sub[1], supersOfSubs)[1])) {
+ if (isCurrentChainDataPriority(helper, paraAccountsRegistrators[encodedKey], relaySS58Prefix)
+ || JSON.stringify(value) === JSON.stringify(constructSubInfo(sub[0], sub[1], supersOfSubs)[1])) {
continue;
}
- }
+ } else if (value[1].length == 0)
+ continue;
+
subsToUpdate.push([key, value]);
}
@@ -156,4 +198,5 @@
}, paraUrl);
};
-forceInsertIdentities().catch(() => process.exit(1));
\ No newline at end of file
+if (process.argv[1] === module.filename)
+ forceInsertIdentities().catch(() => process.exit(1));
tests/src/util/relayIdentitiesChecker.tsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// SPDX-License-Identifier: Apache-2.03//4// Checks and reports the differences between identities and sub-identities on two chains.5//6// Usage: `yarn checkRelayIdentities [relay-1 WS URL] [relay-2 WS URL]`7// Example: `yarn checkRelayIdentities wss://polkadot-rpc.dwellir.com wss://kusama-rpc.dwellir.com`89import {encodeAddress} from '@polkadot/keyring';10import {usingPlaygrounds} from './index';11import {getIdentities, getSubs, getSupers, constructSubInfo} from './identitySetter';1213const relay1Url = process.argv[2] ?? 'ws://localhost:9844';14const relay2Url = process.argv[3] ?? 'ws://localhost:9844';1516async function pullIdentities(relayUrl: string): Promise<[any[], any[]]> {17 const identities: any[] = [];18 const subs: any[] = [];1920 await usingPlaygrounds(async helper => {21 try {22 // iterate over every identity23 for(const [key, value] of await getIdentities(helper)) {24 // if any of the judgements resulted in a good confirmed outcome, keep this identity25 if (value.toHuman().judgements.filter((x: any) => x[1] == 'Reasonable' || x[1] == 'KnownGood').length == 0) continue;26 identities.push([key, value]);27 }2829 const supersOfSubs = await getSupers(helper);3031 // iterate over every sub-identity32 for(const [key, value] of await getSubs(helper)) {33 // only get subs of the identities interesting to us34 if (identities.find((x: any) => x[0] == key) == -1) continue;35 subs.push(constructSubInfo(key, value, supersOfSubs));36 }37 } catch (error) {38 console.error(error);39 throw Error(`Error during fetching identities on ${relayUrl}`);40 }41 }, relayUrl);4243 return [identities, subs];44}4546// The utility for pulling identity and sub-identity data47const checkRelayIdentities = async (): Promise<void> => {48 const [identitiesOnRelay1, subIdentitiesOnRelay1] = await pullIdentities(relay1Url);49 const [identitiesOnRelay2, subIdentitiesOnRelay2] = await pullIdentities(relay2Url);5051 console.log('identities counts:\t', identitiesOnRelay1.length, identitiesOnRelay2.length);52 console.log('sub-identities counts:\t', subIdentitiesOnRelay1.length, subIdentitiesOnRelay2.length);53 console.log();5455 try {56 const matchingAddresses: string[] = [];57 const inequalIdentities: {[name: string]: [any, any]} = {};5859 for (const [key1, value1] of identitiesOnRelay1) {60 const address = encodeAddress(key1);61 const identity2 = identitiesOnRelay2.find(([key2, _value2]) => address === encodeAddress(key2));62 if (!identity2) continue;63 matchingAddresses.push(address);6465 //const [[key2, value2]] = identitiesOnRelay2.splice(index2, 1);66 const [_key2, value2] = identity2;67 if (JSON.stringify(value1.info) === JSON.stringify(value2.info)) continue;68 inequalIdentities[address] = [value1, value2];69 }7071 /*for (const [v1, v2] of Object.values(inequalIdentities)) {72 console.log(v1.toHuman().info);73 console.log();74 console.log(v2.toHuman().info);75 await new Promise(resolve => setTimeout(resolve, 4000));76 }*/7778 console.log(`Accounts with identities on both relays:\t${matchingAddresses.length}`);79 console.log(`Sub-identities with conflicting information:\t${Object.entries(inequalIdentities).length}`);80 console.log();8182 const inequalSubIdentities = [];83 let matchesFound = 0;84 for (const address of matchingAddresses) {85 const sub1 = subIdentitiesOnRelay1.find(([key1, _value1]) => address === encodeAddress(key1));86 if (!sub1) continue;87 const sub2 = subIdentitiesOnRelay2.find(([key2, _value2]) => address === encodeAddress(key2));88 if (!sub2) continue;8990 const [value1, value2] = [sub1[1], sub2[1]];91 matchesFound++;9293 if (JSON.stringify(value1[1]) === JSON.stringify(value2[1])) {94 continue;95 }96 inequalSubIdentities.push([value1, value2]);97 }9899 /*for (const [v1, v2] of inequalSubIdentities) {100 console.log(v1[1]);101 console.log();102 console.log(v2[1]);103 await new Promise(resolve => setTimeout(resolve, 300));104 }*/105 console.log(`Accounts with sub-identities on both relays:\t${matchesFound}`);106 console.log(`Of them, those with conflicting sub-identities:\t${inequalSubIdentities.length}`);107 } catch (error) {108 console.error(error);109 throw Error('Error during comparison');110 }111};112113if (process.argv[1] === module.filename)114 checkRelayIdentities().catch(() => process.exit(1));