@@ -97,7 +97,7 @@ def select(self,
97
97
98
98
if change .coin < min_change_amount :
99
99
additional , _ = self .select (available ,
100
- [TransactionOutput (None , min_change_amount )],
100
+ [TransactionOutput (None , min_change_amount - change . coin )],
101
101
context ,
102
102
max_input_count - len (selected ) if max_input_count else None ,
103
103
include_max_fee = False ,
@@ -130,7 +130,7 @@ class RandomImproveMultiAsset(UTxOSelector):
130
130
def __init__ (self , random_generator : Optional [Iterable [int ]] = None ):
131
131
self .random_generator = iter (random_generator ) if random_generator else None
132
132
133
- def _get_next_random (self , utxos : List [UTxO ]) -> UTxO :
133
+ def _get_next_random (self , utxos : List [UTxO ]) -> Tuple [ int , UTxO ] :
134
134
if not utxos :
135
135
raise InputUTxODepletedException ("Input UTxOs depleted!" )
136
136
if self .random_generator :
@@ -141,7 +141,7 @@ def _get_next_random(self, utxos: List[UTxO]) -> UTxO:
141
141
raise UTxOSelectionException (f"Random index: { i } out of range!" )
142
142
else :
143
143
i = random .randint (0 , len (utxos ) - 1 )
144
- return utxos . pop ( i )
144
+ return i , utxos [ i ]
145
145
146
146
def _random_select_subset (self ,
147
147
amount : Value ,
@@ -151,9 +151,10 @@ def _random_select_subset(self,
151
151
while not amount <= selected_amount :
152
152
if not remaining :
153
153
raise InputUTxODepletedException ("Input UTxOs depleted!" )
154
- to_add = self ._get_next_random (remaining )
154
+ i , to_add = self ._get_next_random (remaining )
155
155
selected .append (to_add )
156
156
selected_amount += to_add .output .amount
157
+ remaining .pop (i )
157
158
158
159
@staticmethod
159
160
def _split_by_asset (value : Value ) -> List [Value ]:
@@ -197,18 +198,21 @@ def _improve(self,
197
198
ideal : Value ,
198
199
upper_bound : Value ,
199
200
max_input_count : int ):
200
- if not remaining or self ._find_diff_by_former (upper_bound , selected_amount ) <= 0 :
201
+ if not remaining or self ._find_diff_by_former (ideal , selected_amount ) <= 0 :
202
+ # In case where there is no remaining UTxOs or we already selected more than ideal,
203
+ # we cannot improve by randomly adding more UTxOs, therefore return immediate.
201
204
return
202
205
if max_input_count and len (selected ) > max_input_count :
203
206
raise MaxInputCountExceededException (f"Max input count: { max_input_count } exceeded!" )
204
207
205
- to_add = self ._get_next_random (remaining )
208
+ i , to_add = self ._get_next_random (remaining )
206
209
if abs (self ._find_diff_by_former (ideal , selected_amount + to_add .output .amount )) < \
207
210
abs (self ._find_diff_by_former (ideal , selected_amount )) and \
208
211
self ._find_diff_by_former (upper_bound , selected_amount + to_add .output .amount ) >= 0 :
209
212
selected .append (to_add )
210
213
selected_amount += to_add .output .amount
211
- self ._improve (selected , selected_amount , remaining , ideal , upper_bound , max_input_count )
214
+
215
+ self ._improve (selected , selected_amount , remaining [:i ] + remaining [i + 1 :], ideal , upper_bound , max_input_count )
212
216
213
217
def select (self ,
214
218
utxos : List [UTxO ],
@@ -254,7 +258,7 @@ def select(self,
254
258
255
259
if change .coin < min_change_amount :
256
260
additional , _ = self .select (remaining ,
257
- [TransactionOutput (None , min_change_amount )],
261
+ [TransactionOutput (None , min_change_amount - change . coin )],
258
262
context ,
259
263
max_input_count - len (selected ) if max_input_count else None ,
260
264
include_max_fee = False ,
0 commit comments