Bläddra i källkod

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

skoupidi 2 år sedan
förälder
incheckning
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 half_split = Arg::with_name("half-split")
+        .long("half-split")
+        .help("Split the output coin into two equal halves");
+
     let transfer =
         SubCommand::with_name("transfer").about("Create a payment transaction").args(&vec![
             amount.clone(),
@@ -199,6 +203,7 @@ pub fn generate_completions(shell: &str) -> Result<()> {
             recipient.clone(),
             spend_hook.clone(),
             user_data.clone(),
+            half_split,
         ]);
 
     // Otc

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

@@ -215,6 +215,10 @@ enum Subcmd {
 
         /// Optional user data to use
         user_data: Option<String>,
+
+        #[structopt(long)]
+        /// Split the output coin into two equal halves
+        half_split: bool,
     },
 
     /// OTC atomic swap
@@ -915,7 +919,7 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
             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?;
 
             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,
             };
 
-            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,
                 Err(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}");
 
             // Already scanned last known block
-            if height >= last {
+            if height > last {
                 return Ok(())
             }
 

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

@@ -45,6 +45,7 @@ impl Drk {
         recipient: PublicKey,
         spend_hook: Option<FuncId>,
         user_data: Option<pallas::Base>,
+        half_split: bool,
     ) -> Result<Transaction> {
         // First get all unspent OwnCoins to see what our balance is
         let owncoins = self.get_token_coins(&token_id).await?;
@@ -121,6 +122,7 @@ impl Drk {
             mint_pk,
             burn_zkbin,
             burn_pk,
+            half_split,
         )?;
 
         // 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
 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
-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
 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
 /// * `burn_zkbin`: `Burn_V1` zkas circuit ZkBinary
 /// * `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:
 ///
@@ -100,6 +102,7 @@ pub fn make_transfer_call(
     mint_pk: ProvingKey,
     burn_zkbin: ZkBinary,
     burn_pk: ProvingKey,
+    half_split: bool,
 ) -> Result<(MoneyTransferParamsV1, TransferCallSecrets, Vec<OwnCoin>)> {
     debug!(target: "contract::money::client::transfer", "Building Money::TransferV1 contract call");
     if value == 0 {
@@ -137,14 +140,35 @@ pub fn make_transfer_call(
         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 {
         outputs.push(TransferCallOutput {

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

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

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

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

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

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

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

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