git.delta.rocks / unique-network / refs/commits / 72c7cbd1ea21

difftreelog

source

tests/src/transfer.nload.ts3.8 KiBsourcehistory
1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56import { ApiPromise } from '@polkadot/api';7import { IKeyringPair } from '@polkadot/types/types';8import privateKey from './substrate/privateKey';9import usingApi, { submitTransactionAsync } from './substrate/substrate-api';10import waitNewBlocks from './substrate/wait-new-blocks';11import { findUnusedAddresses } from './util/helpers';12import * as cluster from 'cluster';13import os from 'os';1415// Innacurate transfer fee16const FEE = 10n ** 8n;1718let counters: { [key: string]: number } = {};19function increaseCounter(name: string, amount: number) {20  if (!counters[name]) {21    counters[name] = 0;22  }23  counters[name] += amount;24}25function flushCounterToMaster() {26  if (Object.keys(counters).length === 0) {27    return;28  }29    process.send!(counters);30    counters = {};31}3233async function distributeBalance(source: IKeyringPair, api: ApiPromise, totalAmount: bigint, stages: number) {34  const accounts = [source];35  // we don't need source in output array36  const failedAccounts = [0];3738  const finalUserAmount = 2 ** stages - 1;39  accounts.push(...await findUnusedAddresses(api, finalUserAmount));40  // findUnusedAddresses produces at least 1 request per user41  increaseCounter('requests', finalUserAmount);4243  for (let stage = 0; stage < stages; stage++) {44    const usersWithBalance = 2 ** stage;45    const amount = totalAmount / (2n ** BigInt(stage)) - FEE * BigInt(stage);46    // console.log(`Stage ${stage}/${stages}, ${usersWithBalance} => ${usersWithBalance * 2} = ${amount}`);47    const txs = [];48    for (let i = 0; i < usersWithBalance; i++) {49      const newUser = accounts[i + usersWithBalance];50      // console.log(`${accounts[i].address} => ${newUser.address} = ${amountToSplit}`);51      const tx = api.tx.balances.transfer(newUser.address, amount);52      txs.push(submitTransactionAsync(accounts[i], tx).catch(() => {53        failedAccounts.push(i + usersWithBalance);54        increaseCounter('txFailed', 1);55      }));56      increaseCounter('tx', 1);57    }58    await Promise.all(txs);59  }6061  for (const account of failedAccounts.reverse()) {62    accounts.splice(account, 1);63  }64  return accounts;65}6667if (cluster.isMaster) {68  let testDone = false;69  usingApi(async (api) => {70    const prevCounters: { [key: string]: number } = {};71    while (!testDone) {72      for (const name in counters) {73        if (!(name in prevCounters)) {74          prevCounters[name] = 0;75        }76        if(counters[name] === prevCounters[name]) {77          continue;78        }79        console.log(`${name.padEnd(15)} = ${counters[name] - prevCounters[name]}`);80        prevCounters[name] = counters[name];81      }82      await waitNewBlocks(api, 1);83    }84  });85  const waiting: Promise<void>[] = [];86  console.log(`Starting ${os.cpus().length} workers`);87  usingApi(async (api) => {88    const alice = privateKey('//Alice');89    for (const id in os.cpus()) {90      const WORKER_NAME = `//LoadWorker${id}_${Date.now()}`;91      const workerAccount = privateKey(WORKER_NAME);92      const tx = api.tx.balances.transfer(workerAccount.address, 400n * 10n ** 23n);93      await submitTransactionAsync(alice, tx);9495      const worker = cluster.fork({96        WORKER_NAME,97        STAGES: id + 2,98      });99      worker.on('message', msg => {100        for (const key in msg) {101          increaseCounter(key, msg[key]);102        }103      });104      waiting.push(new Promise(res => worker.on('exit', res)));105    }106    await Promise.all(waiting);107    testDone = true;108  });109} else {110  increaseCounter('startedWorkers', 1);111  usingApi(async (api) => {112    await distributeBalance(privateKey(process.env.WORKER_NAME as string), api, 400n * 10n ** 22n, 10);113  });114  const interval = setInterval(() => {115    flushCounterToMaster();116  }, 100);117  interval.unref();118}