Эх сурвалжийг харах

money_transfer: split coin selection into a separate function

x 2 жил өмнө
parent
commit
b855d33d9f

+ 27 - 13
src/contract/money/src/client/transfer_v1.rs

@@ -363,6 +363,30 @@ pub struct TransferCallBuilder {
 // low level api mixing concerns - owncoin, select, and build
 // low level api mixing concerns - owncoin, select, and build
 // unable to specify exact structure of tx (multiple outputs, clear and anon inputs)
 // unable to specify exact structure of tx (multiple outputs, clear and anon inputs)
 
 
+/// Select coins from `coins` of at least `min_value` in total.
+/// Different strategies can be used. This function uses the dumb strategy
+/// of selecting coins until we reach `min_value`.
+pub fn select_coins(coins: Vec<OwnCoin>, min_value: u64) -> Result<Vec<OwnCoin>> {
+    let mut total_value = 0;
+    let mut selected = vec![];
+
+    for coin in coins {
+        if total_value >= min_value {
+            break
+        }
+
+        total_value += coin.note.value;
+        selected.push(coin);
+    }
+
+    if total_value < min_value {
+        error!("Not enough value to build tx inputs");
+        return Err(ClientFailed::NotEnoughValue(total_value).into())
+    }
+
+    Ok(selected)
+}
+
 impl TransferCallBuilder {
 impl TransferCallBuilder {
     pub fn build(self) -> Result<TransferCallDebris> {
     pub fn build(self) -> Result<TransferCallDebris> {
         debug!("Building Money::TransferV1 contract call");
         debug!("Building Money::TransferV1 contract call");
@@ -395,14 +419,10 @@ impl TransferCallBuilder {
 
 
             clear_inputs.push(input);
             clear_inputs.push(input);
         } else {
         } else {
-            let mut inputs_value = 0;
-
-            for coin in self.coins.iter() {
-                if inputs_value >= self.value {
-                    debug!("inputs_value >= value");
-                    break
-                }
+            spent_coins = select_coins(self.coins, self.value)?;
 
 
+            let mut inputs_value = 0;
+            for coin in spent_coins.iter() {
                 let leaf_position = coin.leaf_position;
                 let leaf_position = coin.leaf_position;
                 let merkle_path = self.tree.witness(leaf_position, 0).unwrap();
                 let merkle_path = self.tree.witness(leaf_position, 0).unwrap();
                 inputs_value += coin.note.value;
                 inputs_value += coin.note.value;
@@ -416,12 +436,6 @@ impl TransferCallBuilder {
                 };
                 };
 
 
                 inputs.push(input);
                 inputs.push(input);
-                spent_coins.push(coin.clone());
-            }
-
-            if inputs_value < self.value {
-                error!("Not enough value to build tx inputs");
-                return Err(ClientFailed::NotEnoughValue(inputs_value).into())
             }
             }
 
 
             if inputs_value > self.value {
             if inputs_value > self.value {