From 43368e1f9e99bac79e210811d10c161212153116 Mon Sep 17 00:00:00 2001 From: Kristaps Kaupe Date: Thu, 15 Oct 2020 23:04:30 +0300 Subject: [PATCH] Output values on "Not enough funds" exception --- jmclient/jmclient/__init__.py | 2 +- jmclient/jmclient/support.py | 23 ++++++++++++++++------- jmclient/test/test_taker.py | 5 +++-- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/jmclient/jmclient/__init__.py b/jmclient/jmclient/__init__.py index 56579f4..e6e2a93 100644 --- a/jmclient/jmclient/__init__.py +++ b/jmclient/jmclient/__init__.py @@ -7,7 +7,7 @@ from .support import (calc_cj_fee, choose_sweep_orders, choose_orders, rand_weighted_choice, select, select_gradual, select_greedy, select_greediest, get_random_bytes, random_under_max_order_choose, - select_one_utxo) + select_one_utxo, NotEnoughFundsException) from .jsonrpc import JsonRpcError, JsonRpcConnectionError, JsonRpc from .old_mnemonic import mn_decode, mn_encode from .taker import Taker diff --git a/jmclient/jmclient/support.py b/jmclient/jmclient/support.py index bdf601c..f2d8cef 100644 --- a/jmclient/jmclient/support.py +++ b/jmclient/jmclient/support.py @@ -10,6 +10,14 @@ ORDER_KEYS = ['counterparty', 'oid', 'ordertype', 'minsize', 'maxsize', 'txfee', log = get_log() + +class NotEnoughFundsException(RuntimeError): + + def __init__(self, want, has): + super().__init__("Not enough funds, " + + str(want) + " vs. " + str(has) + ".") + + """ Random functions - replacing some NumPy features NOTE THESE ARE NEITHER CRYPTOGRAPHICALLY SECURE @@ -17,7 +25,6 @@ NOR PERFORMANT NOR HIGH PRECISION! Only for sampling purposes """ - def get_random_bytes(num_bytes, cryptographically_secure=False): if cryptographically_secure: # uses os.urandom if available @@ -78,9 +85,10 @@ def select(unspent, value): tv += low[i]["value"] i += 1 if tv < value: - raise Exception("Not enough funds") + raise NotEnoughFundsException(value, tv) return low[:i] + def select_gradual(unspent, value): """ UTXO selection algorithm for gradual dust reduction @@ -94,7 +102,7 @@ def select_gradual(unspent, value): lowsum = reduce(lambda x, y: x + y, map(key, low), 0) if value > lowsum: if len(high) == 0: - raise Exception('Not enough funds') + raise NotEnoughFundsException(value, lowsum) else: return [high[0]] else: @@ -129,11 +137,11 @@ def select_greedy(unspent, value): if value > 0: # no, that drops us below the target picked += [utxo] # so we need this one too value -= key(utxo) # 'backtrack' the counter + picked_sum = sum(key(u) for u in picked) if len(picked) > 0: - if len(picked) < len(utxos) or sum( - key(u) for u in picked) >= original_value: + if len(picked) < len(utxos) or picked_sum >= original_value: return picked - raise Exception('Not enough funds') # if all else fails, we do too + raise NotEnoughFundsException(original_value, picked_sum) # if all else fails, we do too def select_greediest(unspent, value): @@ -149,7 +157,7 @@ def select_greediest(unspent, value): lowsum = reduce(lambda x, y: x + y, map(key, low), 0) if value > lowsum: if len(high) == 0: - raise Exception('Not enough funds') + raise NotEnoughFundsException(value, lowsum) else: return [high[0]] else: @@ -159,6 +167,7 @@ def select_greediest(unspent, value): end += 1 return low[0:end] + def select_one_utxo(unspent, value): key = lambda u: u['value'] return [random.choice([u for u in unspent if key(u) >= value])] diff --git a/jmclient/test/test_taker.py b/jmclient/test/test_taker.py index 6476853..43078f0 100644 --- a/jmclient/test/test_taker.py +++ b/jmclient/test/test_taker.py @@ -13,7 +13,8 @@ from base64 import b64encode from jmbase import utxostr_to_utxo, hextobin from jmclient import load_test_config, jm_single, set_commitment_file,\ get_commitment_file, SegwitLegacyWallet, Taker, VolatileStorage,\ - get_network, WalletService, NO_ROUNDING, BTC_P2PKH + get_network, WalletService, NO_ROUNDING, BTC_P2PKH,\ + NotEnoughFundsException from taker_test_data import t_utxos_by_mixdepth, t_orderbook,\ t_maker_response, t_chosen_orders, t_dummy_ext from commontest import default_max_cj_fee @@ -57,7 +58,7 @@ class DummyWallet(SegwitLegacyWallet): def select_utxos(self, mixdepth, amount, utxo_filter=None, select_fn=None, maxheight=None, includeaddr=False): if amount > self.get_balance_by_mixdepth()[mixdepth]: - raise Exception("Not enough funds") + raise NotEnoughFundsException(amount, self.get_balance_by_mixdepth()[mixdepth]) # comment as for get_utxos_by_mixdepth: retval = {} for k, v in t_utxos_by_mixdepth[mixdepth].items():