def create_tx(self): time.sleep(self.taker.waittime) crow = self.taker.db.execute( 'SELECT COUNT(DISTINCT counterparty) FROM orderbook;').fetchone() counterparty_count = crow['COUNT(DISTINCT counterparty)'] counterparty_count -= len(self.ignored_makers) if counterparty_count < self.taker.makercount: log.debug('not enough counterparties to fill order, ending') #NB: don't shutdown msgchan here, that is done by the caller #after setting GUI state to reflect the reason for shutdown. return None, None, None, None utxos = None orders = None cjamount = None change_addr = None choose_orders_recover = None if self.taker.amount == 0: utxos = self.taker.wallet.get_utxos_by_mixdepth()[ self.taker.mixdepth] #do our best to estimate the fee based on the number of #our own utxos; this estimate may be significantly higher #than the default set in option.txfee * makercount, where #we have a large number of utxos to spend. If it is smaller, #we'll be conservative and retain the original estimate. est_ins = len(utxos) + 3 * self.taker.makercount log.debug("Estimated ins: " + str(est_ins)) est_outs = 2 * self.taker.makercount + 1 log.debug("Estimated outs: " + str(est_outs)) estimated_fee = estimate_tx_fee(est_ins, est_outs) log.debug("We have a fee estimate: " + str(estimated_fee)) log.debug("And a requested fee of: " + str(self.taker.txfee * self.taker.makercount)) if estimated_fee > self.taker.makercount * self.taker.txfee: #both values are integers; we can ignore small rounding errors self.taker.txfee = estimated_fee / self.taker.makercount total_value = sum([va['value'] for va in utxos.values()]) orders, cjamount = choose_sweep_orders(self.taker.db, total_value, self.taker.txfee, self.taker.makercount, self.taker.chooseOrdersFunc, self.ignored_makers) if not orders: raise Exception( "Could not find orders to complete transaction.") total_cj_fee = total_value - cjamount - \ self.taker.txfee*self.taker.makercount else: orders, total_cj_fee = self.sendpayment_choose_orders( self.taker.amount, self.taker.makercount) cjamount = self.taker.amount if not orders: log.debug( 'ERROR not enough liquidity in the orderbook, exiting') return None, None, None, None return orders, total_cj_fee, cjamount, utxos
def create_tx(self): time.sleep(self.taker.waittime) crow = self.taker.db.execute( 'SELECT COUNT(DISTINCT counterparty) FROM orderbook;').fetchone() counterparty_count = crow['COUNT(DISTINCT counterparty)'] counterparty_count -= len(self.ignored_makers) if counterparty_count < self.taker.makercount: log.debug('not enough counterparties to fill order, ending') #NB: don't shutdown msgchan here, that is done by the caller #after setting GUI state to reflect the reason for shutdown. return None, None, None, None utxos = None orders = None cjamount = None change_addr = None choose_orders_recover = None if self.taker.amount == 0: utxos = self.taker.wallet.get_utxos_by_mixdepth()[ self.taker.mixdepth] #do our best to estimate the fee based on the number of #our own utxos; this estimate may be significantly higher #than the default set in option.txfee * makercount, where #we have a large number of utxos to spend. If it is smaller, #we'll be conservative and retain the original estimate. est_ins = len(utxos)+3*self.taker.makercount log.debug("Estimated ins: "+str(est_ins)) est_outs = 2*self.taker.makercount + 1 log.debug("Estimated outs: "+str(est_outs)) estimated_fee = estimate_tx_fee(est_ins, est_outs) log.debug("We have a fee estimate: "+str(estimated_fee)) log.debug("And a requested fee of: "+str( self.taker.txfee * self.taker.makercount)) if estimated_fee > self.taker.makercount * self.taker.txfee: #both values are integers; we can ignore small rounding errors self.taker.txfee = estimated_fee / self.taker.makercount total_value = sum([va['value'] for va in utxos.values()]) orders, cjamount = choose_sweep_orders( self.taker.db, total_value, self.taker.txfee, self.taker.makercount, self.taker.chooseOrdersFunc, self.ignored_makers) if not orders: raise Exception("Could not find orders to complete transaction.") total_cj_fee = total_value - cjamount - \ self.taker.txfee*self.taker.makercount else: orders, total_cj_fee = self.sendpayment_choose_orders( self.taker.amount, self.taker.makercount) cjamount = self.taker.amount if not orders: log.debug( 'ERROR not enough liquidity in the orderbook, exiting') return None, None, None, None return orders, total_cj_fee, cjamount, utxos
def create_tx(self): crow = self.taker.db.execute( 'SELECT COUNT(DISTINCT counterparty) FROM orderbook;' ).fetchone() counterparty_count = crow['COUNT(DISTINCT counterparty)'] counterparty_count -= len(self.ignored_makers) if counterparty_count < self.taker.options.makercount: print 'not enough counterparties to fill order, ending' self.taker.msgchan.shutdown() return utxos = self.taker.utxo_data change_addr = None choose_orders_recover = None if self.taker.cjamount == 0: total_value = sum([va['value'] for va in utxos.values()]) orders, cjamount = choose_sweep_orders( self.taker.db, total_value, self.taker.options.txfee, self.taker.options.makercount, self.taker.chooseOrdersFunc, self.ignored_makers) if not self.taker.options.answeryes: total_cj_fee = total_value - cjamount - self.taker.options.txfee log.debug('total cj fee = ' + str(total_cj_fee)) total_fee_pc = 1.0 * total_cj_fee / cjamount log.debug('total coinjoin fee = ' + str(float('%.3g' % ( 100.0 * total_fee_pc))) + '%') sendpayment.check_high_fee(total_fee_pc) if raw_input('send with these orders? (y/n):')[0] != 'y': # noinspection PyTypeChecker self.finishcallback(None) return else: orders, total_cj_fee = self.sendpayment_choose_orders( self.taker.cjamount, self.taker.options.makercount) if not orders: log.debug( 'ERROR not enough liquidity in the orderbook, exiting') return total_amount = self.taker.cjamount + total_cj_fee + \ self.taker.options.txfee print 'total amount spent = ' + str(total_amount) cjamount = self.taker.cjamount change_addr = self.taker.changeaddr choose_orders_recover = self.sendpayment_choose_orders auth_addr = self.taker.utxo_data[self.taker.auth_utxo]['address'] self.taker.start_cj(self.taker.wallet, cjamount, orders, utxos, self.taker.destaddr, change_addr, self.taker.options.txfee, self.finishcallback, choose_orders_recover, auth_addr)
def create_tx(self): if self.create_tx_attempts == 0: log.debug( 'reached limit of number of attempts to create tx, quitting') self.taker.msgchan.shutdown() return jm_single().bc_interface.sync_unspent(self.taker.wallet) self.create_tx_attempts -= 1 orders = None cj_amount = 0 change_addr = None choose_orders_recover = None if self.sweep: log.debug('sweeping') utxos = self.taker.wallet.get_utxos_by_mixdepth()[ self.tx['srcmixdepth']] #do our best to estimate the fee based on the number of #our own utxos; this estimate may be significantly higher #than the default set in option.txfee * makercount, where #we have a large number of utxos to spend. If it is smaller, #we'll be conservative and retain the original estimate. est_ins = len(utxos) + 3 * self.tx['makercount'] log.debug("Estimated ins: " + str(est_ins)) est_outs = 2 * self.tx['makercount'] + 1 log.debug("Estimated outs: " + str(est_outs)) estimated_fee = estimate_tx_fee(est_ins, est_outs) log.debug("We have a fee estimate: " + str(estimated_fee)) log.debug("And a requested fee of: " + str(self.taker.options.txfee * self.tx['makercount'])) fee_for_tx = max([ estimated_fee, self.tx['makercount'] * self.taker.options.txfee ]) fee_for_tx = int(fee_for_tx / self.tx['makercount']) total_value = sum([addrval['value'] for addrval in utxos.values()]) while True: orders, cj_amount, total_cj_fee = choose_sweep_orders( self.taker.db, total_value, fee_for_tx, self.tx['makercount'], weighted_order_choose, self.ignored_makers) if orders is None: log.debug('waiting for liquidity ' + str(self.taker.options.liquiditywait) + 'secs, hopefully more orders should come in') time.sleep(self.taker.options.liquiditywait) continue abs_cj_fee = 1.0 * total_cj_fee / self.tx['makercount'] rel_cj_fee = abs_cj_fee / cj_amount log.debug('rel/abs average fee = ' + str(rel_cj_fee) + ' / ' + str(abs_cj_fee)) if rel_cj_fee > self.taker.options.maxcjfee[0] \ and abs_cj_fee > self.taker.options.maxcjfee[1]: log.debug('cj fee higher than maxcjfee, waiting ' + str(self.taker.options.liquiditywait) + ' seconds') time.sleep(self.taker.options.liquiditywait) continue break else: if self.tx['amount_fraction'] == 0: cj_amount = int(self.balance * self.taker.options.donateamount / 100.0) self.destaddr = None else: cj_amount = int(self.tx['amount_fraction'] * self.balance) if cj_amount < self.taker.options.mincjamount: log.debug('cj amount too low, bringing up') cj_amount = self.taker.options.mincjamount change_addr = self.taker.wallet.get_internal_addr( self.tx['srcmixdepth']) log.debug('coinjoining ' + str(cj_amount) + ' satoshi') orders, total_cj_fee = self.tumbler_choose_orders( cj_amount, self.tx['makercount']) total_amount = cj_amount + total_cj_fee + \ self.taker.options.txfee*self.tx['makercount'] log.debug('total estimated amount spent = ' + str(total_amount)) #adjust the required amount upwards to anticipate a tripling of #transaction fee after re-estimation; this is sufficiently conservative #to make failures unlikely while keeping the occurence of failure to #find sufficient utxos extremely rare. Indeed, a tripling of 'normal' #txfee indicates undesirable behaviour on maker side anyway. try: utxos = self.taker.wallet.select_utxos( self.tx['srcmixdepth'], total_amount + 2 * self.taker.options.txfee * self.tx['makercount']) except Exception as e: #we cannot afford to just throw not enough funds; better to #try with a smaller request; it could still fail within #CoinJoinTX.recv_txio, but make every effort to avoid stopping. if str(e) == "Not enough funds": log.debug( "Failed to select total amount + twice txfee from" + "wallet; trying to select just total amount.") utxos = self.taker.wallet.select_utxos( self.tx['srcmixdepth'], total_amount) else: raise fee_for_tx = self.taker.options.txfee choose_orders_recover = self.tumbler_choose_orders self.taker.start_cj(self.taker.wallet, cj_amount, orders, utxos, self.destaddr, change_addr, fee_for_tx * self.tx['makercount'], self.finishcallback, choose_orders_recover)
def create_tx(self): if self.create_tx_attempts == 0: log.debug('reached limit of number of attempts to create tx, quitting') self.taker.msgchan.shutdown() return jm_single().bc_interface.sync_unspent(self.taker.wallet) self.create_tx_attempts -= 1 orders = None cj_amount = 0 change_addr = None choose_orders_recover = None if self.sweep: log.debug('sweeping') utxos = self.taker.wallet.get_utxos_by_mixdepth()[self.tx[ 'srcmixdepth']] #do our best to estimate the fee based on the number of #our own utxos; this estimate may be significantly higher #than the default set in option.txfee * makercount, where #we have a large number of utxos to spend. If it is smaller, #we'll be conservative and retain the original estimate. est_ins = len(utxos)+3*self.tx['makercount'] log.debug("Estimated ins: "+str(est_ins)) est_outs = 2*self.tx['makercount'] + 1 log.debug("Estimated outs: "+str(est_outs)) estimated_fee = estimate_tx_fee(est_ins, est_outs) log.debug("We have a fee estimate: "+str(estimated_fee)) log.debug("And a requested fee of: "+str( self.taker.options['txfee'] * self.tx['makercount'])) fee_for_tx = max([estimated_fee, self.tx['makercount'] * self.taker.options['txfee']]) fee_for_tx = int(fee_for_tx / self.tx['makercount']) total_value = sum([addrval['value'] for addrval in utxos.values()]) while True: orders, cj_amount, total_cj_fee = choose_sweep_orders( self.taker.db, total_value, fee_for_tx, self.tx['makercount'], weighted_order_choose, self.ignored_makers) if orders is None: log.debug('waiting for liquidity ' + str( self.taker.options['liquiditywait']) + 'secs, hopefully more orders should come in') time.sleep(self.taker.options['liquiditywait']) continue abs_cj_fee = 1.0 * total_cj_fee / self.tx['makercount'] rel_cj_fee = abs_cj_fee / cj_amount log.debug( 'rel/abs average fee = ' + str(rel_cj_fee) + ' / ' + str( abs_cj_fee)) if rel_cj_fee > self.taker.options['maxcjfee'][0] \ and abs_cj_fee > self.taker.options['maxcjfee'][1]: log.debug('cj fee higher than maxcjfee, waiting ' + str( self.taker.options['liquiditywait']) + ' seconds') time.sleep(self.taker.options['liquiditywait']) continue break else: if self.tx['amount_fraction'] == 0: cj_amount = int(self.balance * self.taker.options['donateamount'] / 100.0) self.destaddr = None else: cj_amount = int(self.tx['amount_fraction'] * self.balance) if cj_amount < self.taker.options['mincjamount']: log.debug('cj amount too low, bringing up') cj_amount = self.taker.options['mincjamount'] change_addr = self.taker.wallet.get_internal_addr( self.tx['srcmixdepth']) log.debug('coinjoining ' + str(cj_amount) + ' satoshi') orders, total_cj_fee = self.tumbler_choose_orders( cj_amount, self.tx['makercount']) total_amount = cj_amount + total_cj_fee + \ self.taker.options['txfee']*self.tx['makercount'] log.debug('total estimated amount spent = ' + str(total_amount)) #adjust the required amount upwards to anticipate an increase of the #transaction fee after re-estimation; this is sufficiently conservative #to make failures unlikely while keeping the occurence of failure to #find sufficient utxos extremely rare. Indeed, a doubling of 'normal' #txfee indicates undesirable behaviour on maker side anyway. try: utxos = self.taker.wallet.select_utxos(self.tx['srcmixdepth'], total_amount+self.taker.options['txfee']*self.tx['makercount']) except Exception as e: #we cannot afford to just throw not enough funds; better to #try with a smaller request; it could still fail within #CoinJoinTX.recv_txio, but make every effort to avoid stopping. if str(e) == "Not enough funds": log.debug("Failed to select total amount + twice txfee from" + "wallet; trying to select just total amount.") utxos = self.taker.wallet.select_utxos(self.tx['srcmixdepth'], total_amount) else: raise fee_for_tx = self.taker.options['txfee'] choose_orders_recover = self.tumbler_choose_orders self.taker.start_cj(self.taker.wallet, cj_amount, orders, utxos, self.destaddr, change_addr, fee_for_tx*self.tx['makercount'], self.finishcallback, choose_orders_recover)
def create_tx(self): crow = self.taker.db.execute( 'SELECT COUNT(DISTINCT counterparty) FROM orderbook;').fetchone() counterparty_count = crow['COUNT(DISTINCT counterparty)'] counterparty_count -= len(self.ignored_makers) if counterparty_count < self.taker.makercount: print('not enough counterparties to fill order, ending') self.taker.msgchan.shutdown() return utxos = None orders = None cjamount = 0 change_addr = None choose_orders_recover = None if self.taker.amount == 0: utxos = self.taker.wallet.get_utxos_by_mixdepth()[ self.taker.mixdepth] #do our best to estimate the fee based on the number of #our own utxos; this estimate may be significantly higher #than the default set in option.txfee * makercount, where #we have a large number of utxos to spend. If it is smaller, #we'll be conservative and retain the original estimate. est_ins = len(utxos) + 3 * self.taker.makercount log.debug("Estimated ins: " + str(est_ins)) est_outs = 2 * self.taker.makercount + 1 log.debug("Estimated outs: " + str(est_outs)) estimated_fee = estimate_tx_fee(est_ins, est_outs) log.debug("We have a fee estimate: " + str(estimated_fee)) log.debug("And a requested fee of: " + str(self.taker.txfee * self.taker.makercount)) if estimated_fee > self.taker.makercount * self.taker.txfee: #both values are integers; we can ignore small rounding errors self.taker.txfee = estimated_fee / self.taker.makercount total_value = sum([va['value'] for va in utxos.values()]) orders, cjamount = choose_sweep_orders(self.taker.db, total_value, self.taker.txfee, self.taker.makercount, self.taker.chooseOrdersFunc, self.ignored_makers) if not orders: raise Exception( "Could not find orders to complete transaction.") if not self.taker.answeryes: total_cj_fee = total_value - cjamount - \ self.taker.txfee*self.taker.makercount log.debug('total cj fee = ' + str(total_cj_fee)) total_fee_pc = 1.0 * total_cj_fee / cjamount log.debug('total coinjoin fee = ' + str(float('%.3g' % (100.0 * total_fee_pc))) + '%') check_high_fee(total_fee_pc) if raw_input('send with these orders? (y/n):')[0] != 'y': self.taker.msgchan.shutdown() return else: orders, total_cj_fee = self.sendpayment_choose_orders( self.taker.amount, self.taker.makercount) if not orders: log.debug( 'ERROR not enough liquidity in the orderbook, exiting') return total_amount = self.taker.amount + total_cj_fee + \ self.taker.txfee*self.taker.makercount print 'total estimated amount spent = ' + str(total_amount) #adjust the required amount upwards to anticipate a tripling of #transaction fee after re-estimation; this is sufficiently conservative #to make failures unlikely while keeping the occurence of failure to #find sufficient utxos extremely rare. Indeed, a tripling of 'normal' #txfee indicates undesirable behaviour on maker side anyway. utxos = self.taker.wallet.select_utxos( self.taker.mixdepth, total_amount + 2 * self.taker.txfee * self.taker.makercount) cjamount = self.taker.amount change_addr = self.taker.wallet.get_internal_addr( self.taker.mixdepth) choose_orders_recover = self.sendpayment_choose_orders self.taker.start_cj(self.taker.wallet, cjamount, orders, utxos, self.taker.destaddr, change_addr, self.taker.makercount * self.taker.txfee, self.finishcallback, choose_orders_recover)
def create_tx(self): crow = self.taker.db.execute( 'SELECT COUNT(DISTINCT counterparty) FROM orderbook;').fetchone() counterparty_count = crow['COUNT(DISTINCT counterparty)'] counterparty_count -= len(self.ignored_makers) if counterparty_count < self.taker.makercount: print('not enough counterparties to fill order, ending') self.taker.msgchan.shutdown() return utxos = None orders = None cjamount = 0 change_addr = None choose_orders_recover = None if self.taker.amount == 0: utxos = self.taker.wallet.get_utxos_by_mixdepth()[ self.taker.mixdepth] #do our best to estimate the fee based on the number of #our own utxos; this estimate may be significantly higher #than the default set in option.txfee * makercount, where #we have a large number of utxos to spend. If it is smaller, #we'll be conservative and retain the original estimate. est_ins = len(utxos)+3*self.taker.makercount log.debug("Estimated ins: "+str(est_ins)) est_outs = 2*self.taker.makercount + 1 log.debug("Estimated outs: "+str(est_outs)) estimated_fee = estimate_tx_fee(est_ins, est_outs) log.debug("We have a fee estimate: "+str(estimated_fee)) log.debug("And a requested fee of: "+str( self.taker.txfee * self.taker.makercount)) if estimated_fee > self.taker.makercount * self.taker.txfee: #both values are integers; we can ignore small rounding errors self.taker.txfee = estimated_fee / self.taker.makercount total_value = sum([va['value'] for va in utxos.values()]) orders, cjamount = choose_sweep_orders( self.taker.db, total_value, self.taker.txfee, self.taker.makercount, self.taker.chooseOrdersFunc, self.ignored_makers) if not orders: raise Exception("Could not find orders to complete transaction.") if not self.taker.answeryes: total_cj_fee = total_value - cjamount - \ self.taker.txfee*self.taker.makercount log.debug('total cj fee = ' + str(total_cj_fee)) total_fee_pc = 1.0 * total_cj_fee / cjamount log.debug('total coinjoin fee = ' + str(float('%.3g' % ( 100.0 * total_fee_pc))) + '%') check_high_fee(total_fee_pc) if raw_input('send with these orders? (y/n):')[0] != 'y': self.taker.msgchan.shutdown() return else: orders, total_cj_fee = self.sendpayment_choose_orders( self.taker.amount, self.taker.makercount) if not orders: log.debug( 'ERROR not enough liquidity in the orderbook, exiting') return total_amount = self.taker.amount + total_cj_fee + \ self.taker.txfee*self.taker.makercount print 'total estimated amount spent = ' + str(total_amount) #adjust the required amount upwards to anticipate a tripling of #transaction fee after re-estimation; this is sufficiently conservative #to make failures unlikely while keeping the occurence of failure to #find sufficient utxos extremely rare. Indeed, a tripling of 'normal' #txfee indicates undesirable behaviour on maker side anyway. utxos = self.taker.wallet.select_utxos(self.taker.mixdepth, total_amount+2*self.taker.txfee*self.taker.makercount) cjamount = self.taker.amount change_addr = self.taker.wallet.get_internal_addr(self.taker.mixdepth) choose_orders_recover = self.sendpayment_choose_orders self.taker.start_cj(self.taker.wallet, cjamount, orders, utxos, self.taker.destaddr, change_addr, self.taker.makercount*self.taker.txfee, self.finishcallback, choose_orders_recover)