Просмотр исходного кода

contract/money/client: shuffle outputs of genesis mint and transfer as per task xo5Vne

skoupidi 1 год назад
Родитель
Сommit
e44bc17586

+ 10 - 6
src/contract/money/src/client/genesis_mint_v1.rs

@@ -26,7 +26,7 @@ use darkfi_sdk::{
     pasta::pallas,
 };
 use log::debug;
-use rand::rngs::OsRng;
+use rand::{prelude::SliceRandom, rngs::OsRng};
 
 use crate::{
     client::{
@@ -104,13 +104,17 @@ impl GenesisMintCallBuilder {
         let spend_hook = self.spend_hook.unwrap_or(FuncId::none());
         let user_data = self.user_data.unwrap_or(pallas::Base::ZERO);
 
+        // Shuffle the amounts vector so our outputs are not in order
+        let mut amounts = self.amounts.clone();
+        amounts.shuffle(&mut OsRng);
+
         // Building the anonymous outputs
         let input_blinds = vec![value_blind];
-        let mut output_blinds = Vec::with_capacity(self.amounts.len());
-        let mut outputs = Vec::with_capacity(self.amounts.len());
-        let mut proofs = Vec::with_capacity(self.amounts.len());
-        for (i, amount) in self.amounts.iter().enumerate() {
-            let value_blind = if i == self.amounts.len() - 1 {
+        let mut output_blinds = Vec::with_capacity(amounts.len());
+        let mut outputs = Vec::with_capacity(amounts.len());
+        let mut proofs = Vec::with_capacity(amounts.len());
+        for (i, amount) in amounts.iter().enumerate() {
+            let value_blind = if i == amounts.len() - 1 {
                 compute_remainder_blind(&input_blinds, &output_blinds)
             } else {
                 Blind::random(&mut OsRng)

+ 22 - 23
src/contract/money/src/client/transfer_v1/mod.rs

@@ -22,7 +22,7 @@ use darkfi_sdk::{
     pasta::pallas,
 };
 use log::{debug, error};
-use rand::rngs::OsRng;
+use rand::{prelude::SliceRandom, rngs::OsRng};
 
 use crate::{
     client::OwnCoin,
@@ -135,6 +135,10 @@ pub fn make_transfer_call(
     let mut outputs = vec![];
 
     let (spent_coins, change_value) = select_coins(coins, value)?;
+    if spent_coins.is_empty() {
+        error!(target: "contract::money::client::transfer", "Error: No coins selected");
+        return Err(ClientFailed::VerifyError(MoneyError::TransferMissingInputs.to_string()).into())
+    }
 
     for coin in spent_coins.iter() {
         let input = TransferCallInput {
@@ -148,27 +152,24 @@ pub fn make_transfer_call(
 
     // Check if we should split the output into two equal halves
     if half_split {
-        // Integer division is safe here as we are dividing by a constant.
-        #[allow(clippy::integer_division)]
+        // Cumpute each half value. If the value is odd,
+        // the remainder(1) will be appended to the second half.
         let mut half = value / 2;
 
-        // Add the first half
-        outputs.push(TransferCallOutput {
-            public_key: recipient,
-            value: half,
-            token_id,
-            spend_hook: output_spend_hook.unwrap_or(FuncId::none()),
-            user_data: output_user_data.unwrap_or(pallas::Base::ZERO),
-            blind: Blind::random(&mut OsRng),
-        });
-
-        // Handle the case where value is odd. If so, division by 2 will truncate the amount.
-        // e.g. in integer division, 3 / 2 == 1.
-        // Arithmetic side effects are safe here: no risk of overflow or panic.
-        #[allow(clippy::arithmetic_side_effects)]
-        if value % 2 != 0 {
-            half += 1;
+        // Add the first half, if its not zero
+        if half != 0 {
+            outputs.push(TransferCallOutput {
+                public_key: recipient,
+                value: half,
+                token_id,
+                spend_hook: output_spend_hook.unwrap_or(FuncId::none()),
+                user_data: output_user_data.unwrap_or(pallas::Base::ZERO),
+                blind: Blind::random(&mut OsRng),
+            });
         }
+
+        // Append the remainder and add the second half
+        half += value % 2;
         outputs.push(TransferCallOutput {
             public_key: recipient,
             value: half,
@@ -199,10 +200,8 @@ pub fn make_transfer_call(
         });
     }
 
-    if inputs.is_empty() {
-        error!(target: "contract::money::client::transfer", "Error: No inputs selected");
-        return Err(ClientFailed::VerifyError(MoneyError::TransferMissingInputs.to_string()).into())
-    }
+    // Shuffle the outputs
+    outputs.shuffle(&mut OsRng);
 
     let xfer_builder = TransferCallBuilder {
         clear_inputs: vec![],