diff --git a/scripts/benchmark/fund.py b/scripts/benchmark/fund.py new file mode 100644 index 00000000000..0174063b8fa --- /dev/null +++ b/scripts/benchmark/fund.py @@ -0,0 +1,71 @@ + +import re +import sys +from argparse import ArgumentParser +from pathlib import Path +from typing import List + +from multiversx_sdk import (Address, ProxyNetworkProvider, # type: ignore + Transaction, TransactionComputer, + TransactionsFactoryConfig, + TransferTransactionsFactory, UserSigner) + + +def main(cli_args: List[str]): + parser = ArgumentParser() + parser.add_argument("--proxy", required=True) + parser.add_argument("--sponsor", required=True) + parser.add_argument("--receivers", required=True) + parser.add_argument("--value", default="1000000000000000000") + args = parser.parse_args(cli_args) + + proxy_url = args.proxy + sponsor_pem_path = Path(args.sponsor) + receivers_path = Path(args.receivers) + value = int(args.value) + + network_provider = ProxyNetworkProvider(proxy_url) + transaction_computer = TransactionComputer() + chain_id = network_provider.get_network_config().chain_id + factory_config = TransactionsFactoryConfig(chain_id=chain_id) + transfers_factory = TransferTransactionsFactory(factory_config) + + sponsor_signer = UserSigner.from_pem_file(sponsor_pem_path.expanduser()) + sponsor_address = sponsor_signer.get_pubkey().to_address("erd") + sponsor_nonce = network_provider.get_account(sponsor_address).nonce + + receivers = read_receivers(receivers_path) + print(f"Found {len(receivers)} receivers") + + transactions: List[Transaction] = [] + + for receiver in receivers: + transaction = transfers_factory.create_transaction_for_native_token_transfer( + sender=sponsor_address, + receiver=receiver, + native_amount=value, + ) + + transaction.nonce = sponsor_nonce + sponsor_nonce += 1 + + bytes_for_signing = transaction_computer.compute_bytes_for_signing(transaction) + transaction.signature = sponsor_signer.sign(bytes_for_signing) + + transactions.append(transaction) + + print(f"Sending {len(transactions)} transactions") + num_txs, _ = network_provider.send_transactions(transactions) + print(f"Sent: {num_txs}") + + +def read_receivers(receivers_path: Path) -> List[Address]: + lines = receivers_path.read_text().splitlines() + pattern = re.compile(r"erd1[a-z0-9]{58}") + addresses = [match.group() for line in lines for match in pattern.finditer(line)] + addresses = list(dict.fromkeys(addresses)) + return [Address.from_bech32(address) for address in addresses] + + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/scripts/benchmark/spam.py b/scripts/benchmark/spam.py new file mode 100644 index 00000000000..561b72eea42 --- /dev/null +++ b/scripts/benchmark/spam.py @@ -0,0 +1,96 @@ + +import re +import sys +from argparse import ArgumentParser +from pathlib import Path +from typing import List + +from multiversx_sdk import (Address, ProxyNetworkProvider, # type: ignore + Transaction, TransactionComputer, + TransactionsFactoryConfig, + TransferTransactionsFactory, UserSigner) + + +class Sender: + def __init__(self, signer: UserSigner): + self.signer = signer + self.address = signer.get_pubkey().to_address("erd") + self.nonce = 0 + + def sync_nonce(self, network_provider: ProxyNetworkProvider): + self.nonce = network_provider.get_account(self.address).nonce + + +def main(cli_args: List[str]): + parser = ArgumentParser() + parser.add_argument("--proxy", required=True) + parser.add_argument("--wallets", required=True) + parser.add_argument("--indices", required=True) + parser.add_argument("--count", default=42) + args = parser.parse_args(cli_args) + + proxy_url = args.proxy + wallets_pem_path = Path(args.wallets) + indices = parse_sender_indices(args.indices) + + network_provider = ProxyNetworkProvider(proxy_url) + transaction_computer = TransactionComputer() + chain_id = network_provider.get_network_config().chain_id + factory_config = TransactionsFactoryConfig(chain_id=chain_id) + transfers_factory = TransferTransactionsFactory(factory_config) + + senders: List[Sender] = [] + + for index in indices: + signer = UserSigner.from_pem_file(wallets_pem_path, index) + senders.append(Sender(signer)) + + for sender in senders: + sender.sync_nonce(network_provider) + + transactions: List[Transaction] = [] + + for sender in senders: + for _ in range(int(args.count)): + transaction = transfers_factory.create_transaction_for_native_token_transfer( + sender=sender.address, + receiver=sender.address, + native_amount=1, + ) + + transaction.nonce = sender.nonce + sender.nonce += 1 + + bytes_for_signing = transaction_computer.compute_bytes_for_signing(transaction) + transaction.signature = sender.signer.sign(bytes_for_signing) + + transactions.append(transaction) + + print(f"Sending {len(transactions)} transactions") + num_txs, _ = network_provider.send_transactions(transactions) + print(f"Sent: {num_txs}") + + +def parse_sender_indices(indices: str) -> List[int]: + if not indices: + return [] + + # Handle specific indices + try: + parts = indices.split(",") + return [int(part) for part in parts] + except Exception: + pass + + # Handle ranges. E.g. 0:4. + try: + parts = indices.split(":") + return list(range(int(parts[0]), int(parts[1]) + 1)) + except Exception: + pass + + raise Exception(f"Cannot parse indices: {indices}") + + +if __name__ == "__main__": + main(sys.argv[1:])