|
|
|
|
@ -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])] |
|
|
|
|
|