diff --git a/joinmarket/irc.py b/joinmarket/irc.py index f7b5253a..feb6ba2c 100644 --- a/joinmarket/irc.py +++ b/joinmarket/irc.py @@ -54,8 +54,8 @@ def get_irc_text(line): return line[line[1:].find(':') + 2:] -def get_irc_nick(source): - return source[1:source.find('!')] +def get_irc_nick(source): # Sybil annoyance through hostmask inclusion + return source[1:source.find('!') + 1] + source[source.find('@') + 1:] class PingThread(threading.Thread): @@ -143,8 +143,9 @@ def push_tx(self, nick, txhex): def announce_orders(self, orderlist, nick=None): # nick=None means announce publicly order_keys = ['oid', 'minsize', 'maxsize', 'txfee', 'cjfee'] - header = 'PRIVMSG ' + (nick if nick else self.channel) + ' :' - orderlines = [] + target = nick[:nick.find('!')] if nick else self.channel # same header + header = 'PRIVMSG ' + target + ' :' # works for both pit announcements + orderlines = [] # and PM replies to !orderbook for i, order in enumerate(orderlist): orderparams = COMMAND_PREFIX + order['ordertype'] + \ ' ' + ' '.join([str(order[k]) for k in order_keys]) @@ -192,7 +193,7 @@ def __privmsg(self, nick, cmd, message): return message = encrypt_encode(message, box) - header = "PRIVMSG " + nick + " :" + header = "PRIVMSG " + nick[:nick.find('!')] + " :" # remove hostmask max_chunk_len = MAX_PRIVMSG_LEN - len(header) - len(cmd) - 4 # 1 for command prefix 1 for space 2 for trailer if len(message) > max_chunk_len: diff --git a/joinmarket/support.py b/joinmarket/support.py index 5c2521ae..e38d4e87 100644 --- a/joinmarket/support.py +++ b/joinmarket/support.py @@ -235,6 +235,14 @@ def pick_order(orders, n, feekey): return orders[pickedOrderIndex] pickedOrderIndex = -1 +def offer_profit(offer): + """ + Calculates the net profit to the maker of the given offer. + Expects an offer in the form (counterparty, oid, cjfee, txfee) + where cjfee and txfee are integer amounts of satoshi. + """ + return offer[2] - offer[3] + def choose_orders(db, cj_amount, n, chooseOrdersBy, ignored_makers=None): if ignored_makers is None: @@ -246,10 +254,20 @@ def choose_orders(db, cj_amount, n, chooseOrdersBy, ignored_makers=None): if o['minsize'] <= cj_amount <= o['maxsize'] and o[ 'counterparty'] not in ignored_makers] - # function that returns the fee for a given order - def feekey(o): - return o[2] - o[3] + """ + restrict to one order per counterparty, choose the one with the lowest + cjfee this is done in advance of the order selection algo, so applies to + all of them. however, if orders are picked manually, allow duplicates. + """ + if chooseOrdersBy != pick_order: + orders = sorted( # index by hostmask only, as it's harder to + dict(((v[0])[v[0].find('!')+1:], v) # spoof than the nick field + for v in sorted(orders, key=offer_profit, + reverse=True)).values(), key=offer_profit) + else: + orders = sorted(orders, key=offer_profit) # sort by increasing cjfee + # after deduplication, ensure we have enough distinct counterparties counterparties = set([o[0] for o in orders]) if n > len(counterparties): log.debug(('ERROR not enough liquidity in the orderbook n=%d ' @@ -258,24 +276,11 @@ def feekey(o): # TODO handle not enough liquidity better, maybe an Exception return None, 0 - """ - restrict to one order per counterparty, choose the one with the lowest - cjfee this is done in advance of the order selection algo, so applies to - all of them. however, if orders are picked manually, allow duplicates. - """ - if chooseOrdersBy != pick_order: - orders = sorted( - dict((v[0], v) for v in sorted( - orders, key=feekey, reverse=True)).values(), key=feekey) - else: - orders = sorted(orders, - key=feekey) # sort from smallest to biggest cj fee - log.debug('considered orders = \n' + '\n'.join([str(o) for o in orders])) total_cj_fee = 0 chosen_orders = [] for i in range(n): - chosen_order = chooseOrdersBy(orders, n, feekey) + chosen_order = chooseOrdersBy(orders, n, offer_profit) orders = [o for o in orders if o[0] != chosen_order[0] ] # remove all orders from that same counterparty chosen_orders.append(chosen_order) @@ -302,7 +307,7 @@ def choose_sweep_orders(db, => cjamount = (totalin - mytxfee - sum(absfee)) / (1 + sum(relfee)) """ total_txfee = txfee*n - + if ignored_makers is None: ignored_makers = [] @@ -344,11 +349,8 @@ def calc_zero_change_cj_amount(ordercombo): total_input_value), o['txfee']) for o in orderlist] - def feekey(o): - return o[2] - o[3] - # sort from smallest to biggest cj fee - available_orders = sorted(available_orders, key=feekey) + available_orders = sorted(available_orders, key=offer_profit) chosen_orders = [] while len(chosen_orders) < n: if len(available_orders) < n - len(chosen_orders): @@ -356,7 +358,7 @@ def feekey(o): # TODO handle not enough liquidity better, maybe an Exception return None, 0 for i in range(n - len(chosen_orders)): - chosen_order = chooseOrdersBy(available_orders, n, feekey) + chosen_order = chooseOrdersBy(available_orders, n, offer_profit) log.debug('chosen = ' + str(chosen_order)) # remove all orders from that same counterparty available_orders = [ diff --git a/ob-watcher.py b/ob-watcher.py index 65bccabb..e784bea5 100644 --- a/ob-watcher.py +++ b/ob-watcher.py @@ -107,28 +107,24 @@ def get_graph_html(fig): # callback functions for displaying order data -def do_nothing(arg, order, btc_unit, rel_unit): - return arg - +def trim_host(nickhost, order, btc_unit, rel_unit): + return nickhost[nickhost.find('!')+1:] def ordertype_display(ordertype, order, btc_unit, rel_unit): ordertypes = {'absorder': 'Absolute Fee', 'relorder': 'Relative Fee'} return ordertypes[ordertype] - def cjfee_display(cjfee, order, btc_unit, rel_unit): if order['ordertype'] == 'absorder': return satoshi_to_unit(cjfee, order, btc_unit, rel_unit) elif order['ordertype'] == 'relorder': return str(float(cjfee) * rel_unit_to_factor[rel_unit]) + rel_unit - def satoshi_to_unit(sat, order, btc_unit, rel_unit): power = unit_to_power[btc_unit] return ("%." + str(power) + "f") % float( Decimal(sat) / Decimal(10 ** power)) - def order_str(s, order, btc_unit, rel_unit): return str(s) @@ -139,7 +135,7 @@ def create_orderbook_table(db, btc_unit, rel_unit): if not rows: return 0, result order_keys_display = (('ordertype', ordertype_display), - ('counterparty', do_nothing), ('oid', order_str), + ('counterparty', trim_host), ('oid', order_str), ('cjfee', cjfee_display), ('txfee', satoshi_to_unit), ('minsize', satoshi_to_unit), ('maxsize', satoshi_to_unit))