-
Notifications
You must be signed in to change notification settings - Fork 54
Use threads to parallelize tx_flood scenario #395
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5215d64
bfa6035
edec07c
3d836de
ca7473d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,30 +1,67 @@ | ||
| #!/usr/bin/env python3 | ||
| import threading | ||
| from random import randrange, choice | ||
| from time import sleep | ||
| from scenarios.utils import ensure_miner | ||
| from warnet.test_framework_bridge import WarnetTestFramework | ||
|
|
||
| BLOCKS = 100 | ||
| TXS = 100 | ||
|
|
||
|
|
||
| def cli_help(): | ||
| return "Generate 100 blocks with 100 TXs each" | ||
| return "Make a big transaction mess" | ||
|
|
||
|
|
||
| class TXFlood(WarnetTestFramework): | ||
| def set_test_params(self): | ||
| self.num_nodes = 1 | ||
| self.addrs = [] | ||
| self.threads = [] | ||
|
|
||
| def add_options(self, parser): | ||
| parser.add_argument( | ||
| "--interval", | ||
| dest="interval", | ||
| default=10, | ||
| type=int, | ||
| help="Number of seconds between TX generation (default 10 seconds)", | ||
| ) | ||
|
|
||
| def orders(self, node): | ||
| wallet = ensure_miner(node) | ||
| for address_type in ["legacy", "p2sh-segwit", "bech32", "bech32m"]: | ||
| self.addrs.append(wallet.getnewaddress(address_type=address_type)) | ||
| while True: | ||
| sleep(self.options.interval) | ||
| try: | ||
| bal = wallet.getbalance() | ||
| if bal < 1: | ||
| continue | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we mine a block here or top-up somehow?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm leaving the block mining to other scenarios for composability. Given the randomness of this scenario, i thought it best just to skip low balance wallets. Keep in mind that even without new blocks, other nodes will be sending you bitcoin as well. |
||
| amounts = {} | ||
| num_out = randrange(1, len(self.nodes) // 2) | ||
| for _ in range(num_out): | ||
| sats = int(float((bal / 20) / num_out) * 1e8) | ||
| amounts[choice(self.addrs)] = randrange(sats // 4, sats) / 1e8 | ||
| wallet.sendmany(dummy="", amounts=amounts) | ||
| self.log.info(f"node {node.index} sent tx with {num_out} outputs") | ||
| except Exception as e: | ||
| self.log.error(f"node {node.index} error: {e}") | ||
|
|
||
| def run_test(self): | ||
| miner = ensure_miner(self.nodes[0]) | ||
| addr = miner.getnewaddress() | ||
| self.generatetoaddress(self.nodes[0], 200, addr) | ||
| for b in range(BLOCKS): | ||
| for t in range(TXS): | ||
| txid = self.nodes[0].sendtoaddress(address=addr, amount=0.001) | ||
| self.log.info(f"sending tx {t}/{TXS}: {txid}") | ||
| block = self.generate(self.nodes[0], 1) | ||
| self.log.info(f"generating block {b}/{BLOCKS}: {block}") | ||
| self.log.info(f"Starting TX mess with {len(self.nodes)} threads") | ||
| for node in self.nodes: | ||
| sleep(1) # stagger | ||
| t = threading.Thread(target=lambda: self.orders(node)) | ||
| t.daemon = False | ||
| t.start() | ||
| self.threads.append({"thread": t, "node": node}) | ||
|
|
||
| while len(self.threads) > 0: | ||
| for thread in self.threads: | ||
| if not thread["thread"].is_alive(): | ||
| self.log.info(f"restarting thread for node {thread['node'].index}") | ||
| thread["thread"] = threading.Thread(target=lambda: self.orders(thread["node"])) | ||
| thread["thread"].daemon = False | ||
| thread["thread"].start() | ||
| sleep(30) | ||
|
|
||
| if __name__ == "__main__": | ||
| TXFlood().main() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really glad to finally see this abstracted away and only called once. been meaning to do that for ages!