git.delta.rocks / unique-network / refs/commits / 3bf184887aa7

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 privateKey from './substrate/privateKey';20import usingApi, {submitTransactionAsync} from './substrate/substrate-api';21import waitNewBlocks from './substrate/wait-new-blocks';22import {findUnusedAddresses} from './util/helpers';23import * as cluster from 'cluster';24import os from 'os';2526// Innacurate transfer fee27const FEE = 10n ** 8n;2829let counters: { [key: string]: number } = {};30function increaseCounter(name: string, amount: number) {31  if (!counters[name]) {32    counters[name] = 0;33  }34  counters[name] += amount;35}36function flushCounterToMaster() {37  if (Object.keys(counters).length === 0) {38    return;39  }40    process.send!(counters);41    counters = {};42}4344async function distributeBalance(source: IKeyringPair, api: ApiPromise, totalAmount: bigint, stages: number) {45  const accounts = [source];46  // we don't need source in output array47  const failedAccounts = [0];4849  const finalUserAmount = 2 ** stages - 1;50  accounts.push(...await findUnusedAddresses(api, finalUserAmount));51  // findUnusedAddresses produces at least 1 request per user52  increaseCounter('requests', finalUserAmount);5354  for (let stage = 0; stage < stages; stage++) {55    const usersWithBalance = 2 ** stage;56    const amount = totalAmount / (2n ** BigInt(stage)) - FEE * BigInt(stage);57    // console.log(`Stage ${stage}/${stages}, ${usersWithBalance} => ${usersWithBalance * 2} = ${amount}`);58    const txs = [];59    for (let i = 0; i < usersWithBalance; i++) {60      const newUser = accounts[i + usersWithBalance];61      // console.log(`${accounts[i].address} => ${newUser.address} = ${amountToSplit}`);62      const tx = api.tx.balances.transfer(newUser.address, amount);63      txs.push(submitTransactionAsync(accounts[i], tx).catch(() => {64        failedAccounts.push(i + usersWithBalance);65        increaseCounter('txFailed', 1);66      }));67      increaseCounter('tx', 1);68    }69    await Promise.all(txs);70  }7172  for (const account of failedAccounts.reverse()) {73    accounts.splice(account, 1);74  }75  return accounts;76}7778if (cluster.isMaster) {79  let testDone = false;80  usingApi(async (api) => {81    const prevCounters: { [key: string]: number } = {};82    while (!testDone) {83      for (const name in counters) {84        if (!(name in prevCounters)) {85          prevCounters[name] = 0;86        }87        if(counters[name] === prevCounters[name]) {88          continue;89        }90        console.log(`${name.padEnd(15)} = ${counters[name] - prevCounters[name]}`);91        prevCounters[name] = counters[name];92      }93      await waitNewBlocks(api, 1);94    }95  });96  const waiting: Promise<void>[] = [];97  console.log(`Starting ${os.cpus().length} workers`);98  usingApi(async (api) => {99    const alice = privateKey('//Alice');100    for (const id in os.cpus()) {101      const WORKER_NAME = `//LoadWorker${id}_${Date.now()}`;102      const workerAccount = privateKey(WORKER_NAME);103      const tx = api.tx.balances.transfer(workerAccount.address, 400n * 10n ** 23n);104      await submitTransactionAsync(alice, tx);105106      const worker = cluster.fork({107        WORKER_NAME,108        STAGES: id + 2,109      });110      worker.on('message', msg => {111        for (const key in msg) {112          increaseCounter(key, msg[key]);113        }114      });115      waiting.push(new Promise(res => worker.on('exit', res)));116    }117    await Promise.all(waiting);118    testDone = true;119  });120} else {121  increaseCounter('startedWorkers', 1);122  usingApi(async (api) => {123    await distributeBalance(privateKey(process.env.WORKER_NAME as string), api, 400n * 10n ** 22n, 10);124  });125  const interval = setInterval(() => {126    flushCounterToMaster();127  }, 100);128  interval.unref();129}