Add option to finalize and post transactions separately (for air-gap wallets) (#255)

* Add option to output finalized slate

* Add subcommand to post a finalized slate file
This commit is contained in:
John Boyd 2019-11-18 05:19:00 -05:00 committed by Yeastplume
parent 021c34bf89
commit 355f08498c
3 changed files with 92 additions and 12 deletions

View file

@ -406,6 +406,8 @@ where
pub struct FinalizeArgs { pub struct FinalizeArgs {
pub input: String, pub input: String,
pub fluff: bool, pub fluff: bool,
pub nopost: bool,
pub dest: Option<String>,
} }
pub fn finalize<'a, L, C, K>( pub fn finalize<'a, L, C, K>(
@ -462,11 +464,14 @@ where
})?; })?;
} }
if !args.nopost {
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| { controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
let result = api.post_tx(m, &slate.tx, args.fluff); let result = api.post_tx(m, &slate.tx, args.fluff);
match result { match result {
Ok(_) => { Ok(_) => {
info!("Transaction sent successfully, check the wallet again for confirmation."); info!(
"Transaction sent successfully, check the wallet again for confirmation."
);
Ok(()) Ok(())
} }
Err(e) => { Err(e) => {
@ -475,6 +480,11 @@ where
} }
} }
})?; })?;
}
if args.dest.is_some() {
PathToSlate((&args.dest.unwrap()).into()).put_tx(&slate)?;
}
Ok(()) Ok(())
} }
@ -720,6 +730,32 @@ where
Ok(()) Ok(())
} }
/// Post
pub struct PostArgs {
pub input: String,
pub fluff: bool,
}
pub fn post<'a, L, C, K>(
wallet: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
keychain_mask: Option<&SecretKey>,
args: PostArgs,
) -> Result<(), Error>
where
L: WalletLCProvider<'a, C, K>,
C: NodeClient + 'a,
K: keychain::Keychain + 'a,
{
let slate = PathToSlate((&args.input).into()).get_tx()?;
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
api.post_tx(m, &slate.tx, args.fluff)?;
info!("Posted transaction");
return Ok(());
})?;
Ok(())
}
/// Repost /// Repost
pub struct RepostArgs { pub struct RepostArgs {
pub id: u32, pub id: u32,

View file

@ -176,6 +176,15 @@ subcommands:
help: Fluff the transaction (ignore Dandelion relay protocol) help: Fluff the transaction (ignore Dandelion relay protocol)
short: f short: f
long: fluff long: fluff
- nopost:
help: Do not post the transaction.
short: n
long: nopost
- dest:
help: Specify file to save the finalized slate.
short: d
long: dest
takes_value: true
- invoice: - invoice:
about: Initialize an invoice transaction. about: Initialize an invoice transaction.
args: args:
@ -259,6 +268,18 @@ subcommands:
short: t short: t
long: txid long: txid
takes_value: true takes_value: true
- post:
about: Posts a finalized transaction to the chain
args:
- input:
help: File name of the transaction to post
short: i
long: input
takes_value: true
- fluff:
help: Fluff the transaction (ignore Dandelion relay protocol)
short: f
long: fluff
- repost: - repost:
about: Reposts a stored, completed but unconfirmed transaction to the chain, or dumps it to a file about: Reposts a stored, completed but unconfirmed transaction to the chain, or dumps it to a file
args: args:

View file

@ -559,15 +559,24 @@ pub fn parse_receive_args(receive_args: &ArgMatches) -> Result<command::ReceiveA
pub fn parse_finalize_args(args: &ArgMatches) -> Result<command::FinalizeArgs, ParseError> { pub fn parse_finalize_args(args: &ArgMatches) -> Result<command::FinalizeArgs, ParseError> {
let fluff = args.is_present("fluff"); let fluff = args.is_present("fluff");
let nopost = args.is_present("nopost");
let tx_file = parse_required(args, "input")?; let tx_file = parse_required(args, "input")?;
if !Path::new(&tx_file).is_file() { if !Path::new(&tx_file).is_file() {
let msg = format!("File {} not found.", tx_file); let msg = format!("File {} not found.", tx_file);
return Err(ParseError::ArgumentError(msg)); return Err(ParseError::ArgumentError(msg));
} }
let dest_file = match args.is_present("dest") {
true => Some(args.value_of("dest").unwrap().to_owned()),
false => None,
};
Ok(command::FinalizeArgs { Ok(command::FinalizeArgs {
input: tx_file.to_owned(), input: tx_file.to_owned(),
fluff: fluff, fluff: fluff,
nopost: nopost,
dest: dest_file.to_owned(),
}) })
} }
@ -738,6 +747,16 @@ pub fn parse_txs_args(args: &ArgMatches) -> Result<command::TxsArgs, ParseError>
}) })
} }
pub fn parse_post_args(args: &ArgMatches) -> Result<command::PostArgs, ParseError> {
let tx_file = parse_required(args, "input")?;
let fluff = args.is_present("fluff");
Ok(command::PostArgs {
input: tx_file.to_owned(),
fluff: fluff,
})
}
pub fn parse_repost_args(args: &ArgMatches) -> Result<command::RepostArgs, ParseError> { pub fn parse_repost_args(args: &ArgMatches) -> Result<command::RepostArgs, ParseError> {
let tx_id = match args.value_of("id") { let tx_id = match args.value_of("id") {
None => None, None => None,
@ -1012,6 +1031,10 @@ where
wallet_config.dark_background_color_scheme.unwrap_or(true), wallet_config.dark_background_color_scheme.unwrap_or(true),
) )
} }
("post", Some(args)) => {
let a = arg_parse!(parse_post_args(&args));
command::post(wallet, km, a)
}
("repost", Some(args)) => { ("repost", Some(args)) => {
let a = arg_parse!(parse_repost_args(&args)); let a = arg_parse!(parse_repost_args(&args));
command::repost(wallet, km, a) command::repost(wallet, km, a)