From 4fcb6053d559efbfde8df577bcb7f2c0f818d9cc Mon Sep 17 00:00:00 2001 From: jwinterm Date: Thu, 4 Jun 2026 07:40:03 -0400 Subject: [PATCH] Make contract slatepack encryption optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --encrypt-for is no longer required. `contract new` without it produces an unencrypted slatepack; `contract sign` without it replies to the incoming slate's sender when known, otherwise unencrypted. Passing --encrypt-for is unchanged. The slatepack layer already produced plaintext for an empty recipient list — this only removes the CLI-side requirement. --- controller/src/command.rs | 27 +++++++++++++-------------- src/bin/grin-wallet.yml | 4 ++-- src/cmd/wallet_args.rs | 5 +++-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/controller/src/command.rs b/controller/src/command.rs index 42098fb..f7e5979 100644 --- a/controller/src/command.rs +++ b/controller/src/command.rs @@ -1620,8 +1620,8 @@ where /// Create new contract command arguments #[derive(Clone)] pub struct ContractNewArgs { - /// Address of the counterparty - pub counterparty_addr: String, + /// Address of the counterparty (None = produce an unencrypted slatepack) + pub counterparty_addr: Option, /// Receive amount pub receive: Option, /// Send amount @@ -1709,7 +1709,7 @@ where api, keychain_mask, &slate, - &args.counterparty_addr, + args.counterparty_addr.as_deref().unwrap_or(""), args.outfile, args.as_json, ); @@ -1884,17 +1884,16 @@ where vec![0], )?; - let counterparty_addr = - if args.counterparty_addr.is_some() { - args.counterparty_addr.unwrap() - } else { - if slatepack.sender.is_none() { - return Err(grin_wallet_libwallet::Error::GenericError( - "No address to encrypt for: pass --encrypt-for. Contracts only support encrypted slates.".into(), - )); - } - String::try_from(&slatepack.sender.unwrap())? - }; + // Encrypt the reply for --encrypt-for if given, else for the incoming slatepack's + // sender. If neither is known the incoming slate was plaintext, so reply plaintext + // (empty dest -> unencrypted slatepack). + let counterparty_addr = if let Some(addr) = args.counterparty_addr { + addr + } else if let Some(sender) = slatepack.sender { + String::try_from(&sender)? + } else { + String::new() + }; let mut slate = owner::slate_from_slatepack_message( api.wallet_inst.clone(), keychain_mask, diff --git a/src/bin/grin-wallet.yml b/src/bin/grin-wallet.yml index a88efb4..bc0b316 100644 --- a/src/bin/grin-wallet.yml +++ b/src/bin/grin-wallet.yml @@ -452,7 +452,7 @@ subcommands: about: Create a new contract with initial setup args: - encrypt-for: - help: The counter party grin address + help: The counter party grin address (optional; omit to produce an unencrypted slatepack) short: e long: encrypt-for takes_value: true @@ -544,7 +544,7 @@ subcommands: about: Sign a contract args: - encrypt-for: - help: The counter party grin address + help: The counter party grin address (optional; defaults to the slate sender, else unencrypted) short: e long: encrypt-for takes_value: true diff --git a/src/cmd/wallet_args.rs b/src/cmd/wallet_args.rs index eeb5dc8..a1f50c1 100644 --- a/src/cmd/wallet_args.rs +++ b/src/cmd/wallet_args.rs @@ -978,7 +978,8 @@ pub fn parse_contract_new_args( args: &ArgMatches, account: &String, ) -> Result { - let counterparty_addr = parse_required(args, "encrypt-for")?; + // Optional: without --encrypt-for the contract slatepack is produced unencrypted. + let counterparty_addr = args.value_of("encrypt-for").map(String::from); // TODO: Make sure the values are in some expected bounds. // TODO: How to deal with decimals and precision? we probably want users to express the value in Grin. @@ -1044,7 +1045,7 @@ pub fn parse_contract_new_args( }; Ok(command::ContractNewArgs { - counterparty_addr: String::from(counterparty_addr), + counterparty_addr: counterparty_addr, receive: receive, send: send, src_acct_name: src_acct_name,