Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
429 changes: 304 additions & 125 deletions Cargo.lock

Large diffs are not rendered by default.

31 changes: 17 additions & 14 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ frost-rerandomized = "2.0.0-rc.0"
frostd = { path = "frostd" }
futures = "0.3.31"
futures-util = "0.3.31"
halo2_gadgets = "0.3.0"
halo2_proofs = "0.3.0"
halo2_gadgets = "0.4.0"
halo2_proofs = "0.3.2"
hex = "0.4.3"
itertools = "0.14.0"
lazy_static = "1.5.0"
message-io = "0.18"
orchard = "0.10.1"
orchard = "0.11.0"
pczt = "0.5"
postcard = "1.1.1"
rand = "0.8.5"
rand_core = "0.6.4"
Expand All @@ -43,7 +44,7 @@ regex = "1.11.1"
reqwest = { version = "0.12.12", default-features = false }
rpassword = "7.3.1"
rustls = "0.23.21"
sapling-crypto = "0.4.0"
sapling-crypto = "0.5.0"
serde = "1.0.204"
serde-hex = "0.1.0"
serde_json = "1.0.138"
Expand All @@ -60,16 +61,18 @@ tracing = "0.1"
tracing-subscriber = "0.3"
uuid = "1.11.0"
xeddsa = "1.0.2"
zcash_address = "0.6.2"
zcash_client_backend = "0.16.0"
zcash_encoding = "0.2.2"
zcash_keys = "0.6.0"
zcash_primitives = "0.21.0"
zcash_proofs = "0.21.0"
zcash_protocol = "0.4.3"
zcash_address = "0.10.1"
zcash_client_backend = "0.21.0"
zcash_encoding = "0.3.0"
zcash_keys = "0.12.0"
zcash_primitives = "0.26.1"
zcash_proofs = "0.26.1"
zcash_protocol = "0.7.1"
zcash_transparent = "0.6"
zeroize = "1.8.1"

[patch.crates-io]
# TODO: remove this when https://github.com/zcash/orchard/issues/430 is fully
# addressed and a new release is made
orchard = { git = "https://github.com/conradoplg/orchard.git", rev = "f0c88b78a1d70d55ce6bb480566d132e57d5607b" }
# TODO: remove this when https://github.com/zcash/orchard/pull/475 is merged,
# and a all ECC crates are updated to point to the orchard version that includes
# it.
orchard = { git = "https://github.com/conradoplg/orchard.git", rev = "4d001c5b6ad15373e68a5923d5868fbe42daba96" }
2 changes: 2 additions & 0 deletions zcash-sign/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ halo2_proofs = { workspace = true }
hex = { workspace = true }
lazy_static = { workspace = true }
orchard = { workspace = true, features = ["unstable-frost"] }
pczt = { workspace = true, features = ["signer"] }
rand = { workspace = true }
rand_core = { workspace = true }
sapling-crypto = { workspace = true }
Expand All @@ -26,3 +27,4 @@ zcash_keys = { workspace = true, features = ["test-dependencies", "orchard"] }
zcash_primitives = { workspace = true }
zcash_proofs = { workspace = true, features = ["bundled-prover"] }
zcash_protocol = { workspace = true }
zcash_transparent = { workspace = true, features = ["transparent-inputs"] }
14 changes: 12 additions & 2 deletions zcash-sign/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ pub(crate) enum Command {
/// The SpendValidatingKey (VerifyingKey in FROST) to use
#[arg(short, long)]
ak: String,
/// The network the address will be generated for: "main" or "test" (default: "main")
#[arg(short, long)]
#[arg(default_value = "main")]
network: String,
/// Whether to generate a dummy Sapling key along with the Orchard key.
/// Require for Ywallet use since it does not support Orchard-only keys.
/// DANGER: make sure to not send to the Sapling address, or your
Expand All @@ -31,8 +35,14 @@ pub(crate) enum Command {
#[arg(short = 'o', long)]
tx: String,

/// The UnifiedFullViewingKey generated previously, in hex format
/// The UnifiedFullViewingKey generated previously, in hex format.
/// Not required for PCZTs, only for Ywallet transaction plans.
#[arg(short, long)]
ufvk: Option<String>,

/// The network the address will be generated for: "main" or "test" (default: "main")
#[arg(short, long)]
ufvk: String,
#[arg(default_value = "main")]
network: String,
},
}
3 changes: 2 additions & 1 deletion zcash-sign/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod generate;
mod sign;
pub(crate) mod sign_ywallet;
pub mod transaction_plan;

