Browse Source

drk/transfer: added new --half-split to split output coin into two equal halves

skoupidi 2 years ago
parent
commit
6b5ae99724

+ 5 - 0
bin/drk/src/cli_util.rs

@@ -192,6 +192,10 @@ pub fn generate_completions(shell: &str) -> Result<()> {
 
 
     let user_data = Arg::with_name("user-data").help("Optional user data to use");
     let user_data = Arg::with_name("user-data").help("Optional user data to use");
 
 
+    let half_split = Arg::with_name("half-split")
+        .long("half-split")
+        .help("Split the output coin into two equal halves");
+
     let transfer =
     let transfer =
         SubCommand::with_name("transfer").about("Create a payment transaction").args(&vec![
         SubCommand::with_name("transfer").about("Create a payment transaction").args(&vec![
             amount.clone(),
             amount.clone(),
@@ -199,6 +203,7 @@ pub fn generate_completions(shell: &str) -> Result<()> {
             recipient.clone(),
             recipient.clone(),
             spend_hook.clone(),
             spend_hook.clone(),
             user_data.clone(),
             user_data.clone(),
+            half_split,
         ]);
         ]);
 
 
     // Otc
     // Otc

+ 9 - 2
bin/drk/src/main.rs

@@ -215,6 +215,10 @@ enum Subcmd {
 
 
         /// Optional user data to use
         /// Optional user data to use
         user_data: Option<String>,
         user_data: Option<String>,
+
+        #[structopt(long)]
+        /// Split the output coin into two equal halves
+        half_split: bool,
     },
     },
 
 
     /// OTC atomic swap
     /// OTC atomic swap
@@ -915,7 +919,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
             Ok(())
             Ok(())
         }
         }
 
 
-        Subcmd::Transfer { amount, token, recipient, spend_hook, user_data } => {
+        Subcmd::Transfer { amount, token, recipient, spend_hook, user_data, half_split } => {
             let drk = Drk::new(args.wallet_path, args.wallet_pass, Some(args.endpoint), ex).await?;
             let drk = Drk::new(args.wallet_path, args.wallet_pass, Some(args.endpoint), ex).await?;
 
 
             if let Err(e) = f64::from_str(&amount) {
             if let Err(e) = f64::from_str(&amount) {
@@ -971,7 +975,10 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
                 None => None,
                 None => None,
             };
             };
 
 
-            let tx = match drk.transfer(&amount, token_id, rcpt, spend_hook, user_data).await {
+            let tx = match drk
+                .transfer(&amount, token_id, rcpt, spend_hook, user_data, half_split)
+                .await
+            {
                 Ok(t) => t,
                 Ok(t) => t,
                 Err(e) => {
                 Err(e) => {
                     eprintln!("Failed to create payment transaction: {e:?}");
                     eprintln!("Failed to create payment transaction: {e:?}");

+ 1 - 1
bin/drk/src/rpc.rs

@@ -263,7 +263,7 @@ impl Drk {
             println!("Last known block number reported by darkfid: {last}");
             println!("Last known block number reported by darkfid: {last}");
 
 
             // Already scanned last known block
             // Already scanned last known block
-            if height >= last {
+            if height > last {
                 return Ok(())
                 return Ok(())
             }
             }
 
 

+ 2 - 0
bin/drk/src/transfer.rs

@@ -45,6 +45,7 @@ impl Drk {
         recipient: PublicKey,
         recipient: PublicKey,
         spend_hook: Option<FuncId>,
         spend_hook: Option<FuncId>,
         user_data: Option<pallas::Base>,
         user_data: Option<pallas::Base>,
+        half_split: bool,
     ) -> Result<Transaction> {
     ) -> Result<Transaction> {
         // First get all unspent OwnCoins to see what our balance is
         // First get all unspent OwnCoins to see what our balance is
         let owncoins = self.get_token_coins(&token_id).await?;
         let owncoins = self.get_token_coins(&token_id).await?;
@@ -121,6 +122,7 @@ impl Drk {
             mint_pk,
             mint_pk,
             burn_zkbin,
             burn_zkbin,
             burn_pk,
             burn_pk,
+            half_split,
         )?;
         )?;
 
 
         // Encode the call
         // Encode the call

+ 3 - 1
doc/src/testnet/token.md

@@ -4,7 +4,9 @@ Now that you have your wallet set up, you will need some native `DRK`
 tokens in order to be able to perform transactions, since that token
 tokens in order to be able to perform transactions, since that token
 is used to pay the transaction fees. You can obtain `DRK` either by
 is used to pay the transaction fees. You can obtain `DRK` either by
 successfully mining a block that gets finalized or by asking for some
 successfully mining a block that gets finalized or by asking for some
-by the community on `darkirc` and/or your comrades.
+by the community on `darkirc` and/or your comrades. Don't forget to
+tell them to add the `--half-split` flag when they create the transfer
+transaction, so you get more than one coins to play with.
 
 
 After you request some `DRK` and the other party submitted a transaction
 After you request some `DRK` and the other party submitted a transaction
 to the network, it should be in the consensus' mempool, waiting for
 to the network, it should be in the consensus' mempool, waiting for

+ 32 - 8
src/contract/money/src/client/transfer_v1/mod.rs

@@ -80,6 +80,8 @@ pub fn select_coins(coins: Vec<OwnCoin>, min_value: u64) -> Result<(Vec<OwnCoin>
 /// * `mint_pk`: Proving key for the `Mint_V1` zk circuit
 /// * `mint_pk`: Proving key for the `Mint_V1` zk circuit
 /// * `burn_zkbin`: `Burn_V1` zkas circuit ZkBinary
 /// * `burn_zkbin`: `Burn_V1` zkas circuit ZkBinary
 /// * `burn_pk`: Proving key for the `Burn_V1` zk circuit
 /// * `burn_pk`: Proving key for the `Burn_V1` zk circuit
+/// * `half_split`: Flag indicating to split the output coin into
+///    two equal halves.
 ///
 ///
 /// Returns a tuple of:
 /// Returns a tuple of:
 ///
 ///
@@ -100,6 +102,7 @@ pub fn make_transfer_call(
     mint_pk: ProvingKey,
     mint_pk: ProvingKey,
     burn_zkbin: ZkBinary,
     burn_zkbin: ZkBinary,
     burn_pk: ProvingKey,
     burn_pk: ProvingKey,
+    half_split: bool,
 ) -> Result<(MoneyTransferParamsV1, TransferCallSecrets, Vec<OwnCoin>)> {
 ) -> Result<(MoneyTransferParamsV1, TransferCallSecrets, Vec<OwnCoin>)> {
     debug!(target: "contract::money::client::transfer", "Building Money::TransferV1 contract call");
     debug!(target: "contract::money::client::transfer", "Building Money::TransferV1 contract call");
     if value == 0 {
     if value == 0 {
@@ -137,14 +140,35 @@ pub fn make_transfer_call(
         inputs.push(input);
         inputs.push(input);
     }
     }
 
 
-    outputs.push(TransferCallOutput {
-        public_key: recipient,
-        value,
-        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),
-    });
+    // Check if we should split the output into two equal halves
+    if half_split {
+        let value = value / 2;
+        outputs.push(TransferCallOutput {
+            public_key: recipient,
+            value,
+            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),
+        });
+        outputs.push(TransferCallOutput {
+            public_key: recipient,
+            value,
+            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),
+        });
+    } else {
+        outputs.push(TransferCallOutput {
+            public_key: recipient,
+            value,
+            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),
+        });
+    }
 
 
     if change_value > 0 {
     if change_value > 0 {
         outputs.push(TransferCallOutput {
         outputs.push(TransferCallOutput {

+ 2 - 0
src/contract/money/tests/delayed_tx.rs

@@ -98,6 +98,7 @@ fn delayed_tx() -> Result<()> {
             mint_pk.clone(),
             mint_pk.clone(),
             burn_zkbin.clone(),
             burn_zkbin.clone(),
             burn_pk.clone(),
             burn_pk.clone(),
+            false,
         )?;
         )?;
 
 
         let mut output_coins = vec![];
         let mut output_coins = vec![];
@@ -243,6 +244,7 @@ fn delayed_tx() -> Result<()> {
                 &[bob_coins[0].clone()],
                 &[bob_coins[0].clone()],
                 bob_coins[0].note.token_id,
                 bob_coins[0].note.token_id,
                 current_block_height,
                 current_block_height,
+                false,
             )
             )
             .await?;
             .await?;
 
 

+ 1 - 0
src/contract/money/tests/integration.rs

@@ -60,6 +60,7 @@ fn money_integration() -> Result<()> {
                 &[alice_coins[0].clone()],
                 &[alice_coins[0].clone()],
                 alice_coins[0].note.token_id,
                 alice_coins[0].note.token_id,
                 current_block_height,
                 current_block_height,
+                false,
             )
             )
             .await?;
             .await?;
 
 

+ 4 - 0
src/contract/money/tests/mint_pay_swap.rs

@@ -142,6 +142,7 @@ fn mint_pay_swap() -> Result<()> {
                 &alice_owncoins,
                 &alice_owncoins,
                 alice_token_id,
                 alice_token_id,
                 current_block_height,
                 current_block_height,
+                false,
             )
             )
             .await?;
             .await?;
 
 
@@ -191,6 +192,7 @@ fn mint_pay_swap() -> Result<()> {
                 &bob_owncoins_tmp,
                 &bob_owncoins_tmp,
                 bob_token_id,
                 bob_token_id,
                 current_block_height,
                 current_block_height,
+                false,
             )
             )
             .await?;
             .await?;
 
 
@@ -296,6 +298,7 @@ fn mint_pay_swap() -> Result<()> {
                 &alice_owncoins,
                 &alice_owncoins,
                 alice_token_id,
                 alice_token_id,
                 current_block_height,
                 current_block_height,
+                false,
             )
             )
             .await?;
             .await?;
 
 
@@ -341,6 +344,7 @@ fn mint_pay_swap() -> Result<()> {
                 &bob_owncoins,
                 &bob_owncoins,
                 bob_token_id,
                 bob_token_id,
                 current_block_height,
                 current_block_height,
+                false,
             )
             )
             .await?;
             .await?;
 
 

+ 3 - 0
src/contract/test-harness/src/money_transfer.rs

@@ -36,6 +36,7 @@ use super::{Holder, TestHarness};
 
 
 impl TestHarness {
 impl TestHarness {
     /// Create a `Money::Transfer` transaction.
     /// Create a `Money::Transfer` transaction.
+    #[allow(clippy::too_many_arguments)]
     pub async fn transfer(
     pub async fn transfer(
         &mut self,
         &mut self,
         amount: u64,
         amount: u64,
@@ -44,6 +45,7 @@ impl TestHarness {
         owncoins: &[OwnCoin],
         owncoins: &[OwnCoin],
         token_id: TokenId,
         token_id: TokenId,
         block_height: u32,
         block_height: u32,
+        half_split: bool,
     ) -> Result<(Transaction, (MoneyTransferParamsV1, Option<MoneyFeeParamsV1>), Vec<OwnCoin>)>
     ) -> Result<(Transaction, (MoneyTransferParamsV1, Option<MoneyFeeParamsV1>), Vec<OwnCoin>)>
     {
     {
         let wallet = self.holders.get(holder).unwrap();
         let wallet = self.holders.get(holder).unwrap();
@@ -66,6 +68,7 @@ impl TestHarness {
             mint_pk.clone(),
             mint_pk.clone(),
             burn_zkbin.clone(),
             burn_zkbin.clone(),
             burn_pk.clone(),
             burn_pk.clone(),
+            half_split,
         )?;
         )?;
 
 
         // Encode the call
         // Encode the call