@@ -220,21 +220,23 @@ impl TransactionBuilder {
220220 associated_inputs. entry ( output. clone ( ) ) . or_default ( ) . push ( input) ;
221221 }
222222 }
223- // Phase 2: Improvement
224- for output in outputs. iter_mut ( ) {
225- let associated = associated_inputs. get_mut ( output) . unwrap ( ) ;
226- for input in associated. iter_mut ( ) {
227- let random_index = rng. gen_range ( 0 ..available_inputs. len ( ) ) ;
228- let new_input = available_inputs. get_mut ( random_index) . unwrap ( ) ;
229- let cur = from_bignum ( & input. output . amount . coin ) ;
230- let new = from_bignum ( & new_input. output . amount . coin ) ;
231- let min = from_bignum ( & output. amount . coin ) ;
232- let ideal = 2 * min;
233- let max = 3 * min;
234- let move_closer = ( ideal as i128 - new as i128 ) . abs ( ) < ( ideal as i128 - cur as i128 ) . abs ( ) ;
235- let not_exceed_max = new < max;
236- if move_closer && not_exceed_max {
237- std:: mem:: swap ( input, new_input) ;
223+ if !available_inputs. is_empty ( ) {
224+ // Phase 2: Improvement
225+ for output in outputs. iter_mut ( ) {
226+ let associated = associated_inputs. get_mut ( output) . unwrap ( ) ;
227+ for input in associated. iter_mut ( ) {
228+ let random_index = rng. gen_range ( 0 ..available_inputs. len ( ) ) ;
229+ let new_input = available_inputs. get_mut ( random_index) . unwrap ( ) ;
230+ let cur = from_bignum ( & input. output . amount . coin ) ;
231+ let new = from_bignum ( & new_input. output . amount . coin ) ;
232+ let min = from_bignum ( & output. amount . coin ) ;
233+ let ideal = 2 * min;
234+ let max = 3 * min;
235+ let move_closer = ( ideal as i128 - new as i128 ) . abs ( ) < ( ideal as i128 - cur as i128 ) . abs ( ) ;
236+ let not_exceed_max = new < max;
237+ if move_closer && not_exceed_max {
238+ std:: mem:: swap ( input, new_input) ;
239+ }
238240 }
239241 }
240242 }
@@ -2064,7 +2066,6 @@ mod tests {
20642066 assert_eq ! ( 3u8 , tx. inputs( ) . get( 1 ) . transaction_id( ) . 0 [ 0 ] ) ;
20652067 }
20662068
2067-
20682069 #[ test]
20692070 fn tx_builder_cip2_random_improve ( ) {
20702071 // we have a = 1 to test increasing fees when more inputs are added
@@ -2117,6 +2118,31 @@ mod tests {
21172118 assert ! ( input_total >= Value :: new( & tx_builder. min_fee( ) . unwrap( ) . checked_add( & to_bignum( COST ) ) . unwrap( ) ) ) ;
21182119 }
21192120
2121+ #[ test]
2122+ fn tx_builder_cip2_random_improve_when_using_all_available_inputs ( ) {
2123+ // we have a = 1 to test increasing fees when more inputs are added
2124+ let linear_fee = LinearFee :: new ( & to_bignum ( 1 ) , & to_bignum ( 0 ) ) ;
2125+ let mut tx_builder = TransactionBuilder :: new (
2126+ & linear_fee,
2127+ & Coin :: zero ( ) ,
2128+ & to_bignum ( 0 ) ,
2129+ 9999 ,
2130+ 9999 ,
2131+ & to_bignum ( 0 ) ,
2132+ ) ;
2133+ const COST : u64 = 1000 ;
2134+ tx_builder. add_output ( & TransactionOutput :: new (
2135+ & Address :: from_bech32 ( "addr1vyy6nhfyks7wdu3dudslys37v252w2nwhv0fw2nfawemmnqs6l44z" ) . unwrap ( ) ,
2136+ & Value :: new ( & to_bignum ( COST ) )
2137+ ) ) . unwrap ( ) ;
2138+ let mut available_inputs = TransactionUnspentOutputs :: new ( ) ;
2139+ available_inputs. add ( & make_input ( 1u8 , Value :: new ( & to_bignum ( 800 ) ) ) ) ;
2140+ available_inputs. add ( & make_input ( 2u8 , Value :: new ( & to_bignum ( 800 ) ) ) ) ;
2141+ let add_inputs_res =
2142+ tx_builder. add_inputs_from ( & available_inputs, CoinSelectionStrategyCIP2 :: RandomImprove ) ;
2143+ assert ! ( add_inputs_res. is_ok( ) , "{:?}" , add_inputs_res. err( ) ) ;
2144+ }
2145+
21202146 fn build_tx_pay_to_multisig ( ) {
21212147 let linear_fee = LinearFee :: new ( & to_bignum ( 10 ) , & to_bignum ( 2 ) ) ;
21222148 let mut tx_builder =
@@ -2322,3 +2348,4 @@ mod tests {
23222348 assert_eq ! ( _deser_t. body( ) . auxiliary_data_hash. unwrap( ) , utils:: hash_auxiliary_data( & auxiliary_data) ) ;
23232349 }
23242350}
2351+
0 commit comments