Skip to content

Commit 7c98e4a

Browse files
committed
Add pczt send-without-storing command
1 parent 195b6ff commit 7c98e4a

File tree

3 files changed

+88
-0
lines changed

3 files changed

+88
-0
lines changed

src/commands/pczt.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub(crate) mod inspect;
77
pub(crate) mod prove;
88
pub(crate) mod redact;
99
pub(crate) mod send;
10+
pub(crate) mod send_without_storing;
1011
pub(crate) mod shield;
1112
pub(crate) mod sign;
1213
pub(crate) mod update_with_derivation;
@@ -36,6 +37,10 @@ pub(crate) enum Command {
3637
Combine(combine::Command),
3738
/// Extract a finished transaction and send it
3839
Send(send::Command),
40+
/// Extract a finished transaction and send it, without storing in the wallet
41+
///
42+
/// This should be used for PCZTs created with `pczt create-manual`.
43+
SendWithoutStoring(send_without_storing::Command),
3944
#[cfg(feature = "pczt-qr")]
4045
/// Render a PCZT as an animated QR code
4146
ToQr(qr::Send),
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use anyhow::anyhow;
2+
use clap::Args;
3+
use pczt::{
4+
roles::{spend_finalizer::SpendFinalizer, tx_extractor::TransactionExtractor},
5+
Pczt,
6+
};
7+
use tokio::io::{stdin, AsyncReadExt};
8+
use zcash_client_backend::proto::service;
9+
use zcash_proofs::prover::LocalTxProver;
10+
11+
use crate::{
12+
config::WalletConfig,
13+
error,
14+
remote::{tor_client, Servers},
15+
};
16+
17+
// Options accepted for the `pczt send-without-storing` command
18+
#[derive(Debug, Args)]
19+
pub(crate) struct Command {
20+
/// The server to send via (default is \"ecc\")
21+
#[arg(short, long)]
22+
#[arg(default_value = "ecc", value_parser = Servers::parse)]
23+
server: Servers,
24+
25+
/// Disable connections via TOR
26+
#[arg(long)]
27+
disable_tor: bool,
28+
}
29+
30+
impl Command {
31+
pub(crate) async fn run(self, wallet_dir: Option<String>) -> Result<(), anyhow::Error> {
32+
let config = WalletConfig::read(wallet_dir.as_ref())?;
33+
let params = config.network();
34+
35+
let server = self.server.pick(params)?;
36+
let mut client = if self.disable_tor {
37+
server.connect_direct().await?
38+
} else {
39+
server.connect(|| tor_client(wallet_dir.as_ref())).await?
40+
};
41+
42+
let mut buf = vec![];
43+
stdin().read_to_end(&mut buf).await?;
44+
45+
let pczt = Pczt::parse(&buf).map_err(|e| anyhow!("Failed to read PCZT: {:?}", e))?;
46+
47+
let prover = LocalTxProver::bundled();
48+
let (spend_vk, output_vk) = prover.verifying_keys();
49+
50+
let finalized = SpendFinalizer::new(pczt)
51+
.finalize_spends()
52+
.map_err(|e| anyhow!("Failed to finalize PCZT spends: {e:?}"))?;
53+
54+
let tx = TransactionExtractor::new(finalized)
55+
.with_sapling(&spend_vk, &output_vk)
56+
.extract()
57+
.map_err(|e| anyhow!("Failed to extract transaction from PCZT: {e:?}"))?;
58+
let txid = tx.txid();
59+
60+
// Send the transaction.
61+
println!("Sending transaction...");
62+
let raw_tx = {
63+
let mut raw_tx = service::RawTransaction::default();
64+
tx.write(&mut raw_tx.data).unwrap();
65+
raw_tx
66+
};
67+
let response = client.send_transaction(raw_tx).await?.into_inner();
68+
69+
if response.error_code != 0 {
70+
Err(error::Error::SendFailed {
71+
code: response.error_code,
72+
reason: response.error_message,
73+
}
74+
.into())
75+
} else {
76+
println!("{txid}");
77+
Ok(())
78+
}
79+
}
80+
}

src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ fn main() -> Result<(), anyhow::Error> {
187187
commands::pczt::Command::Sign(command) => command.run(wallet_dir).await,
188188
commands::pczt::Command::Combine(command) => command.run().await,
189189
commands::pczt::Command::Send(command) => command.run(wallet_dir).await,
190+
commands::pczt::Command::SendWithoutStoring(command) => {
191+
command.run(wallet_dir).await
192+
}
190193
#[cfg(feature = "pczt-qr")]
191194
commands::pczt::Command::ToQr(command) => {
192195
command

0 commit comments

Comments
 (0)