Add `propose` command.
This command takes the same arguments as `send`, but instead of executing a transaction, it simply creates and prints out the proposal for the transaction without executing it.
This commit is contained in:
parent
f3449b6a45
commit
0973bfd868
|
@ -1 +1,2 @@
|
|||
/target
|
||||
/zec_sqlite_wallet*
|
||||
|
|
|
@ -529,8 +529,7 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
|||
[[package]]
|
||||
name = "equihash"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab579d7cf78477773b03e80bc2f89702ef02d7112c711d54ca93dcdce68533d5"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=236cd569ee4a824d98920d1a61b8cc2b90ceba1d#236cd569ee4a824d98920d1a61b8cc2b90ceba1d"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
"byteorder",
|
||||
|
@ -555,8 +554,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "f4jumble"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a83e8d7fd0c526af4aad893b7c9fe41e2699ed8a776a6c74aecdeafe05afc75"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=236cd569ee4a824d98920d1a61b8cc2b90ceba1d#236cd569ee4a824d98920d1a61b8cc2b90ceba1d"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
]
|
||||
|
@ -1842,9 +1840,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "shardtree"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c19f96dde3a8693874f7e7c53d95616569b4009379a903789efbd448f4ea9cc7"
|
||||
checksum = "dbf20c7a2747d9083092e3a3eeb9a7ed75577ae364896bebbc5e0bdcd4e97735"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"either",
|
||||
|
@ -2611,8 +2609,7 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546"
|
|||
[[package]]
|
||||
name = "zcash_address"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8944af5c206cf2e37020ad54618e1825501b98548d35a638b73e0ec5762df8d5"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=236cd569ee4a824d98920d1a61b8cc2b90ceba1d#236cd569ee4a824d98920d1a61b8cc2b90ceba1d"
|
||||
dependencies = [
|
||||
"bech32",
|
||||
"bs58",
|
||||
|
@ -2623,8 +2620,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_client_backend"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6a382af39be9ee5a3788157145c404b7cd19acc440903f6c34b09fb44f0e991"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=236cd569ee4a824d98920d1a61b8cc2b90ceba1d#236cd569ee4a824d98920d1a61b8cc2b90ceba1d"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bech32",
|
||||
|
@ -2637,6 +2633,7 @@ dependencies = [
|
|||
"incrementalmerkletree",
|
||||
"memuse",
|
||||
"nom",
|
||||
"nonempty",
|
||||
"orchard",
|
||||
"percent-encoding",
|
||||
"prost",
|
||||
|
@ -2658,8 +2655,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_client_sqlite"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9e9603969437fa41e469f0c0e646e9604f04403304380c00433d8df91c046d2"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=236cd569ee4a824d98920d1a61b8cc2b90ceba1d#236cd569ee4a824d98920d1a61b8cc2b90ceba1d"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"byteorder",
|
||||
|
@ -2684,8 +2680,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_encoding"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f03391b81727875efa6ac0661a20883022b6fba92365dc121c48fa9b00c5aac0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=236cd569ee4a824d98920d1a61b8cc2b90ceba1d#236cd569ee4a824d98920d1a61b8cc2b90ceba1d"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"nonempty",
|
||||
|
@ -2707,10 +2702,10 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_primitives"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d17e4c94ca8d69d2fcf2be97522da5732a580eb2125cda3b150761952f8df8e6"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=236cd569ee4a824d98920d1a61b8cc2b90ceba1d#236cd569ee4a824d98920d1a61b8cc2b90ceba1d"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"bellman",
|
||||
"bip0039",
|
||||
"bitvec",
|
||||
"blake2b_simd",
|
||||
|
@ -2730,8 +2725,10 @@ dependencies = [
|
|||
"orchard",
|
||||
"rand",
|
||||
"rand_core",
|
||||
"redjubjub",
|
||||
"sha2",
|
||||
"subtle",
|
||||
"tracing",
|
||||
"zcash_address",
|
||||
"zcash_encoding",
|
||||
"zcash_note_encryption",
|
||||
|
@ -2740,8 +2737,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_proofs"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df0c99f65a840ff256c106b28d67d702d9759d206112473d4982c92003262406"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=236cd569ee4a824d98920d1a61b8cc2b90ceba1d#236cd569ee4a824d98920d1a61b8cc2b90ceba1d"
|
||||
dependencies = [
|
||||
"bellman",
|
||||
"blake2b_simd",
|
||||
|
|
|
@ -24,3 +24,9 @@ zcash_client_backend = { version = "0.10", features = ["lightwalletd-tonic"] }
|
|||
zcash_client_sqlite = { version = "0.8", features = ["unstable"] }
|
||||
zcash_primitives = "0.13"
|
||||
zcash_proofs = "0.13"
|
||||
|
||||
[patch.crates-io]
|
||||
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "236cd569ee4a824d98920d1a61b8cc2b90ceba1d" }
|
||||
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "236cd569ee4a824d98920d1a61b8cc2b90ceba1d" }
|
||||
zcash_client_backend = { git = "https://github.com/zcash/librustzcash.git", rev = "236cd569ee4a824d98920d1a61b8cc2b90ceba1d" }
|
||||
zcash_client_sqlite = { git = "https://github.com/zcash/librustzcash.git", rev = "236cd569ee4a824d98920d1a61b8cc2b90ceba1d" }
|
||||
|
|
|
@ -2,6 +2,7 @@ pub(crate) mod balance;
|
|||
pub(crate) mod init;
|
||||
pub(crate) mod list_tx;
|
||||
pub(crate) mod list_unspent;
|
||||
pub(crate) mod propose;
|
||||
pub(crate) mod reset;
|
||||
pub(crate) mod send;
|
||||
pub(crate) mod sync;
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
use anyhow::anyhow;
|
||||
use gumdrop::Options;
|
||||
|
||||
use zcash_client_backend::data_api::WalletRead;
|
||||
use zcash_client_backend::data_api::{SaplingInputSource, WalletRead};
|
||||
use zcash_client_sqlite::WalletDb;
|
||||
use zcash_primitives::{
|
||||
consensus::Parameters,
|
||||
transaction::components::amount::{Amount, MAX_MONEY},
|
||||
transaction::components::{
|
||||
amount::{Amount, MAX_MONEY},
|
||||
sapling::fees::InputView,
|
||||
},
|
||||
zip32::AccountId,
|
||||
};
|
||||
|
||||
|
@ -41,7 +44,7 @@ impl Command {
|
|||
)?;
|
||||
|
||||
for note in notes {
|
||||
println!("{}: {}", note.note_id, format_zec(note.note_value));
|
||||
println!("{}: {}", note.note_id(), format_zec(note.value()));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
use gumdrop::Options;
|
||||
|
||||
use zcash_client_backend::{
|
||||
address::RecipientAddress,
|
||||
data_api::wallet::{input_selection::GreedyInputSelector, propose_transfer},
|
||||
fees::standard::SingleOutputChangeStrategy,
|
||||
zip321::{Payment, TransactionRequest},
|
||||
};
|
||||
use zcash_client_sqlite::WalletDb;
|
||||
use zcash_primitives::{
|
||||
consensus::Parameters,
|
||||
transaction::{components::amount::NonNegativeAmount, fees::StandardFeeRule},
|
||||
zip32::AccountId,
|
||||
};
|
||||
|
||||
use crate::{data::get_db_paths, error, MIN_CONFIRMATIONS};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub(crate) enum FeeRule {
|
||||
Fixed,
|
||||
Zip317,
|
||||
}
|
||||
|
||||
impl Default for FeeRule {
|
||||
fn default() -> Self {
|
||||
FeeRule::Zip317
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl From<FeeRule> for StandardFeeRule {
|
||||
fn from(rule: FeeRule) -> Self {
|
||||
match rule {
|
||||
FeeRule::Fixed => StandardFeeRule::PreZip313,
|
||||
FeeRule::Zip317 => StandardFeeRule::Zip317,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn parse_fee_rule(name: &str) -> Result<FeeRule, String> {
|
||||
match name {
|
||||
"fixed" => Ok(FeeRule::Fixed),
|
||||
"zip317" => Ok(FeeRule::Zip317),
|
||||
other => Err(format!("Fee rule {} not recognized.", other)),
|
||||
}
|
||||
}
|
||||
|
||||
// Options accepted for the `propose` command
|
||||
#[derive(Debug, Options)]
|
||||
pub(crate) struct Command {
|
||||
#[options(
|
||||
required,
|
||||
help = "the recipient's Unified, Sapling or transparent address"
|
||||
)]
|
||||
address: String,
|
||||
|
||||
#[options(required, help = "the amount in zatoshis")]
|
||||
value: u64,
|
||||
|
||||
#[options(
|
||||
required,
|
||||
help = "fee strategy: \"fixed\" or \"zip317\"",
|
||||
parse(try_from_str = "parse_fee_rule")
|
||||
)]
|
||||
fee_rule: FeeRule,
|
||||
}
|
||||
|
||||
impl Command {
|
||||
pub(crate) async fn run(
|
||||
self,
|
||||
params: impl Parameters + Copy + 'static,
|
||||
wallet_dir: Option<String>,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let account = AccountId::from(0);
|
||||
let (_, db_data) = get_db_paths(wallet_dir.as_ref());
|
||||
let mut db_data = WalletDb::for_path(db_data, params)?;
|
||||
|
||||
let input_selector = GreedyInputSelector::new(
|
||||
SingleOutputChangeStrategy::new(self.fee_rule.into(), None),
|
||||
Default::default(),
|
||||
);
|
||||
|
||||
let request = TransactionRequest::new(vec![Payment {
|
||||
recipient_address: RecipientAddress::decode(¶ms, &self.address)
|
||||
.ok_or(error::Error::InvalidRecipient)?,
|
||||
amount: NonNegativeAmount::from_u64(self.value)
|
||||
.map_err(|_| error::Error::InvalidAmount)?,
|
||||
memo: None,
|
||||
label: None,
|
||||
message: None,
|
||||
other_params: vec![],
|
||||
}])
|
||||
.map_err(error::Error::from)?;
|
||||
|
||||
let proposal = propose_transfer(
|
||||
&mut db_data,
|
||||
¶ms,
|
||||
account,
|
||||
&input_selector,
|
||||
request,
|
||||
MIN_CONFIRMATIONS,
|
||||
)
|
||||
.map_err(error::Error::from)?;
|
||||
|
||||
// Display the proposal
|
||||
println!("Proposal: {:#?}", proposal);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ use zcash_client_backend::{
|
|||
wallet::{input_selection::GreedyInputSelector, spend},
|
||||
WalletRead,
|
||||
},
|
||||
fees::zip317::SingleOutputChangeStrategy,
|
||||
fees::standard::SingleOutputChangeStrategy,
|
||||
keys::UnifiedSpendingKey,
|
||||
proto::service,
|
||||
wallet::OvkPolicy,
|
||||
|
@ -15,13 +15,12 @@ use zcash_client_backend::{
|
|||
};
|
||||
use zcash_client_sqlite::WalletDb;
|
||||
use zcash_primitives::{
|
||||
consensus::Parameters,
|
||||
transaction::{components::Amount, fees::zip317::FeeRule},
|
||||
zip32::AccountId,
|
||||
consensus::Parameters, transaction::components::amount::NonNegativeAmount, zip32::AccountId,
|
||||
};
|
||||
use zcash_proofs::prover::LocalTxProver;
|
||||
|
||||
use crate::{
|
||||
commands::propose::{parse_fee_rule, FeeRule},
|
||||
data::{get_db_paths, get_wallet_seed},
|
||||
error,
|
||||
remote::connect_to_lightwalletd,
|
||||
|
@ -36,6 +35,13 @@ pub(crate) struct Command {
|
|||
|
||||
#[options(required, help = "the amount in zatoshis")]
|
||||
value: u64,
|
||||
|
||||
#[options(
|
||||
required,
|
||||
help = "fee strategy: \"fixed\" or \"zip317\"",
|
||||
parse(try_from_str = "parse_fee_rule")
|
||||
)]
|
||||
fee_rule: FeeRule,
|
||||
}
|
||||
|
||||
impl Command {
|
||||
|
@ -59,14 +65,15 @@ impl Command {
|
|||
let prover =
|
||||
LocalTxProver::with_default_location().ok_or(error::Error::MissingParameters)?;
|
||||
let input_selector = GreedyInputSelector::new(
|
||||
SingleOutputChangeStrategy::new(FeeRule::standard()),
|
||||
SingleOutputChangeStrategy::new(self.fee_rule.into(), None),
|
||||
Default::default(),
|
||||
);
|
||||
|
||||
let request = TransactionRequest::new(vec![Payment {
|
||||
recipient_address: RecipientAddress::decode(¶ms, &self.address)
|
||||
.ok_or(error::Error::InvalidRecipient)?,
|
||||
amount: Amount::from_u64(self.value).map_err(|_| error::Error::InvalidAmount)?,
|
||||
amount: NonNegativeAmount::from_u64(self.value)
|
||||
.map_err(|_| error::Error::InvalidAmount)?,
|
||||
memo: None,
|
||||
label: None,
|
||||
message: None,
|
||||
|
@ -77,7 +84,8 @@ impl Command {
|
|||
let id_tx = spend(
|
||||
&mut db_data,
|
||||
¶ms,
|
||||
prover,
|
||||
&prover,
|
||||
&prover,
|
||||
&input_selector,
|
||||
&usk,
|
||||
request,
|
||||
|
|
|
@ -18,7 +18,6 @@ pub(crate) type WalletErrorT = WalletError<
|
|||
commitment_tree::Error,
|
||||
GreedyInputSelectorError<FeeError, ReceivedNoteId>,
|
||||
FeeError,
|
||||
ReceivedNoteId,
|
||||
>;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -54,6 +54,9 @@ enum Command {
|
|||
#[options(help = "list the unspent notes in the wallet")]
|
||||
ListUnspent(commands::list_unspent::Command),
|
||||
|
||||
#[options(help = "propose a transfer of funds to the given address and display the proposal")]
|
||||
Propose(commands::propose::Command),
|
||||
|
||||
#[options(help = "send funds to the given address")]
|
||||
Send(commands::send::Command),
|
||||
}
|
||||
|
@ -89,6 +92,7 @@ fn main() -> Result<(), anyhow::Error> {
|
|||
Some(Command::Balance(command)) => command.run(params, opts.wallet_dir),
|
||||
Some(Command::ListTx(command)) => command.run(opts.wallet_dir),
|
||||
Some(Command::ListUnspent(command)) => command.run(params, opts.wallet_dir),
|
||||
Some(Command::Propose(command)) => command.run(params, opts.wallet_dir).await,
|
||||
Some(Command::Send(command)) => command.run(params, opts.wallet_dir).await,
|
||||
_ => Ok(()),
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue