| 
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -11,12 +11,18 @@ const { remote } = Electron;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import { snodeRpc } from './lokiRpc';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import { getRandomSnode, getRandomSnodePool, requiredSnodesForAgreement } from './snodePool';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  getRandomSnode,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  getRandomSnodePool,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  getSwarmFor,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  requiredSnodesForAgreement,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				} from './snodePool';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import { Constants } from '..';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import { getSodium, sha256 } from '../crypto';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import _, { range } from 'lodash';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import pRetry from 'p-retry';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  fromBase64ToArray,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  fromHex,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  fromHexToArray,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  fromUInt8ArrayToBase64,
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -25,6 +31,8 @@ import {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				} from '../utils/String';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import { Snode } from '../../data/data';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import { updateIsOnline } from '../../state/ducks/onion';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import { ed25519Str } from '../onions/onionPath';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import { UserUtils, StringUtils } from '../utils';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				// ONS name can have [a-zA-Z0-9_-] except that - is not allowed as start or end
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				// do not define a regex but rather create it on the fly to avoid https://stackoverflow.com/questions/3891641/regex-test-only-works-every-other-time
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -593,3 +601,163 @@ export async function retrieveNextMessages(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return [];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/**
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * Makes a post to a node to receive the timestamp info. If non-existant, returns -1
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * @param snode Snode to send request to
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * @returns timestamp of the response from snode
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				const getNetworkTime = async (snode: Snode): Promise<string | number> => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const response: any = await snodeRpc('info', {}, snode);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const body = JSON.parse(response.body);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const timestamp = body?.timestamp;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (!timestamp) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    throw new Error(`getNetworkTime returned invalid timestamp: ${timestamp}`);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  return timestamp;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				// tslint:disable-next-line: max-func-body-length
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				export const forceNetworkDeletion = async (): Promise<Array<string> | null> => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const sodium = await getSodium();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const userX25519PublicKey = UserUtils.getOurPubKeyStrFromCache();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const userED25519KeyPair = await UserUtils.getUserED25519KeyPair();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (!userED25519KeyPair) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    window.log.warn('Cannot forceNetworkDeletion, did not find user ed25519 key.');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return null;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const edKeyPriv = userED25519KeyPair.privKey;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  try {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    const maliciousSnodes = await pRetry(async () => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const userSwarm = await getSwarmFor(userX25519PublicKey);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const snodeToMakeRequestTo: Snode | undefined = _.sample(userSwarm);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const edKeyPrivBytes = fromHexToArray(edKeyPriv);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (!snodeToMakeRequestTo) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        window.log.warn('Cannot forceNetworkDeletion, without a valid swarm node.');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return null;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return pRetry(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        async () => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          const timestamp = await getNetworkTime(snodeToMakeRequestTo);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          const verificationData = StringUtils.encode(`delete_all${timestamp}`, 'utf8');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          const message = new Uint8Array(verificationData);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          const signature = sodium.crypto_sign_detached(message, edKeyPrivBytes);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          const signatureBase64 = fromUInt8ArrayToBase64(signature);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          const deleteMessageParams = {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            pubkey: userX25519PublicKey,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            pubkey_ed25519: userED25519KeyPair.pubKey.toUpperCase(),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            timestamp,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            signature: signatureBase64,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          const ret = await snodeRpc(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            'delete_all',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            deleteMessageParams,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            snodeToMakeRequestTo,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            userX25519PublicKey
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          if (!ret) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            throw new Error(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              `Empty response got for delete_all on snode ${ed25519Str(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                snodeToMakeRequestTo.pubkey_ed25519
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              )}`
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          try {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            const parsedResponse = JSON.parse(ret.body);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            const { swarm } = parsedResponse;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if (!swarm) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              throw new Error(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                `Invalid JSON swarm response got for delete_all on snode ${ed25519Str(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                  snodeToMakeRequestTo.pubkey_ed25519
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                )}, ${ret?.body}`
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            const swarmAsArray = Object.entries(swarm) as Array<Array<any>>;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if (!swarmAsArray.length) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              throw new Error(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                `Invalid JSON swarmAsArray response got for delete_all on snode ${ed25519Str(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                  snodeToMakeRequestTo.pubkey_ed25519
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                )}, ${ret?.body}`
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // results will only contains the snode pubkeys which returned invalid/empty results
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            const results: Array<string> = _.compact(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              swarmAsArray.map(snode => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                const snodePubkey = snode[0];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                const snodeJson = snode[1];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                const isFailed = snodeJson.failed || false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if (isFailed) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                  const reason = snodeJson.reason;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                  const statusCode = snodeJson.code;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                  if (reason && statusCode) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    window.log.warn(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                      `Could not delete data from ${ed25519Str(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        snodeToMakeRequestTo.pubkey_ed25519
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                      )} due to error: ${reason}: ${statusCode}`
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                  } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    window.log.warn(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                      `Could not delete data from ${ed25519Str(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        snodeToMakeRequestTo.pubkey_ed25519
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                      )}`
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                  return snodePubkey;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                const hashes = snodeJson.deleted as Array<string>;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                const signatureSnode = snodeJson.signature as string;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                // The signature format is ( PUBKEY_HEX || TIMESTAMP || DELETEDHASH[0] || ... || DELETEDHASH[N] )
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                const dataToVerify = `${userX25519PublicKey}${timestamp}${hashes.join('')}`;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                const dataToVerifyUtf8 = StringUtils.encode(dataToVerify, 'utf8');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                const isValid = sodium.crypto_sign_verify_detached(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                  fromBase64ToArray(signatureSnode),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                  new Uint8Array(dataToVerifyUtf8),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                  fromHexToArray(snodePubkey)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if (!isValid) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                  return snodePubkey;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                return null;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              })
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            return results;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          } catch (e) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            throw new Error(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              `Invalid JSON response got for delete_all on snode ${ed25519Str(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                snodeToMakeRequestTo.pubkey_ed25519
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              )}, ${ret?.body}`
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          retries: 3,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          minTimeout: 500,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          onFailedAttempt: e => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            window?.log?.warn(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              `delete_all request attempt #${e.attemptNumber} failed. ${e.retriesLeft} retries left...`
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }, {});
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return maliciousSnodes;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  } catch (e) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    window.log.warn('failed to delete everything on network:', e);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return null;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				};
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |