Add cancel tx by tx_slate_id

This commit is contained in:
Quentin Le Sceller
2018-11-13 11:53:23 +01:00
parent 1b264595e3
commit 59b0f1b1d7
6 changed files with 86 additions and 26 deletions
+40 -13
View File
@@ -603,22 +603,49 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) -> i
}
}
("cancel", Some(tx_args)) => {
let tx_id = tx_args
.value_of("id")
.ok_or_else(|| {
ErrorKind::GenericError("'id' argument (-i) is required.".to_string())
}).and_then(|v| {
v.parse().map_err(|e| {
ErrorKind::GenericError(format!(
let mut tx_id_string = "";
let tx_id = match tx_args.value_of("id") {
None => None,
Some(tx) => match tx.parse() {
Ok(t) => {
tx_id_string = tx;
Some(t)
}
Err(e) => {
return Err(ErrorKind::GenericError(format!(
"Could not parse id parameter. e={:?}",
e
))
})
})?;
let result = api.cancel_tx(tx_id);
e,
)).into());
}
},
};
let tx_slate_id = match tx_args.value_of("txid") {
None => None,
Some(tx) => match tx.parse() {
Ok(t) => {
tx_id_string = tx;
Some(t)
}
Err(e) => {
return Err(ErrorKind::GenericError(format!(
"Could not parse txid parameter. e={:?}",
e,
)).into());
}
},
};
if (tx_id.is_none() && tx_slate_id.is_none())
|| (tx_id.is_some() && tx_slate_id.is_some())
{
return Err(ErrorKind::GenericError(format!(
"'id' (-i) or 'txid' (-t) argument is required."
)).into());
}
let result = api.cancel_tx(tx_id, tx_slate_id);
match result {
Ok(_) => {
info!("Transaction {} Cancelled", tx_id);
info!("Transaction {} Cancelled", tx_id_string);
Ok(())
}
Err(e) => {
+5
View File
@@ -321,6 +321,11 @@ fn real_main() -> i32 {
.help("The ID of the transaction to cancel")
.short("i")
.long("id")
.takes_value(true))
.arg(Arg::with_name("txid")
.help("The TxID of the transaction to cancel")
.short("t")
.long("txid")
.takes_value(true)))
.subcommand(SubCommand::with_name("info")
+6 -2
View File
@@ -322,7 +322,11 @@ where
/// output if you're recipient), and unlock all locked outputs associated
/// with the transaction used when a transaction is created but never
/// posted
pub fn cancel_tx(&mut self, tx_id: u32) -> Result<(), Error> {
pub fn cancel_tx(
&mut self,
tx_id: Option<u32>,
tx_slate_id: Option<Uuid>,
) -> Result<(), Error> {
let mut w = self.wallet.lock();
w.open_with_credentials()?;
let parent_key_id = w.parent_key_id();
@@ -331,7 +335,7 @@ where
"Can't contact running Grin node. Not Cancelling.",
))?;
}
tx::cancel_tx(&mut *w, &parent_key_id, tx_id)?;
tx::cancel_tx(&mut *w, &parent_key_id, tx_id, tx_slate_id)?;
w.close()?;
Ok(())
}
+18 -2
View File
@@ -342,7 +342,7 @@ where
let params = parse_params(&req);
if let Some(id_string) = params.get("id") {
Box::new(match id_string[0].parse() {
Ok(id) => match api.cancel_tx(id) {
Ok(id) => match api.cancel_tx(Some(id), None) {
Ok(_) => ok(()),
Err(e) => {
error!("cancel_tx: failed with error: {}", e);
@@ -356,9 +356,25 @@ where
).into())
}
})
} else if let Some(tx_id_string) = params.get("tx_id") {
Box::new(match tx_id_string[0].parse() {
Ok(tx_id) => match api.cancel_tx(None, Some(tx_id)) {
Ok(_) => ok(()),
Err(e) => {
error!("cancel_tx: failed with error: {}", e);
err(e)
}
},
Err(e) => {
error!("cancel_tx: could not parse tx_id: {}", e);
err(ErrorKind::TransactionCancellationError(
"cancel_tx: cannot cancel transaction. Could not parse tx_id in request.",
).into())
}
})
} else {
Box::new(err(ErrorKind::TransactionCancellationError(
"cancel_tx: Cannot cancel transaction. Missing id param in request.",
"cancel_tx: Cannot cancel transaction. Missing id or tx_id param in request.",
).into()))
}
}
+2 -2
View File
@@ -150,11 +150,11 @@ pub enum ErrorKind {
/// Transaction doesn't exist
#[fail(display = "Transaction {} doesn't exist", _0)]
TransactionDoesntExist(u32),
TransactionDoesntExist(String),
/// Transaction already rolled back
#[fail(display = "Transaction {} cannot be cancelled", _0)]
TransactionNotCancellable(u32),
TransactionNotCancellable(String),
/// Cancellation error
#[fail(display = "Cancellation Error: {}", _0)]
+15 -7
View File
@@ -16,6 +16,7 @@
use std::sync::Arc;
use util::RwLock;
use uuid::Uuid;
use core::core::verifier_cache::LruVerifierCache;
use core::core::Transaction;
@@ -153,26 +154,33 @@ where
pub fn cancel_tx<T: ?Sized, C, K>(
wallet: &mut T,
parent_key_id: &Identifier,
tx_id: u32,
tx_id: Option<u32>,
tx_slate_id: Option<Uuid>,
) -> Result<(), Error>
where
T: WalletBackend<C, K>,
C: WalletClient,
K: Keychain,
{
let tx_vec = updater::retrieve_txs(wallet, Some(tx_id), None, &parent_key_id)?;
let mut tx_id_string = String::new();
if let Some(tx_id) = tx_id {
tx_id_string = tx_id.to_string();
} else if let Some(tx_slate_id) = tx_slate_id {
tx_id_string = tx_slate_id.to_string();
}
let tx_vec = updater::retrieve_txs(wallet, tx_id, tx_slate_id, &parent_key_id)?;
if tx_vec.len() != 1 {
return Err(ErrorKind::TransactionDoesntExist(tx_id))?;
return Err(ErrorKind::TransactionDoesntExist(tx_id_string))?;
}
let tx = tx_vec[0].clone();
if tx.tx_type != TxLogEntryType::TxSent && tx.tx_type != TxLogEntryType::TxReceived {
return Err(ErrorKind::TransactionNotCancellable(tx_id))?;
return Err(ErrorKind::TransactionNotCancellable(tx_id_string))?;
}
if tx.confirmed == true {
return Err(ErrorKind::TransactionNotCancellable(tx_id))?;
return Err(ErrorKind::TransactionNotCancellable(tx_id_string))?;
}
// get outputs associated with tx
let res = updater::retrieve_outputs(wallet, false, Some(tx_id), &parent_key_id)?;
let res = updater::retrieve_outputs(wallet, false, Some(tx.id), &parent_key_id)?;
let outputs = res.iter().map(|(out, _)| out).cloned().collect();
updater::cancel_tx_and_outputs(wallet, tx, outputs, parent_key_id)?;
Ok(())
@@ -192,7 +200,7 @@ where
{
let tx_vec = updater::retrieve_txs(wallet, Some(tx_id), None, parent_key_id)?;
if tx_vec.len() != 1 {
return Err(ErrorKind::TransactionDoesntExist(tx_id))?;
return Err(ErrorKind::TransactionDoesntExist(tx_id.to_string()))?;
}
let tx = tx_vec[0].clone();
Ok((tx.confirmed, tx.tx_hex))