git.delta.rocks / unique-network / refs/commits / 751651bbbc76

difftreelog

Merge pull request #852 from UniqueNetwork/feat/improvements-to-identity-setter

Yaroslav Bolyukin2023-01-26parents: #acb95c7 #4b9f806.patch.diff
in: master

3 files changed

modifiedtests/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'",
modifiedtests/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));
addedtests/src/util/relayIdentitiesChecker.tsdiffbeforeafterboth

no changes