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.tsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// SPDX-License-Identifier: Apache-2.03//4// Usage: `yarn setIdentities [relay WS URL] [parachain WS URL] [sudo key]`5// Example: `yarn setIdentities wss://polkadot-rpc.dwellir.com ws://localhost:9944 escape pattern miracle train sudden cart adapt embark wedding alien lamp mesh`67import {encodeAddress} from '@polkadot/keyring';8import {usingPlaygrounds, Pallets} from './index';9import {ChainHelperBase} from './playgrounds/unique';1011const relayUrl = process.argv[2] ?? 'ws://localhost:9844';12const paraUrl = process.argv[3] ?? 'ws://localhost:9944';13const key = process.argv.length > 4 ? process.argv.slice(4).join(' ') : '//Alice';1415function extractAccountId(key: any): string {16 return (key as any).toHuman()[0];17}1819function extractIdentity(key: any, value: any): [string, any] {20 return [extractAccountId(key), (value as any).unwrap()];21}2223async function getIdentities(helper: ChainHelperBase, noneCasePredicate?: (key: any, value: any) => void) {24 const identities: [string, any][] = [];25 for(const [key, v] of await helper.getApi().query.identity.identityOf.entries()) {26 const value = v as any;27 if (value.isNone) {28 if (noneCasePredicate) noneCasePredicate(key, value);29 continue;30 }31 identities.push(extractIdentity(key, value));32 }33 return identities;34}3536function constructSubInfo(identityAccount: string, subQuery: any, supers: any[], ss58?: number): [string, any] {37 const deposit = subQuery.toJSON()[0];38 const subIdentities = subQuery.toHuman()[1];39 subIdentities.map((sub: string) => supers.find((sup: any) => sup[0] === sub));40 // supers.find((x: any) => x[0] === subIdentities[0])![1].toHuman();41 return [42 encodeAddress(identityAccount, ss58), [43 deposit,44 subIdentities.map((sub: string) => [45 encodeAddress(sub, ss58),46 supers.find((sup: any) => sup[0] === sub)![1].toJSON()[1],47 ]),48 ],49 ];50}5152async function getSubs(helper: ChainHelperBase) {53 return (await helper.getApi().query.identity.subsOf.entries()).map(([key, value]) => [extractAccountId(key), value as any]);54}5556async function getSupers(helper: ChainHelperBase) {57 return (await helper.getApi().query.identity.superOf.entries()).map(([key, value]) => [extractAccountId(key), value as any]);58}5960// The utility for pulling identity and sub-identity data61const forceInsertIdentities = async (): Promise<void> => {62 const identitiesOnRelay: any[] = [];63 const subsOnRelay: any[] = [];64 const identitiesToRemove: string[] = [];65 await usingPlaygrounds(async helper => {66 try {67 // iterate over every identity68 for(const [key, value] of await getIdentities(helper, (key, _value) => identitiesToRemove.push((key as any).toHuman()[0]))) {69 // if any of the judgements resulted in a good confirmed outcome, keep this identity70 if (value.toHuman().judgements.filter((x: any) => x[1] == 'Reasonable' || x[1] == 'KnownGood').length == 0) continue;71 identitiesOnRelay.push([key, value]);72 }7374 const sublessIdentities = [...identitiesOnRelay];75 const supersOfSubs = await getSupers(helper);7677 // iterate over every sub-identity78 for(const [key, value] of await getSubs(helper)) {79 // only get subs of the identities interesting to us80 const identityIndex = sublessIdentities.findIndex((x: any) => x[0] == key);81 if (identityIndex == -1) continue;82 sublessIdentities.splice(identityIndex, 1);83 subsOnRelay.push(constructSubInfo(key, value, supersOfSubs));84 }8586 // mark the rest of sub-identities for deletion with empty arrays87 /*for(const [account, _identity] of sublessIdentities) {88 subsOnRelay.push([account, ['0', []]]);89 }*/90 } catch (error) {91 console.error(error);92 throw Error('Error during fetching identities');93 }94 }, relayUrl);9596 await usingPlaygrounds(async (helper, privateKey) => {97 if (helper.fetchMissingPalletNames([Pallets.Identity]).length != 0) console.error('pallet-identity is not included in parachain.');98 try {99 const superuser = await privateKey(key);100 const ss58Format = helper.chain.getChainProperties().ss58Format;101 const paraIdentities = await getIdentities(helper);102 const identitiesToAdd: any[] = [];103104 // cross-reference every account for changes105 for (const [key, value] of identitiesOnRelay) {106 const encodedKey = encodeAddress(key, ss58Format);107108 const identity = paraIdentities.find(i => i[0] === encodedKey);109 if (identity) {110 // only update if the identity info does not exist or is changed111 if (JSON.stringify(value) === JSON.stringify(identity[1])) {112 continue;113 }114 }115 identitiesToAdd.push([key, value]);116 // exercise caution - in case we have an identity and the realy doesn't, it might mean one of two things:117 // 1) it was deleted on the relay;118 // 2) it is our own identity, we don't want to delete it.119 // identitiesToRemove.push((key as any).toHuman()[0]);120 }121122 const paraSubs = await getSubs(helper);123 const supersOfSubs = await getSupers(helper);124 const subsToUpdate: any[] = [];125126 if (identitiesToRemove.length != 0)127 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceRemoveIdentities', [identitiesToRemove]);128 if (identitiesToAdd.length != 0)129 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceInsertIdentities', [identitiesToAdd]);130131 console.log(`Tried to upload ${identitiesToAdd.length} identities`132 + ` and found ${identitiesToRemove.length} identities for potential removal.`133 + ` Now there are ${(awaithelper.getApi().query.identity.identityOf.keys()).length}.`);134135 for (const [key, value] of subsOnRelay) {136 const encodedKey = encodeAddress(key, ss58Format);137 const sub = paraSubs.find(i => i[0] === encodedKey);138 if (sub) {139 // only update if the sub-identity info does not exist or is changed140 if (JSON.stringify(value) === JSON.stringify(constructSubInfo(sub[0], sub[1], supersOfSubs)[1])) {141 continue;142 }143 }144 subsToUpdate.push([key, value]);145 }146147 if (subsToUpdate.length != 0)148 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceSetSubs', [subsToUpdate]);149150 console.log(`Also tried to update ${subsToUpdate.length} identities with their sub-identities.`151 + ` Now there are ${(awaithelper.getApi().query.identity.subsOf.keys()).length} identities with subs.`);152 } catch (error) {153 console.error(error);154 throw Error('Error during setting identities');155 }156 }, paraUrl);157};158159forceInsertIdentities().catch(() => process.exit(1));tests/src/util/relayIdentitiesChecker.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/util/relayIdentitiesChecker.ts
@@ -0,0 +1,114 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Checks and reports the differences between identities and sub-identities on two chains.
+//
+// Usage: `yarn checkRelayIdentities [relay-1 WS URL] [relay-2 WS URL]`
+// Example: `yarn checkRelayIdentities wss://polkadot-rpc.dwellir.com wss://kusama-rpc.dwellir.com`
+
+import {encodeAddress} from '@polkadot/keyring';
+import {usingPlaygrounds} from './index';
+import {getIdentities, getSubs, getSupers, constructSubInfo} from './identitySetter';
+
+const relay1Url = process.argv[2] ?? 'ws://localhost:9844';
+const relay2Url = process.argv[3] ?? 'ws://localhost:9844';
+
+async function pullIdentities(relayUrl: string): Promise<[any[], any[]]> {
+ const identities: any[] = [];
+ const subs: any[] = [];
+
+ await usingPlaygrounds(async helper => {
+ try {
+ // iterate over every identity
+ for(const [key, value] of await getIdentities(helper)) {
+ // 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;
+ identities.push([key, value]);
+ }
+
+ const supersOfSubs = await getSupers(helper);
+
+ // iterate over every sub-identity
+ for(const [key, value] of await getSubs(helper)) {
+ // only get subs of the identities interesting to us
+ if (identities.find((x: any) => x[0] == key) == -1) continue;
+ subs.push(constructSubInfo(key, value, supersOfSubs));
+ }
+ } catch (error) {
+ console.error(error);
+ throw Error(`Error during fetching identities on ${relayUrl}`);
+ }
+ }, relayUrl);
+
+ return [identities, subs];
+}
+
+// The utility for pulling identity and sub-identity data
+const checkRelayIdentities = async (): Promise<void> => {
+ const [identitiesOnRelay1, subIdentitiesOnRelay1] = await pullIdentities(relay1Url);
+ const [identitiesOnRelay2, subIdentitiesOnRelay2] = await pullIdentities(relay2Url);
+
+ console.log('identities counts:\t', identitiesOnRelay1.length, identitiesOnRelay2.length);
+ console.log('sub-identities counts:\t', subIdentitiesOnRelay1.length, subIdentitiesOnRelay2.length);
+ console.log();
+
+ try {
+ const matchingAddresses: string[] = [];
+ const inequalIdentities: {[name: string]: [any, any]} = {};
+
+ for (const [key1, value1] of identitiesOnRelay1) {
+ const address = encodeAddress(key1);
+ const identity2 = identitiesOnRelay2.find(([key2, _value2]) => address === encodeAddress(key2));
+ if (!identity2) continue;
+ matchingAddresses.push(address);
+
+ //const [[key2, value2]] = identitiesOnRelay2.splice(index2, 1);
+ const [_key2, value2] = identity2;
+ if (JSON.stringify(value1.info) === JSON.stringify(value2.info)) continue;
+ inequalIdentities[address] = [value1, value2];
+ }
+
+ /*for (const [v1, v2] of Object.values(inequalIdentities)) {
+ console.log(v1.toHuman().info);
+ console.log();
+ console.log(v2.toHuman().info);
+ await new Promise(resolve => setTimeout(resolve, 4000));
+ }*/
+
+ console.log(`Accounts with identities on both relays:\t${matchingAddresses.length}`);
+ console.log(`Sub-identities with conflicting information:\t${Object.entries(inequalIdentities).length}`);
+ console.log();
+
+ const inequalSubIdentities = [];
+ let matchesFound = 0;
+ for (const address of matchingAddresses) {
+ const sub1 = subIdentitiesOnRelay1.find(([key1, _value1]) => address === encodeAddress(key1));
+ if (!sub1) continue;
+ const sub2 = subIdentitiesOnRelay2.find(([key2, _value2]) => address === encodeAddress(key2));
+ if (!sub2) continue;
+
+ const [value1, value2] = [sub1[1], sub2[1]];
+ matchesFound++;
+
+ if (JSON.stringify(value1[1]) === JSON.stringify(value2[1])) {
+ continue;
+ }
+ inequalSubIdentities.push([value1, value2]);
+ }
+
+ /*for (const [v1, v2] of inequalSubIdentities) {
+ console.log(v1[1]);
+ console.log();
+ console.log(v2[1]);
+ await new Promise(resolve => setTimeout(resolve, 300));
+ }*/
+ console.log(`Accounts with sub-identities on both relays:\t${matchesFound}`);
+ console.log(`Of them, those with conflicting sub-identities:\t${inequalSubIdentities.length}`);
+ } catch (error) {
+ console.error(error);
+ throw Error('Error during comparison');
+ }
+};
+
+if (process.argv[1] === module.filename)
+ checkRelayIdentities().catch(() => process.exit(1));