git.delta.rocks / unique-network / refs/commits / 4f3a2095e1df

difftreelog

source

tests/src/transfer.nload.ts4.4 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {ApiPromise} from '@polkadot/api';18import {IKeyringPair} from '@polkadot/types/types';19import usingApi, {submitTransactionAsync} from './substrate/substrate-api';20import waitNewBlocks from './substrate/wait-new-blocks';21import {findUnusedAddresses} from './util/helpers';22import * as cluster from 'cluster';23import os from 'os';2425// Innacurate transfer fee26const FEE = 10n ** 8n;2728let counters: { [key: string]: number } = {};29function increaseCounter(name: string, amount: number) {30  if (!counters[name]) {31    counters[name] = 0;32  }33  counters[name] += amount;34}35function flushCounterToMaster() {36  if (Object.keys(counters).length === 0) {37    return;38  }39    process.send!(counters);40    counters = {};41}4243async function distributeBalance(source: IKeyringPair, api: ApiPromise, totalAmount: bigint, stages: number) {44  const accounts = [source];45  // we don't need source in output array46  const failedAccounts = [0];4748  const finalUserAmount = 2 ** stages - 1;49  accounts.push(...await findUnusedAddresses(api, finalUserAmount));50  // findUnusedAddresses produces at least 1 request per user51  increaseCounter('requests', finalUserAmount);5253  for (let stage = 0; stage < stages; stage++) {54    const usersWithBalance = 2 ** stage;55    const amount = totalAmount / (2n ** BigInt(stage)) - FEE * BigInt(stage);56    // console.log(`Stage ${stage}/${stages}, ${usersWithBalance} => ${usersWithBalance * 2} = ${amount}`);57    const txs = [];58    for (let i = 0; i < usersWithBalance; i++) {59      const newUser = accounts[i + usersWithBalance];60      // console.log(`${accounts[i].address} => ${newUser.address} = ${amountToSplit}`);61      const tx = api.tx.balances.transfer(newUser.address, amount);62      txs.push(submitTransactionAsync(accounts[i], tx).catch(() => {63        failedAccounts.push(i + usersWithBalance);64        increaseCounter('txFailed', 1);65      }));66      increaseCounter('tx', 1);67    }68    await Promise.all(txs);69  }7071  for (const account of failedAccounts.reverse()) {72    accounts.splice(account, 1);73  }74  return accounts;75}7677if (cluster.isMaster) {78  let testDone = false;79  usingApi(async (api) => {80    const prevCounters: { [key: string]: number } = {};81    while (!testDone) {82      for (const name in counters) {83        if (!(name in prevCounters)) {84          prevCounters[name] = 0;85        }86        if(counters[name] === prevCounters[name]) {87          continue;88        }89        console.log(`${name.padEnd(15)} = ${counters[name] - prevCounters[name]}`);90        prevCounters[name] = counters[name];91      }92      await waitNewBlocks(api, 1);93    }94  });95  const waiting: Promise<void>[] = [];96  console.log(`Starting ${os.cpus().length} workers`);97  usingApi(async (api, privateKeyWrapper) => {98    const alice = privateKeyWrapper('//Alice');99    for (const id in os.cpus()) {100      const WORKER_NAME = `//LoadWorker${id}_${Date.now()}`;101      const workerAccount = privateKeyWrapper(WORKER_NAME);102      const tx = api.tx.balances.transfer(workerAccount.address, 400n * 10n ** 23n);103      await submitTransactionAsync(alice, tx);104105      const worker = cluster.fork({106        WORKER_NAME,107        STAGES: id + 2,108      });109      worker.on('message', msg => {110        for (const key in msg) {111          increaseCounter(key, msg[key]);112        }113      });114      waiting.push(new Promise(res => worker.on('exit', res)));115    }116    await Promise.all(waiting);117    testDone = true;118  });119} else {120  increaseCounter('startedWorkers', 1);121  usingApi(async (api, privateKeyWrapper) => {122    await distributeBalance(privateKeyWrapper(process.env.WORKER_NAME as string), api, 400n * 10n ** 22n, 10);123  });124  const interval = setInterval(() => {125    flushCounterToMaster();126  }, 100);127  interval.unref();128}