pub use generate::generate;
pub use sign::sign;
pub use sign::{sign, Input};
42 changes: 26 additions & 16 deletions zcash-sign/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,33 @@ mod args;

use std::{error::Error, fs};

use base64::{prelude::BASE64_STANDARD, Engine as _};
use clap::Parser as _;
use eyre::eyre;
use pczt::Pczt;
use rand::{thread_rng, RngCore};

use orchard::keys::{Scope, SpendValidatingKey};
use sapling_crypto::zip32::ExtendedSpendingKey;
use zcash_client_backend::address::UnifiedAddress;
use zcash_keys::keys::UnifiedFullViewingKey;
use zcash_protocol::consensus::MainNetwork;

use zcash_sign::transaction_plan::TransactionPlan;
use zcash_protocol::consensus::{self};

use args::{Args, Command};

fn generate(args: &Command) -> Result<(), Box<dyn Error>> {
let Command::Generate {
ak,
danger_dummy_sapling,
network,
} = args
else {
panic!("invalid Command");
};
let params: consensus::Network = match network.as_str() {
"main" => consensus::Network::MainNetwork,
"test" => consensus::Network::TestNetwork,
_ => Err(eyre!("Invalid network: {}", network))?,
};

let ak = hex::decode(ak.trim()).unwrap();
let ak = SpendValidatingKey::from_bytes(&ak).ok_or(eyre!("Invalid ak"))?;
Expand All @@ -37,7 +41,7 @@ fn generate(args: &Command) -> Result<(), Box<dyn Error>> {
let unified_address = UnifiedAddress::from_receivers(Some(orchard_address), None, None)
.expect("must work with a shielded address");
// TODO: make params selectable
let unified_address_str = unified_address.encode(&MainNetwork);
let unified_address_str = unified_address.encode(&params);

println!("Orchard-only unified address: {unified_address_str:?}");

Expand All @@ -51,7 +55,7 @@ fn generate(args: &Command) -> Result<(), Box<dyn Error>> {
};

let ufvk = UnifiedFullViewingKey::new(sapling_fvk, Some(fvk.clone())).unwrap();
let ufvk_str = ufvk.encode(&MainNetwork);
let ufvk_str = ufvk.encode(&params);

println!("Unified Full Viewing Key: {ufvk_str:?}");

Expand All @@ -63,26 +67,32 @@ fn sign(args: &Command) -> Result<(), Box<dyn Error>> {
tx_plan,
ufvk,
tx: tx_path,
network,
} = args
else {
panic!("invalid Command")
};
// TODO: make configurable
let network = MainNetwork;
let params: consensus::Network = match network.as_str() {
"main" => consensus::Network::MainNetwork,
"test" => consensus::Network::TestNetwork,
_ => Err(eyre!("Invalid network: {}", network))?,
};

let tx_plan = fs::read_to_string(tx_plan)?;
let tx_plan: TransactionPlan = serde_json::from_str(&tx_plan)?;
let tx_plan = fs::read(tx_plan)?;
let input = match Pczt::parse(&tx_plan) {
Ok(pczt) => zcash_sign::Input::Pczt(pczt),
Err(_) => zcash_sign::Input::YwalletTxPlan(serde_json::from_slice(&tx_plan)?),
};

let ufvk = UnifiedFullViewingKey::decode(&network, ufvk.trim()).unwrap();
let ufvk = ufvk
.clone()
.map(|ufvk_str| UnifiedFullViewingKey::decode(&params, ufvk_str.trim()).unwrap());

let mut rng = thread_rng();

let tx = zcash_sign::sign(&mut rng, &tx_plan, &ufvk)?;

let mut tx_bytes = vec![];
tx.write(&mut tx_bytes).unwrap();
let tx_bytes = zcash_sign::sign(&mut rng, params, &input, ufvk.as_ref())?;

fs::write(tx_path, BASE64_STANDARD.encode(&tx_bytes))?;
fs::write(tx_path, tx_bytes)?;
println!("Tx written to {tx_path}");

Ok(())
Expand Down
Loading
Loading