def poll_mitosis(starting_balance, account_data, tx_stats, stub): complete = {t: False for t in tx_stats.keys()} pending = complete.keys() while not all(complete.values()): for tx_id in pending: try: resp = stub.GetBalance( mobilecoind_api_pb2.GetBalanceRequest( monitor_id=account_data.monitor_id)) if resp.balance == starting_balance and resp.account_block_height == resp.ledger_num_blocks: complete[tx_id] = True tx_stats[tx_id]['time_delta'] = time.time( ) - tx_stats[tx_id]['start'] tx_stats[tx_id][ 'block_delta'] = resp.ledger_num_blocks - tx_stats[ tx_id]['block_start'] # FIXME: don't know status currently...see below in poll tx_stats[tx_id]['status'] = TransferStatus.success except Exception as exc: print(f"Got Balance exception: {repr(exc)}") pending = [k for k in complete if not complete[k]] print("Still pending:", len(pending)) time.sleep(2) print("All accounts transfers complete") print(f"Stats: {tx_stats}") return tx_stats
def run_test(stub, amount, monitor_id, dest, max_seconds): tx_stats = {} sync_start = time.time() wait_for_accounts_sync(stub, [monitor_id, dest.monitor_id], 3) logging.info("Time to sync: %s", time.time() - sync_start) resp = stub.GetBalance( mobilecoind_api_pb2.GetBalanceRequest(monitor_id=monitor_id)) starting_balance = resp.balance logging.info("Starting balance prior to transfer: %s", starting_balance) tx_resp = stub.SendPayment( mobilecoind_api_pb2.SendPaymentRequest( sender_monitor_id=monitor_id, sender_subaddress=0, outlay_list=[ mobilecoind_api_pb2.Outlay( value=amount, receiver=dest.public_address, ) ], fee=0, tombstone=0, )) tx_stats[0] = { 'start': time.time(), 'time_delta': None, 'tombstone': tx_resp.sender_tx_receipt.tombstone, 'block_delta': None, 'status': TransferStatus.pending, 'receipt': tx_resp, } stats = poll(monitor_id, tx_stats, stub) # FIXME: Move max seconds check inside polling assert tx_stats[0]['time_delta'] < max_seconds, "Did not clear in time" assert tx_stats[0][ 'status'] == TransferStatus.success, "Transfer did not succeed" return stats
print(args) stub = connect(args.mobilecoind_host, args.mobilecoind_port) accounts = [ load_key_and_register("{}/{}".format(args.key_dir, k), stub) for k in sorted( filter(lambda x: x.endswith(".json"), os.listdir(args.key_dir))) ] monitor_ids = [a.monitor_id for a in accounts] # Go through each account and have all their friends transact to them for i, account_data in enumerate(accounts): wait_for_accounts_sync(stub, monitor_ids, 3) # Get starting balance resp = stub.GetBalance( mobilecoind_api_pb2.GetBalanceRequest(monitor_id=account_data.monitor_id)) balance = resp.balance print("Starting balance for account", i, ":", resp) # Note: due to the transaction fee, we can't assume we have enough funds # to divide equally among all our friends, so add an extra factor. amount = 10 # int(balance / (len(accounts)*10)) # Create a pool of transfers to all other accounts print("Transferring", amount, "each to", len(accounts), "accounts") # FIXME: no reason it can't also send to itself src_accounts = {a.monitor_id for a in accounts} src_accounts.remove(account_data.monitor_id) for i, src in enumerate(src_accounts):
def run_test(stub, amount, monitor_id, dest, max_seconds, token_id): tx_stats = {} sync_start = time.time() wait_for_accounts_sync(stub, [monitor_id], 3) logging.info("Time to sync: %s", time.time() - sync_start) resp = stub.GetBalance( mobilecoind_api_pb2.GetBalanceRequest(monitor_id=monitor_id, token_id=token_id)) starting_balance = resp.balance logging.info("Starting balance prior to transfer: %s", starting_balance) # Try building a payment that sends all of our balance # We may get a defragmentation error -- if we do, then submit optimization Tx outs # until we don't get that error anymore while True: try: tx_resp = stub.SendPayment( mobilecoind_api_pb2.SendPaymentRequest( sender_monitor_id=monitor_id, sender_subaddress=0, outlay_list=[ mobilecoind_api_pb2.Outlay( value=amount, receiver=dest, ) ], fee=0, tombstone=0, token_id=token_id, )) break except grpc.RpcError as e: if "insufficient funds due to utxo fragmentation" in e.details.lower(): logging.info("Got defragmentation error, building an optimization transaction") opt_tx = stub.GenerateOptimizationTx( mobilecoind_api_pb2.GenerateOptimizationTxRequest( monitor_id=monitor_id, subaddress=0, fee=0, token_id=token_id, )) tx_resp = stub.SubmitTx( mobilecoind_api_pb2.SubmitTxRequest( tx_proposal=opt_tx.tx_proposal )) tx_stats[0] = { 'start': time.time(), 'time_delta': None, 'tombstone': tx_resp.sender_tx_receipt.tombstone, 'block_delta': None, 'status': TransferStatus.pending, 'receipt': tx_resp, } stats = poll(monitor_id, tx_stats, stub) # Subtract fee from amount, so that we don't get an insufficient funds error # in the next cycle (since it costs us a fee to defragment) amount = amount - opt_tx.tx_proposal.fee else: logging.error("RPC Error encountered") raise tx_stats[0] = { 'start': time.time(), 'time_delta': None, 'tombstone': tx_resp.sender_tx_receipt.tombstone, 'block_delta': None, 'status': TransferStatus.pending, 'receipt': tx_resp, } stats = poll(monitor_id, tx_stats, stub) # FIXME: Move max seconds check inside polling assert tx_stats[0]['time_delta'] < max_seconds, "Did not clear in time" assert tx_stats[0]['status'] == TransferStatus.success, "Transfer did not succeed" return stats
for b58_pubfile in sorted(glob.glob(os.path.join(args.dest_key_dir, '*.b58pub')), key=filename_key) ] # convert from b58 to external.PublicAddress using mobilecoind helpers dest_addresses = [ stub.ParseAddressCode(mobilecoind_api_pb2.ParseAddressCodeRequest(b58_code = b58)).receiver for b58 in dest_b58addresses ] # Go through each account and have all their friends transact to them for i, (src_account, dest) in enumerate(zip(source_accounts, dest_addresses)): # If we have already done max_accounts many accounts, then stop if i == args.max_accounts: break; wait_for_accounts_sync(stub, [src_account.monitor_id], 3) # Get starting balance resp = stub.GetBalance( mobilecoind_api_pb2.GetBalanceRequest(monitor_id=src_account.monitor_id, token_id=args.token_id)) balance = resp.balance logging.info("Starting balance for account %s : %s", i, resp) amount = balance - args.fee # Create a pool of transfers to all other accounts logging.info("Transferring %s to %s", amount, dest) run_test(stub, amount, src_account.monitor_id, dest, args.max_seconds, args.token_id) logging.info("All transfers successful")