def setup(request): request.addfinalizer(teardown) global bitcoin_conf, bitcoin_path, bitcoin_rpcpassword, bitcoin_rpcusername bitcoin_path = request.config.getoption("--btcroot") bitcoin_conf = request.config.getoption("--btcconf") bitcoin_rpcpassword = request.config.getoption("--btcpwd") bitcoin_rpcusername = request.config.getoption("--btcuser") #start up miniircd #minor bug in miniircd (seems); need *full* unqualified path for motd file cwd = os.getcwd() n_irc = request.config.getoption("--nirc") global miniircd_procs for i in range(n_irc): miniircd_proc = local_command([ "./miniircd/miniircd", "--ports=" + str(6667 + i), "--motd=" + cwd + "/miniircd/testmotd" ], bg=True) miniircd_procs.append(miniircd_proc) #start up regtest blockchain btc_proc = subprocess.call([ bitcoin_path + "bitcoind", "-regtest", "-daemon", "-conf=" + bitcoin_conf ]) time.sleep(3) #generate blocks local_command([ bitcoin_path + "bitcoin-cli", "-regtest", "-rpcuser="******"-rpcpassword="******"generate", "101" ])
def setup(request): request.addfinalizer(teardown) global bitcoin_conf, bitcoin_path, bitcoin_rpcpassword, bitcoin_rpcusername bitcoin_path = request.config.getoption("--btcroot") bitcoin_conf = request.config.getoption("--btcconf") bitcoin_rpcpassword = request.config.getoption("--btcpwd") bitcoin_rpcusername = request.config.getoption("--btcuser") #start up miniircd #minor bug in miniircd (seems); need *full* unqualified path for motd file cwd = os.getcwd() n_irc = request.config.getoption("--nirc") global miniircd_procs for i in range(n_irc): miniircd_proc = local_command( ["./miniircd/miniircd", "--ports=" + str(6667+i), "--motd=" + cwd + "/miniircd/testmotd"], bg=True) miniircd_procs.append(miniircd_proc) #start up regtest blockchain btc_proc = subprocess.call([bitcoin_path + "bitcoind", "-regtest", "-daemon", "-conf=" + bitcoin_conf]) time.sleep(3) #generate blocks local_command([bitcoin_path + "bitcoin-cli", "-regtest", "-rpcuser="******"-rpcpassword="******"generate", "101"])
def run_send(self, bad=False): yigen_procs = [] if bad: i = 2 else: i = 0 ygp = local_command([python_cmd,yg_cmd,\ str(self.wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) #run a single sendpayment call amt = 100000000 #in satoshis dest_address = btc.privkey_to_address(os.urandom(32), get_p2pk_vbyte()) try: sp_proc = local_command([ python_cmd, 'sendpayment.py', '--yes', '-N', '1', self.wallets[1]['seed'], str(amt), dest_address ]) except subprocess.CalledProcessError, e: for ygp in yigen_procs: ygp.kill() print e.returncode print e.message raise
def run_send(self, bad=False): yigen_procs = [] if bad: i = 2 else: i = 0 ygp = local_command([python_cmd,yg_cmd,\ str(self.wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) #run a single sendpayment call amt = 100000000 #in satoshis dest_address = btc.privkey_to_address(os.urandom(32), get_p2pk_vbyte()) try: sp_proc = local_command([python_cmd, 'sendpayment.py', '--yes', '-N', '1', self.wallets[1]['seed'], str( amt), dest_address]) except subprocess.CalledProcessError, e: for ygp in yigen_procs: ygp.kill() print e.returncode print e.message raise
def teardown(): #didn't find a stop command in miniircd, so just kill global miniircd_proc miniircd_proc.kill() #shut down bitcoin and remove the regtest dir local_command([bitcoin_path + "bitcoin-cli", "-regtest", "-rpcuser="******"-rpcpassword="******"stop"])
def run_tumble(self, amt): yigen_procs = [] for i in range(6): ygp = local_command([python_cmd, yg_cmd,\ str(self.wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) #start a tumbler amt = amt * 1e8 #in satoshis #send to any old address dest_address = btc.privkey_to_address(os.urandom(32), get_p2pk_vbyte()) try: print 'taker seed: '+self.wallets[6]['seed'] while True: print 'hello' time.sleep(80) except subprocess.CalledProcessError, e: for ygp in yigen_procs: ygp.kill() print e.returncode print e.message raise
def run_tumble(self, amt): yigen_procs = [] for i in range(6): ygp = local_command([python_cmd, yg_cmd,\ str(self.wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) #start a tumbler amt = amt * 1e8 #in satoshis #send to any old address dest_address = btc.privkey_to_address(os.urandom(32), get_p2pk_vbyte()) try: print 'taker seed: ' + self.wallets[6]['seed'] while True: print 'hello' time.sleep(80) except subprocess.CalledProcessError, e: for ygp in yigen_procs: ygp.kill() print e.returncode print e.message raise
def test_junk_messages(setup_messaging): #start a yg bot just to receive messages wallets = make_wallets(1, wallet_structures=[[1,0,0,0,0]], mean_amt=1) wallet = wallets[0]['wallet'] ygp = local_command([python_cmd, yg_cmd,\ str(wallets[0]['seed'])], bg=True) #time.sleep(90) #start a raw IRCMessageChannel instance in a thread; #then call send_* on it with various errant messages mc = DummyMC("irc_ping_test") mc.register_orderbookwatch_callbacks(on_order_seen=on_order_seen) mc.register_taker_callbacks(on_pubkey=on_pubkey) RawIRCThread(mc).start() time.sleep(1) mc._IRCMessageChannel__pubmsg("!orderbook") time.sleep(1) mc._IRCMessageChannel__pubmsg("!orderbook!orderbook") time.sleep(1) mc._IRCMessageChannel__pubmsg("junk and crap"*20) time.sleep(5) #try: with pytest.raises(CJPeerError) as e_info: mc.send_error(yg_name, "fly you fools!") #except CJPeerError: # print "CJPeerError raised" # pass time.sleep(5) mc.shutdown() ygp.send_signal(signal.SIGINT) ygp.wait()
def test_start_ygs(setup_ygrunner, num_ygs, wallet_structures, mean_amt): """Set up some wallets, for the ygs and 1 sp. Then start the ygs in background and publish the seed of the sp wallet for easy import into -qt """ wallets = make_wallets(num_ygs + 1, wallet_structures=wallet_structures, mean_amt=mean_amt) #the sendpayment bot uses the last wallet in the list wallet = wallets[num_ygs]['wallet'] print "Seed : " + wallets[num_ygs]['seed'] #useful to see the utxos on screen sometimes sync_wallet(wallet) print wallet.unspent yigen_procs = [] for i in range(num_ygs): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) try: while True: time.sleep(20) print 'waiting' finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait()
def test_junk_messages(setup_messaging): #start a yg bot just to receive messages wallets = make_wallets(1, wallet_structures=[[1, 0, 0, 0, 0]], mean_amt=1) wallet = wallets[0]['wallet'] ygp = local_command([python_cmd, yg_cmd,\ str(wallets[0]['seed'])], bg=True) #time.sleep(90) #start a raw IRCMessageChannel instance in a thread; #then call send_* on it with various errant messages mc = DummyMC("irc_ping_test") mc.register_orderbookwatch_callbacks(on_order_seen=on_order_seen) mc.register_taker_callbacks(on_pubkey=on_pubkey) RawIRCThread(mc).start() time.sleep(1) mc._IRCMessageChannel__pubmsg("!orderbook") time.sleep(1) mc._IRCMessageChannel__pubmsg("!orderbook!orderbook") time.sleep(1) mc._IRCMessageChannel__pubmsg("junk and crap" * 20) time.sleep(5) #try: with pytest.raises(CJPeerError) as e_info: mc.send_error(yg_name, "fly you fools!") #except CJPeerError: # print "CJPeerError raised" # pass time.sleep(5) mc.shutdown() ygp.send_signal(signal.SIGINT) ygp.wait()
def test_junk_messages(setup_messaging): #start a yg bot just to receive messages wallets = make_wallets(1, wallet_structures=[[1, 0, 0, 0, 0]], mean_amt=1) wallet = wallets[0]['wallet'] ygp = local_command([python_cmd, yg_cmd,\ str(wallets[0]['seed'])], bg=True) #time.sleep(90) #start a raw IRCMessageChannel instance in a thread; #then call send_* on it with various errant messages mc = DummyMC("irc_ping_test") mc.register_orderbookwatch_callbacks(on_order_seen=on_order_seen) mc.register_taker_callbacks(on_pubkey=on_pubkey) RawIRCThread(mc).start() time.sleep(1) mc.request_orderbook() time.sleep(1) #now try directly mc.pubmsg("!orderbook") time.sleep(1) #should be ignored; can we check? mc.pubmsg("!orderbook!orderbook") time.sleep(1) #assuming MAX_PRIVMSG_LEN is not something crazy #big like 550, this should fail with pytest.raises(AssertionError) as e_info: mc.pubmsg("junk and crap" * 40) time.sleep(1) #assuming MAX_PRIVMSG_LEN is not something crazy #small like 180, this should succeed mc.pubmsg("junk and crap" * 15) time.sleep(2) #try a long order announcement in public #because we don't want to build a real orderbook, #call the underlying IRC announce function. #TODO: how to test that the sent format was correct? mc._announce_orders(["!abc def gh 0001"] * 30, None) time.sleep(5) #send a fill with an invalid pubkey to the existing yg; #this should trigger a NaclError but should NOT kill it. mc._IRCMessageChannel__privmsg(yg_name, "fill", "0 10000000 abcdef") time.sleep(1) #try: with pytest.raises(CJPeerError) as e_info: mc.send_error(yg_name, "fly you fools!") #except CJPeerError: # print "CJPeerError raised" # pass time.sleep(5) mc.shutdown() ygp.send_signal(signal.SIGINT) ygp.wait()
def run_simple_send(self, n, m): #start yield generator with wallet1 yigen_proc = local_command( [python_cmd, yg_cmd, str(self.wallets[0]['seed'])], bg=True) #A significant delay is needed to wait for the yield generator to sync its wallet time.sleep(20) #run a single sendpayment call with wallet2 amt = n * 100000000 #in satoshis dest_address = btc.privkey_to_address(os.urandom(32), get_p2pk_vbyte()) try: for i in range(m): sp_proc = local_command([python_cmd,'sendpayment.py','--yes','-N','1', self.wallets[1]['seed'],\ str(amt), dest_address]) except subprocess.CalledProcessError, e: if yigen_proc: yigen_proc.terminate() print e.returncode print e.message raise
def run_sweep(self): #currently broken due to flooding; to make it work #change the 60 loop for the bad wallet to 20 yigen_procs = [] ygp = local_command([python_cmd,yg_cmd,\ str(self.wallets[3]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) dest_address = btc.privkey_to_address(os.urandom(32), get_p2pk_vbyte()) try: sp_proc = local_command([python_cmd, 'sendpayment.py', '--yes', '-N', '1', self.wallets[2][ 'seed'], '0', dest_address]) except subprocess.CalledProcessError, e: for ygp in yigen_procs: ygp.kill() print e.returncode print e.message raise
def run_sweep(self): #currently broken due to flooding; to make it work #change the 60 loop for the bad wallet to 20 yigen_procs = [] ygp = local_command([python_cmd,yg_cmd,\ str(self.wallets[3]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) dest_address = btc.privkey_to_address(os.urandom(32), get_p2pk_vbyte()) try: sp_proc = local_command([ python_cmd, 'sendpayment.py', '--yes', '-N', '1', self.wallets[2]['seed'], '0', dest_address ]) except subprocess.CalledProcessError, e: for ygp in yigen_procs: ygp.kill() print e.returncode print e.message raise
def run_tumble(self, amt): yigen_procs = [] for i in range(6): ygp = local_command([python_cmd, yg_cmd,\ str(self.wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(60) #start a tumbler amt = amt * 1e8 #in satoshis #send to any old address dest_address = btc.privkey_to_address(os.urandom(32), get_p2pk_vbyte()) try: #default mixdepth source is zero, so will take coins from m 0. #see tumbler.py --h for details expected = ['tumble with these tx'] test_in = ['y'] p = pexpect.spawn(python_cmd, ['tumbler.py', '-N', '2', '0', '-a', '0', '-M', '5', '-w', '10', '-l', '0.2', '-s', '1000000', '-q', '5', self.wallets[6]['seed'], dest_address]) interact(p, test_in, expected) p.expect(pexpect.EOF, timeout=100000) p.close() if p.exitstatus != 0: print 'failed due to exit status: ' + str(p.exitstatus) return False except subprocess.CalledProcessError, e: for ygp in yigen_procs: ygp.kill() print e.returncode print e.message raise
def test_external_commitment_used(setup_podle): tries = jm_single().config.getint("POLICY", "taker_utxo_retries") #Don't want to wait too long, but must account for possible #throttling with !auth jm_single().maker_timeout_sec = 12 amount = 50000000 wallets = make_wallets(3, wallet_structures=[[1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 1, 0, 0, 0]], mean_amt=1) #the sendpayment bot uses the last wallet in the list wallet = wallets[2]['wallet'] yigen_procs = [] for i in range(2): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(10) destaddr = btc.privkey_to_address(binascii.hexlify(os.urandom(32)), magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg log.debug('starting sendpayment') jm_single().bc_interface.sync_wallet(wallet) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()] mcc = MessageChannelCollection(mcs) #add all utxo in mixdepth 0 to 'used' list of commitments, utxos = wallet.get_utxos_by_mixdepth()[0] for u, addrval in utxos.iteritems(): priv = wallet.get_key_from_addr(addrval['address']) podle = btc.PoDLE(u, priv) for i in range(tries): #loop because we want to use up all retries of this utxo commitment = podle.generate_podle(i)['commit'] btc.update_commitments(commitment=commitment) #create a new utxo, notionally from an external source; to make life a little #easier we'll pay to another mixdepth, but this is OK because #taker does not source from here currently, only from the utxos chosen #for the transaction, not the whole wallet. So we can treat it as if #external (don't access its privkey). utxos = wallet.get_utxos_by_mixdepth()[1] ecs = {} for u, addrval in utxos.iteritems(): priv = wallet.get_key_from_addr(addrval['address']) ecs[u] = {} ecs[u]['reveal'] = {} for j in range(tries): P, P2, s, e, commit = generate_single_podle_sig( binascii.unhexlify(priv), j) if 'P' not in ecs[u]: ecs[u]['P'] = P ecs[u]['reveal'][j] = {'P2': P2, 's': s, 'e': e} btc.update_commitments(external_to_add=ecs) #Now the conditions described above hold. We do a normal single #sendpayment. taker = sendpayment.SendPayment(mcc, wallet, destaddr, amount, 2, 5000, 3, 0, True, weighted_order_choose) try: log.debug('starting message channels') mcc.run() finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] assert received == amount, "sendpayment failed - coins not arrived, " +\ "received: " + str(received) #Cleanup - remove the external commitments added btc.update_commitments(external_to_remove=ecs)
def test_sendpayment(setup_regtest, num_ygs, wallet_structures, mean_amt, mixdepth, sending_amt, ygcfs, fails, donate, rpcwallet): """Test of sendpayment code, with yield generators in background. """ log = get_log() makercount = num_ygs answeryes = True txfee = 5000 waittime = 5 amount = sending_amt wallets = make_wallets(makercount + 1, wallet_structures=wallet_structures, mean_amt=mean_amt) #the sendpayment bot uses the last wallet in the list if not rpcwallet: wallet = wallets[makercount]['wallet'] else: wallet = BitcoinCoreWallet(fromaccount="") yigen_procs = [] if ygcfs: assert makercount == len(ygcfs) for i in range(makercount): if ygcfs: #back up default config, overwrite before start os.rename("joinmarket.cfg", "joinmarket.cfg.bak") shutil.copy2(ygcfs[i], "joinmarket.cfg") ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) if ygcfs: #Note: in case of using multiple configs, #the starting config is what is used by sendpayment os.rename("joinmarket.cfg.bak", "joinmarket.cfg") #A significant delay is needed to wait for the yield generators to sync time.sleep(20) if donate: destaddr = None else: destaddr = btc.privkey_to_address( os.urandom(32), from_hex=False, magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg #TODO paramatetrize this as a test variable chooseOrdersFunc = weighted_order_choose log.debug('starting sendpayment') sync_wallet(wallet) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()] mcc = MessageChannelCollection(mcs) #hack fix for #356 if multiple orders per counterparty #removed for now. #if amount==0: makercount=2 taker = sendpayment.SendPayment(mcc, wallet, destaddr, amount, makercount-2, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc) try: log.debug('starting message channels') mcc.run(failures=fails) finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) if not donate: received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] if amount != 0: assert received == amount, "sendpayment failed - coins not arrived, " +\ "received: " + str(received) #TODO: how to check success for sweep case? else: assert received != 0
def test_sendpayment(setup_regtest, num_ygs, wallet_structures, mean_amt, mixdepth, sending_amt): """Test of sendpayment code, with yield generators in background. """ log = get_log() makercount = num_ygs answeryes = True txfee = 5000 waittime = 5 amount = sending_amt wallets = make_wallets(makercount + 1, wallet_structures=wallet_structures, mean_amt=mean_amt) #the sendpayment bot uses the last wallet in the list wallet = wallets[makercount]['wallet'] yigen_procs = [] for i in range(makercount): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) if btc.secp_present: destaddr = btc.privkey_to_address(os.urandom(32), from_hex=False, magicbyte=get_p2pk_vbyte()) else: destaddr = btc.privkey_to_address(os.urandom(32), magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg #TODO paramatetrize this as a test variable chooseOrdersFunc = weighted_order_choose jm_single().nickname = random_nick() log.debug('starting sendpayment') jm_single().bc_interface.sync_wallet(wallet) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 irc = IRCMessageChannel(jm_single().nickname) taker = sendpayment.SendPayment(irc, wallet, destaddr, amount, makercount, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc) try: log.debug('starting irc') irc.run() finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] if amount != 0: assert received == amount, "sendpayment failed - coins not arrived, " +\ "received: " + str(received) #TODO: how to check success for sweep case? else: assert received != 0
def test_tumbler(setup_tumbler, num_ygs, wallet_structures, mean_amt, sdev_amt, yg_excess): """Test of tumbler code, with yield generators in background. """ log = get_log() options = Options() options.mixdepthsrc = 0 options.mixdepthcount = 4 options.minmakercount = 2 options.makercountrange = (num_ygs, 0) options.maxcjfee = (0.01, 10000) options.txfee = 5000 options.addrcount = 3 options.donateamount = 0.5 options.txcountparams = (4, 1) options.mintxcount = 1 options.amountpower = 100 options.timelambda = 0.2 options.waittime = 10 options.mincjamount = 1000000 options.liquiditywait = 5 options.maxbroadcasts = 4 options.maxcreatetx = 9 options = vars(options) wallets = make_wallets(num_ygs + 1, wallet_structures=wallet_structures, mean_amt=mean_amt, sdev_amt=sdev_amt) #need to make sure that at least some ygs have substantially #more coins for last stages of sweep/spend in tumble: for i in range(num_ygs): jm_single().bc_interface.grab_coins( wallets[i]['wallet'].get_external_addr(0), yg_excess) #the tumbler bot uses the last wallet in the list wallet = wallets[num_ygs]['wallet'] yigen_procs = [] for i in range(num_ygs): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) destaddrs = [] for i in range(3): if btc.secp_present: destaddr = btc.privkey_to_address( os.urandom(32), from_hex=False, magicbyte=get_p2pk_vbyte()) else: destaddr = btc.privkey_to_address( os.urandom(32), magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg destaddrs.append(destaddr) tx_list = tumbler.generate_tumbler_tx(destaddrs, options) pprint(tx_list) if options['addrcount'] + 1 > options['mixdepthcount']: print('not enough mixing depths to pay to all destination addresses, ' 'increasing mixdepthcount') options['mixdepthcount'] = options['addrcount'] + 1 tx_list2 = copy.deepcopy(tx_list) tx_dict = {} for tx in tx_list2: srcmixdepth = tx['srcmixdepth'] tx.pop('srcmixdepth') if srcmixdepth not in tx_dict: tx_dict[srcmixdepth] = [] tx_dict[srcmixdepth].append(tx) dbg_tx_list = [] for srcmixdepth, txlist in tx_dict.iteritems(): dbg_tx_list.append({'srcmixdepth': srcmixdepth, 'tx': txlist}) log.debug('tumbler transaction list') pprint(dbg_tx_list) total_wait = sum([tx['wait'] for tx in tx_list]) print('creates ' + str(len(tx_list)) + ' transactions in total') print('waits in total for ' + str(len(tx_list)) + ' blocks and ' + str( total_wait) + ' minutes') total_block_and_wait = len(tx_list) * 10 + total_wait print('estimated time taken ' + str(total_block_and_wait) + ' minutes or ' + str(round(total_block_and_wait / 60.0, 2)) + ' hours') jm_single().nickname = random_nick() log.debug('starting tumbler') jm_single().bc_interface.sync_wallet(wallet) jm_single().bc_interface.pushtx_failure_prob = 0.4 irc = IRCMessageChannel(jm_single().nickname) tumbler_bot = tumbler.Tumbler(irc, wallet, tx_list, options) try: log.debug('starting irc') irc.run() except: log.debug('CRASHING, DUMPING EVERYTHING') debug_dump_object(wallet, ['addr_cache', 'keys', 'wallet_name', 'seed']) debug_dump_object(tumbler_bot) import traceback log.debug(traceback.format_exc()) finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] assert received != 0 """TODO: figure out a sensible assertion check for the destination
def test_tx_commitments_used(setup_podle, consume_tx, age_required, cmt_age): tries = jm_single().config.getint("POLICY","taker_utxo_retries") #remember and reset at the end taker_utxo_age = jm_single().config.getint("POLICY", "taker_utxo_age") jm_single().config.set("POLICY", "taker_utxo_age", str(age_required)) #Don't want to wait too long, but must account for possible #throttling with !auth jm_single().maker_timeout_sec = 12 amount = 0 wallets = make_wallets(3, wallet_structures=[[1,2,1,0,0],[1,2,0,0,0],[2,2,1,0,0]], mean_amt=1) #the sendpayment bot uses the last wallet in the list wallet = wallets[2]['wallet'] #make_wallets calls grab_coins which mines 1 block per individual payout, #so the age of the coins depends on where they are in that list. The sendpayment #is the last wallet in the list, and we choose the non-tx utxos which are in #mixdepth 1 and 2 (2 and 1 utxos in each respectively). We filter for those #that have sufficient age, so to get 1 which is old enough, it will be the oldest, #which will have an age of 2 + 1 (the first utxo spent to that wallet). #So if we need an age of 6, we need to mine 3 more blocks. blocks_reqd = cmt_age - 3 jm_single().bc_interface.tick_forward_chain(blocks_reqd) yigen_procs = [] for i in range(2): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) time.sleep(5) destaddr = btc.privkey_to_address( binascii.hexlify(os.urandom(32)), magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg log.debug('starting sendpayment') jm_single().bc_interface.sync_wallet(wallet) log.debug("Here is the whole wallet: \n" + str(wallet.unspent)) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()] mcc = MessageChannelCollection(mcs) if consume_tx: #add all utxo in mixdepth 0 to 'used' list of commitments, utxos = wallet.get_utxos_by_mixdepth()[0] for u, addrval in utxos.iteritems(): priv = wallet.get_key_from_addr(addrval['address']) podle = btc.PoDLE(u, priv) for i in range(tries): #loop because we want to use up all retries of this utxo commitment = podle.generate_podle(i)['commit'] btc.update_commitments(commitment=commitment) #Now test a sendpayment from mixdepth 0 with all the depth 0 utxos #used up, so that the other utxos in the wallet get used. taker = sendpayment.SendPayment(mcc, wallet, destaddr, amount, 2, 5000, 3, 0, True, weighted_order_choose) try: log.debug('starting message channels') mcc.run() finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] jm_single().config.set("POLICY", "taker_utxo_age", str(taker_utxo_age)) if cmt_age < age_required: assert received == 0, "Coins arrived but shouldn't" else: assert received != 0, "sendpayment failed - coins not arrived, " +\ "received: " + str(received)
def test_external_commitment_used(setup_podle): tries = jm_single().config.getint("POLICY","taker_utxo_retries") #Don't want to wait too long, but must account for possible #throttling with !auth jm_single().maker_timeout_sec = 12 amount = 50000000 wallets = make_wallets(3, wallet_structures=[[1,0,0,0,0],[1,0,0,0,0],[1,1,0,0,0]], mean_amt=1) #the sendpayment bot uses the last wallet in the list wallet = wallets[2]['wallet'] yigen_procs = [] for i in range(2): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(10) destaddr = btc.privkey_to_address( binascii.hexlify(os.urandom(32)), magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg log.debug('starting sendpayment') jm_single().bc_interface.sync_wallet(wallet) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()] mcc = MessageChannelCollection(mcs) #add all utxo in mixdepth 0 to 'used' list of commitments, utxos = wallet.get_utxos_by_mixdepth()[0] for u, addrval in utxos.iteritems(): priv = wallet.get_key_from_addr(addrval['address']) podle = btc.PoDLE(u, priv) for i in range(tries): #loop because we want to use up all retries of this utxo commitment = podle.generate_podle(i)['commit'] btc.update_commitments(commitment=commitment) #create a new utxo, notionally from an external source; to make life a little #easier we'll pay to another mixdepth, but this is OK because #taker does not source from here currently, only from the utxos chosen #for the transaction, not the whole wallet. So we can treat it as if #external (don't access its privkey). utxos = wallet.get_utxos_by_mixdepth()[1] ecs = {} for u, addrval in utxos.iteritems(): priv = wallet.get_key_from_addr(addrval['address']) ecs[u] = {} ecs[u]['reveal']={} for j in range(tries): P, P2, s, e, commit = generate_single_podle_sig( binascii.unhexlify(priv), j) if 'P' not in ecs[u]: ecs[u]['P'] = P ecs[u]['reveal'][j] = {'P2':P2, 's':s, 'e':e} btc.update_commitments(external_to_add=ecs) #Now the conditions described above hold. We do a normal single #sendpayment. taker = sendpayment.SendPayment(mcc, wallet, destaddr, amount, 2, 5000, 3, 0, True, weighted_order_choose) try: log.debug('starting message channels') mcc.run() finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] assert received == amount, "sendpayment failed - coins not arrived, " +\ "received: " + str(received) #Cleanup - remove the external commitments added btc.update_commitments(external_to_remove=ecs)
def test_failed_sendpayment(setup_podle, num_ygs, wallet_structures, mean_amt, mixdepth, sending_amt): """Test of initiating joins, but failing to complete, to see commitment usage. YGs in background as per test_regtest. Use sweeps to avoid recover_from_nonrespondants without intruding into sendpayment code. """ makercount = num_ygs answeryes = True txfee = 5000 waittime = 3 #Don't want to wait too long, but must account for possible #throttling with !auth jm_single().maker_timeout_sec = 12 amount = 0 wallets = make_wallets(makercount + 1, wallet_structures=wallet_structures, mean_amt=mean_amt) #the sendpayment bot uses the last wallet in the list wallet = wallets[makercount]['wallet'] yigen_procs = [] for i in range(makercount): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) destaddr = btc.privkey_to_address( os.urandom(32), from_hex=False, magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg #TODO paramatetrize this as a test variable chooseOrdersFunc = weighted_order_choose log.debug('starting sendpayment') jm_single().bc_interface.sync_wallet(wallet) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()] mcc = MessageChannelCollection(mcs) #Allow taker more retries than makers allow, so as to trigger #blacklist failure case jm_single().config.set("POLICY", "taker_utxo_retries", "4") #override ioauth receipt with a dummy do-nothing callback: def on_ioauth(*args): log.debug("Taker received: " + ','.join([str(x) for x in args])) class DummySendPayment(sendpayment.SendPayment): def __init__(self, msgchan, wallet, destaddr, amount, makercount, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc, on_ioauth): self.on_ioauth = on_ioauth self.podle_fails = 0 self.podle_allowed_fails = 3 #arbitrary; but do it more than once self.retries = 0 super(DummySendPayment, self).__init__(msgchan, wallet, destaddr, amount, makercount, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc) def on_welcome(self): Taker.on_welcome(self) DummyPaymentThread(self).start() class DummyPaymentThread(sendpayment.PaymentThread): def finishcallback(self, coinjointx): #Don't ignore makers and just re-start self.taker.retries += 1 if self.taker.podle_fails == self.taker.podle_allowed_fails: self.taker.msgchan.shutdown() return self.create_tx() def create_tx(self): try: super(DummyPaymentThread, self).create_tx() except btc.PoDLEError: log.debug("Got one commit failure, continuing") self.taker.podle_fails += 1 taker = DummySendPayment(mcc, wallet, destaddr, amount, makercount, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc, on_ioauth) try: log.debug('starting message channels') mcc.run() finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #We should have been able to try (tur -1) + podle_allowed_fails times assert taker.retries == jm_single().config.getint( "POLICY", "taker_utxo_retries") + taker.podle_allowed_fails #wait for block generation time.sleep(2) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] #Sanity check no transaction succeeded assert received == 0
def test_tumbler(setup_tumbler, num_ygs, wallet_structures, mean_amt, sdev_amt, yg_excess): """Test of tumbler code, with yield generators in background. """ log = get_log() options = Options() options.mixdepthsrc = 0 options.mixdepthcount = 4 options.minmakercount = 2 options.makercountrange = (num_ygs, 0) options.maxcjfee = (0.01, 10000) options.txfee = 5000 options.addrcount = 3 options.donateamount = 0.5 options.txcountparams = (4, 1) options.mintxcount = 1 options.amountpower = 100 options.timelambda = 0.2 options.waittime = 10 options.mincjamount = 1000000 options.liquiditywait = 5 options.maxbroadcasts = 4 options.maxcreatetx = 9 options = vars(options) wallets = make_wallets(num_ygs + 1, wallet_structures=wallet_structures, mean_amt=mean_amt, sdev_amt=sdev_amt) #need to make sure that at least some ygs have substantially #more coins for last stages of sweep/spend in tumble: for i in range(num_ygs): jm_single().bc_interface.grab_coins( wallets[i]['wallet'].get_external_addr(0), yg_excess) #the tumbler bot uses the last wallet in the list wallet = wallets[num_ygs]['wallet'] yigen_procs = [] for i in range(num_ygs): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) destaddrs = [] for i in range(3): destaddr = btc.privkey_to_address(os.urandom(32), from_hex=False, magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg destaddrs.append(destaddr) tx_list = tumbler.generate_tumbler_tx(destaddrs, options) pprint(tx_list) if options['addrcount'] + 1 > options['mixdepthcount']: print( 'not enough mixing depths to pay to all destination addresses, ' 'increasing mixdepthcount') options['mixdepthcount'] = options['addrcount'] + 1 tx_list2 = copy.deepcopy(tx_list) tx_dict = {} for tx in tx_list2: srcmixdepth = tx['srcmixdepth'] tx.pop('srcmixdepth') if srcmixdepth not in tx_dict: tx_dict[srcmixdepth] = [] tx_dict[srcmixdepth].append(tx) dbg_tx_list = [] for srcmixdepth, txlist in tx_dict.iteritems(): dbg_tx_list.append({'srcmixdepth': srcmixdepth, 'tx': txlist}) log.debug('tumbler transaction list') pprint(dbg_tx_list) total_wait = sum([tx['wait'] for tx in tx_list]) print('creates ' + str(len(tx_list)) + ' transactions in total') print('waits in total for ' + str(len(tx_list)) + ' blocks and ' + str(total_wait) + ' minutes') total_block_and_wait = len(tx_list) * 10 + total_wait print('estimated time taken ' + str(total_block_and_wait) + ' minutes or ' + str(round(total_block_and_wait / 60.0, 2)) + ' hours') jm_single().nickname = random_nick() log.debug('starting tumbler') jm_single().bc_interface.sync_wallet(wallet) jm_single().bc_interface.pushtx_failure_prob = 0.4 mcs = [ IRCMessageChannel(c, jm_single().nickname) for c in get_irc_mchannels() ] mcc = MessageChannelCollection(mcs) tumbler_bot = tumbler.Tumbler(mcc, wallet, tx_list, options) try: log.debug('starting message channels') mcc.run() except: log.debug('CRASHING, DUMPING EVERYTHING') debug_dump_object(wallet, ['addr_cache', 'keys', 'wallet_name', 'seed']) debug_dump_object(tumbler_bot) import traceback log.debug(traceback.format_exc()) finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] assert received != 0 """TODO: figure out a sensible assertion check for the destination
def test_tx_commitments_used(setup_podle, consume_tx, age_required, cmt_age): tries = jm_single().config.getint("POLICY", "taker_utxo_retries") #remember and reset at the end taker_utxo_age = jm_single().config.getint("POLICY", "taker_utxo_age") jm_single().config.set("POLICY", "taker_utxo_age", str(age_required)) #Don't want to wait too long, but must account for possible #throttling with !auth jm_single().maker_timeout_sec = 12 amount = 0 wallets = make_wallets(3, wallet_structures=[[1, 2, 1, 0, 0], [1, 2, 0, 0, 0], [2, 2, 1, 0, 0]], mean_amt=1) #the sendpayment bot uses the last wallet in the list wallet = wallets[2]['wallet'] #make_wallets calls grab_coins which mines 1 block per individual payout, #so the age of the coins depends on where they are in that list. The sendpayment #is the last wallet in the list, and we choose the non-tx utxos which are in #mixdepth 1 and 2 (2 and 1 utxos in each respectively). We filter for those #that have sufficient age, so to get 1 which is old enough, it will be the oldest, #which will have an age of 2 + 1 (the first utxo spent to that wallet). #So if we need an age of 6, we need to mine 3 more blocks. blocks_reqd = cmt_age - 3 jm_single().bc_interface.tick_forward_chain(blocks_reqd) yigen_procs = [] for i in range(2): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) time.sleep(5) destaddr = btc.privkey_to_address(binascii.hexlify(os.urandom(32)), magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg log.debug('starting sendpayment') jm_single().bc_interface.sync_wallet(wallet) log.debug("Here is the whole wallet: \n" + str(wallet.unspent)) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()] mcc = MessageChannelCollection(mcs) if consume_tx: #add all utxo in mixdepth 0 to 'used' list of commitments, utxos = wallet.get_utxos_by_mixdepth()[0] for u, addrval in utxos.iteritems(): priv = wallet.get_key_from_addr(addrval['address']) podle = btc.PoDLE(u, priv) for i in range(tries): #loop because we want to use up all retries of this utxo commitment = podle.generate_podle(i)['commit'] btc.update_commitments(commitment=commitment) #Now test a sendpayment from mixdepth 0 with all the depth 0 utxos #used up, so that the other utxos in the wallet get used. taker = sendpayment.SendPayment(mcc, wallet, destaddr, amount, 2, 5000, 3, 0, True, weighted_order_choose) try: log.debug('starting message channels') mcc.run() finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] jm_single().config.set("POLICY", "taker_utxo_age", str(taker_utxo_age)) if cmt_age < age_required: assert received == 0, "Coins arrived but shouldn't" else: assert received != 0, "sendpayment failed - coins not arrived, " +\ "received: " + str(received)
def test_sendpayment(setup_regtest, num_ygs, wallet_structures, mean_amt, mixdepth, sending_amt, ygcfs, fails, donate): """Test of sendpayment code, with yield generators in background. """ log = get_log() makercount = num_ygs answeryes = True txfee = 5000 waittime = 5 amount = sending_amt wallets = make_wallets(makercount + 1, wallet_structures=wallet_structures, mean_amt=mean_amt) #the sendpayment bot uses the last wallet in the list wallet = wallets[makercount]['wallet'] yigen_procs = [] if ygcfs: assert makercount == len(ygcfs) for i in range(makercount): if ygcfs: #back up default config, overwrite before start os.rename("joinmarket.cfg", "joinmarket.cfg.bak") shutil.copy2(ygcfs[i], "joinmarket.cfg") ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) if ygcfs: #Note: in case of using multiple configs, #the starting config is what is used by sendpayment os.rename("joinmarket.cfg.bak", "joinmarket.cfg") #A significant delay is needed to wait for the yield generators to sync time.sleep(20) if donate: destaddr = None else: destaddr = btc.privkey_to_address(os.urandom(32), from_hex=False, magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg #TODO paramatetrize this as a test variable chooseOrdersFunc = weighted_order_choose log.debug('starting sendpayment') jm_single().bc_interface.sync_wallet(wallet) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()] mcc = MessageChannelCollection(mcs) #hack fix for #356 if multiple orders per counterparty #removed for now. #if amount==0: makercount=2 taker = sendpayment.SendPayment(mcc, wallet, destaddr, amount, makercount - 2, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc) try: log.debug('starting message channels') mcc.run(failures=fails) finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) if not donate: received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] if amount != 0: assert received == amount, "sendpayment failed - coins not arrived, " +\ "received: " + str(received) #TODO: how to check success for sweep case? else: assert received != 0
def test_failed_sendpayment(setup_podle, num_ygs, wallet_structures, mean_amt, mixdepth, sending_amt): """Test of initiating joins, but failing to complete, to see commitment usage. YGs in background as per test_regtest. Use sweeps to avoid recover_from_nonrespondants without intruding into sendpayment code. """ makercount = num_ygs answeryes = True txfee = 5000 waittime = 3 #Don't want to wait too long, but must account for possible #throttling with !auth jm_single().maker_timeout_sec = 12 amount = 0 wallets = make_wallets(makercount + 1, wallet_structures=wallet_structures, mean_amt=mean_amt) #the sendpayment bot uses the last wallet in the list wallet = wallets[makercount]['wallet'] yigen_procs = [] for i in range(makercount): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) destaddr = btc.privkey_to_address(os.urandom(32), from_hex=False, magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg #TODO paramatetrize this as a test variable chooseOrdersFunc = weighted_order_choose log.debug('starting sendpayment') jm_single().bc_interface.sync_wallet(wallet) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 mcs = [IRCMessageChannel(c) for c in get_irc_mchannels()] mcc = MessageChannelCollection(mcs) #Allow taker more retries than makers allow, so as to trigger #blacklist failure case jm_single().config.set("POLICY", "taker_utxo_retries", "4") #override ioauth receipt with a dummy do-nothing callback: def on_ioauth(*args): log.debug("Taker received: " + ','.join([str(x) for x in args])) class DummySendPayment(sendpayment.SendPayment): def __init__(self, msgchan, wallet, destaddr, amount, makercount, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc, on_ioauth): self.on_ioauth = on_ioauth self.podle_fails = 0 self.podle_allowed_fails = 3 #arbitrary; but do it more than once self.retries = 0 super(DummySendPayment, self).__init__(msgchan, wallet, destaddr, amount, makercount, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc) def on_welcome(self): Taker.on_welcome(self) DummyPaymentThread(self).start() class DummyPaymentThread(sendpayment.PaymentThread): def finishcallback(self, coinjointx): #Don't ignore makers and just re-start self.taker.retries += 1 if self.taker.podle_fails == self.taker.podle_allowed_fails: self.taker.msgchan.shutdown() return self.create_tx() def create_tx(self): try: super(DummyPaymentThread, self).create_tx() except btc.PoDLEError: log.debug("Got one commit failure, continuing") self.taker.podle_fails += 1 taker = DummySendPayment(mcc, wallet, destaddr, amount, makercount, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc, on_ioauth) try: log.debug('starting message channels') mcc.run() finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #We should have been able to try (tur -1) + podle_allowed_fails times assert taker.retries == jm_single().config.getint( "POLICY", "taker_utxo_retries") + taker.podle_allowed_fails #wait for block generation time.sleep(2) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] #Sanity check no transaction succeeded assert received == 0
def test_sendpayment(setup_regtest, num_ygs, wallet_structures, mean_amt, mixdepth, sending_amt): """Test of sendpayment code, with yield generators in background. """ log = get_log() makercount = num_ygs answeryes = True txfee = 5000 waittime = 5 amount = sending_amt wallets = make_wallets(makercount + 1, wallet_structures=wallet_structures, mean_amt=mean_amt) #the sendpayment bot uses the last wallet in the list wallet = wallets[makercount]['wallet'] yigen_procs = [] for i in range(makercount): ygp = local_command([python_cmd, yg_cmd,\ str(wallets[i]['seed'])], bg=True) time.sleep(2) #give it a chance yigen_procs.append(ygp) #A significant delay is needed to wait for the yield generators to sync time.sleep(20) if btc.secp_present: destaddr = btc.privkey_to_address( os.urandom(32), from_hex=False, magicbyte=get_p2pk_vbyte()) else: destaddr = btc.privkey_to_address( os.urandom(32), magicbyte=get_p2pk_vbyte()) addr_valid, errormsg = validate_address(destaddr) assert addr_valid, "Invalid destination address: " + destaddr + \ ", error message: " + errormsg #TODO paramatetrize this as a test variable chooseOrdersFunc = weighted_order_choose jm_single().nickname = random_nick() log.debug('starting sendpayment') jm_single().bc_interface.sync_wallet(wallet) #Trigger PING LAG sending artificially joinmarket.irc.PING_INTERVAL = 3 irc = IRCMessageChannel(jm_single().nickname) taker = sendpayment.SendPayment(irc, wallet, destaddr, amount, makercount, txfee, waittime, mixdepth, answeryes, chooseOrdersFunc) try: log.debug('starting irc') irc.run() finally: if any(yigen_procs): for ygp in yigen_procs: #NB *GENTLE* shutdown is essential for #test coverage reporting! ygp.send_signal(signal.SIGINT) ygp.wait() #wait for block generation time.sleep(5) received = jm_single().bc_interface.get_received_by_addr( [destaddr], None)['data'][0]['balance'] if amount != 0: assert received == amount, "sendpayment failed - coins not arrived, " +\ "received: " + str(received) #TODO: how to check success for sweep case? else: assert received != 0