Browse Source

drk: attach the fee right away in tx-from-calls using the provided secrets

skoupidi 6 tháng trước cách đây
mục cha
commit
b7a494ea95
4 tập tin đã thay đổi với 61 bổ sung12 xóa
  1. 3 1
      bin/drk/src/cli_util.rs
  2. 29 5
      bin/drk/src/interactive.rs
  3. 27 4
      bin/drk/src/main.rs
  4. 2 2
      doc/src/testnet/contract.md

+ 3 - 1
bin/drk/src/cli_util.rs

@@ -409,7 +409,9 @@ pub fn generate_completions(shell: &str) -> Result<String> {
         Arg::with_name("calls-map").help("Optional parent/children dependency map for the calls");
 
     let tx_from_calls = SubCommand::with_name("tx-from-calls")
-        .about("Create a transaction from newline-separated calls from stdin")
+        .about(
+            "Create a transaction from newline-separated calls from stdin and attach the fee call",
+        )
         .args(&[calls_map]);
 
     // Inspect

+ 29 - 5
bin/drk/src/interactive.rs

@@ -95,7 +95,7 @@ fn help(output: &mut Vec<String>) {
     output
         .push(String::from("\tattach-fee: Attach the fee call to a transaction given from stdin"));
     output.push(String::from(
-        "\ttx-from-calls: Create a transaction from newline-separated calls from stdin",
+        "\ttx-from-calls: Create a transaction from newline-separated calls from stdin and attach the fee call",
     ));
     output.push(String::from("\tinspect: Inspect a transaction from stdin"));
     output.push(String::from("\tbroadcast: Read a transaction from stdin and broadcast it"));
@@ -545,7 +545,7 @@ pub async fn interactive(
                 "otc" => handle_otc(drk, &parts, &input, &mut output).await,
                 "dao" => handle_dao(drk, &parts, &input, &mut output).await,
                 "attach-fee" => handle_attach_fee(drk, &input, &mut output).await,
-                "tx-from-calls" => handle_tx_from_calls(&parts, &input, &mut output).await,
+                "tx-from-calls" => handle_tx_from_calls(drk, &parts, &input, &mut output).await,
                 "inspect" => handle_inspect(&input, &mut output).await,
                 "broadcast" => handle_broadcast(drk, &input, &mut output).await,
                 "subscribe" => {
@@ -2352,7 +2352,12 @@ async fn handle_attach_fee(drk: &DrkPtr, input: &[String], output: &mut Vec<Stri
 }
 
 /// Auxiliary function to define the tx from calls command handling.
-async fn handle_tx_from_calls(parts: &[&str], input: &[String], output: &mut Vec<String>) {
+async fn handle_tx_from_calls(
+    drk: &DrkPtr,
+    parts: &[&str],
+    input: &[String],
+    output: &mut Vec<String>,
+) {
     // Check correct subcommand structure
     if parts.len() != 1 && parts.len() != 2 {
         output.push(String::from("Malformed `tx-from-calls` subcommand"));
@@ -2395,7 +2400,7 @@ async fn handle_tx_from_calls(parts: &[&str], input: &[String], output: &mut Vec
         return
     }
 
-    // Create a transaction from the mapped calls.
+    // Create a transaction from the mapped calls
     let (mut tx_builder, signature_secrets) = match tx_from_calls_mapped(&calls, &calls_map) {
         Ok(pair) => pair,
         Err(e) => {
@@ -2404,7 +2409,7 @@ async fn handle_tx_from_calls(parts: &[&str], input: &[String], output: &mut Vec
         }
     };
 
-    // Now build and sign the tx
+    // Now build and sign the fee-less tx
     let mut tx = match tx_builder.build() {
         Ok(tx) => tx,
         Err(e) => {
@@ -2421,6 +2426,25 @@ async fn handle_tx_from_calls(parts: &[&str], input: &[String], output: &mut Vec
     };
     tx.signatures.push(sigs);
 
+    // Attach its fee and grab its signature
+    if let Err(e) = drk.read().await.attach_fee(&mut tx).await {
+        output.push(format!("Failed to attach the fee call to the transaction: {e}"));
+        return
+    }
+    // Its safe to unwrap here since we know the fee signature
+    // is in the last position.
+    let fee_signature = tx.signatures.last().unwrap().clone();
+
+    // Re-sign the tx using the calls secrets
+    let sigs = match tx.create_sigs(&signature_secrets) {
+        Ok(s) => s,
+        Err(e) => {
+            output.push(format!("Failed to create the transaction signatures: {e}"));
+            return
+        }
+    };
+    tx.signatures = vec![sigs, fee_signature];
+
     output.push(base64::encode(&serialize_async(&tx).await));
 }
 

+ 27 - 4
bin/drk/src/main.rs

@@ -178,7 +178,7 @@ enum Subcmd {
     /// Attach the fee call to a transaction given from stdin
     AttachFee,
 
-    /// Create a transaction from newline-separated calls from stdin
+    /// Create a transaction from newline-separated calls from stdin and attach the fee call
     TxFromCalls {
         /// Optional parent/children dependency map for the calls
         calls_map: Option<String>,
@@ -2054,17 +2054,40 @@ async fn realmain(args: Args, ex: ExecutorPtr) -> Result<()> {
                 exit(1);
             }
 
-            // Create a transaction from the mapped calls.
+            // Create a transaction from the mapped calls
             let (mut tx_builder, signature_secrets) = tx_from_calls_mapped(&calls, &calls_map)?;
 
-            // Now build and sign the tx
+            // Now build the fee-less tx
             let mut tx = tx_builder.build()?;
             let sigs = tx.create_sigs(&signature_secrets)?;
             tx.signatures.push(sigs);
 
+            // Attach its fee and grab its signature
+            let drk = new_wallet(
+                network,
+                blockchain_config.cache_path,
+                blockchain_config.wallet_path,
+                blockchain_config.wallet_pass,
+                Some(blockchain_config.endpoint),
+                &ex,
+                args.fun,
+            )
+            .await;
+            if let Err(e) = drk.attach_fee(&mut tx).await {
+                eprintln!("Failed to attach the fee call to the transaction: {e}");
+                exit(2);
+            };
+            // Its safe to unwrap here since we know the fee signature
+            // is in the last position.
+            let fee_signature = tx.signatures.last().unwrap().clone();
+
+            // Re-sign the tx using the calls secrets
+            let sigs = tx.create_sigs(&signature_secrets)?;
+            tx.signatures = vec![sigs, fee_signature];
+
             println!("{}", base64::encode(&serialize_async(&tx).await));
 
-            Ok(())
+            drk.stop_rpc_client().await
         }
 
         Subcmd::Inspect => {

+ 2 - 2
doc/src/testnet/contract.md

@@ -180,7 +180,7 @@ actual registration transaction, attach a fee to it and broadcast it to
 the network:
 
 ```shell
-drk> tx-from-calls < ../smart-contract/register.call | attach-fee | broadcast
+drk> tx-from-calls < ../smart-contract/register.call | broadcast
 
 [mark_tx_spend] Processing transaction: 23ea7d01ae16389e71d73fa27748ce1633d39c6b55a4aa31d8f5ba1017a4f840
 [mark_tx_spend] Found Money contract in call 1
@@ -204,7 +204,7 @@ Then, we build the actual deregistration transaction again, attach its
 fee and broadcast it to the network:
 
 ```shell
-drk> tx-from-calls < ../smart-contract/deregister.call | attach-fee | broadcast
+drk> tx-from-calls < ../smart-contract/deregister.call | broadcast
 
 [mark_tx_spend] Processing transaction: f3304e6f5673d9ece211af6dd85c70ec8c8e85e91439b8cffbcf5387b11de1d0
 [mark_tx_spend] Found Money contract in call 1