[wallet] panic: 'attempt to subtract with overflow' when sending small quantities #396 (#603)

* Fund calculation inconsistent (#582)

* [wallet] panic: 'attempt to subtract with overflow' when sending small quantities (#396)
This commit is contained in:
Heung B Lee 2018-01-12 04:44:15 -08:00 committed by Yeastplume
parent 31f91dc487
commit 5edc63f617
4 changed files with 57 additions and 4 deletions

View file

@ -489,6 +489,14 @@ fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) {
amount_to_hr_string(available), amount_to_hr_string(available),
); );
} }
Err(wallet::Error::FeeExceedsAmount {sender_amount, recipient_fee}) => {
error!(
LOGGER,
"Recipient rejected the transfer because transaction fee ({}) exceeded amount ({}).",
amount_to_hr_string(recipient_fee),
amount_to_hr_string(sender_amount)
);
}
Err(e) => { Err(e) => {
error!(LOGGER, "Tx not sent: {:?}", e); error!(LOGGER, "Tx not sent: {:?}", e);
} }

View file

@ -24,7 +24,7 @@ use serde_json;
use api; use api;
use core::consensus::reward; use core::consensus::reward;
use core::core::{build, Block, Output, Transaction, TxKernel}; use core::core::{build, Block, Output, Transaction, TxKernel, amount_to_hr_string};
use core::ser; use core::ser;
use keychain::{Identifier, Keychain}; use keychain::{Identifier, Keychain};
use types::*; use types::*;
@ -66,6 +66,19 @@ fn handle_sender_initiation(
}); });
} }
if fee > amount {
info!(
LOGGER,
"Rejected the transfer because transaction fee ({}) exceeds received amount ({}).",
amount_to_hr_string(fee),
amount_to_hr_string(amount)
);
return Err(Error::FeeExceedsAmount {
sender_amount: amount,
recipient_fee: fee,
});
}
let out_amount = amount - fee; let out_amount = amount - fee;
//First step is just to get the excess sum of the outputs we're participating in //First step is just to get the excess sum of the outputs we're participating in
@ -310,6 +323,19 @@ fn build_final_transaction(
}); });
} }
if fee > amount {
info!(
LOGGER,
"Rejected the transfer because transaction fee ({}) exceeds received amount ({}).",
amount_to_hr_string(fee),
amount_to_hr_string(amount)
);
return Err(Error::FeeExceedsAmount {
sender_amount: amount,
recipient_fee: fee,
});
}
let out_amount = amount - fee; let out_amount = amount - fee;
// Get output we created in earlier step // Get output we created in earlier step

View file

@ -15,7 +15,7 @@
use api; use api;
use client; use client;
use checker; use checker;
use core::core::{build, Transaction}; use core::core::{build, Transaction, amount_to_hr_string};
use core::ser; use core::ser;
use keychain::{BlindingFactor, Identifier, Keychain}; use keychain::{BlindingFactor, Identifier, Keychain};
use receiver::TxWrapper; use receiver::TxWrapper;
@ -97,7 +97,16 @@ pub fn issue_send_tx(
debug!(LOGGER, "Posting partial transaction to {}", url); debug!(LOGGER, "Posting partial transaction to {}", url);
let res = client::send_partial_tx(&url, &partial_tx); let res = client::send_partial_tx(&url, &partial_tx);
if let Err(e) = res { if let Err(e) = res {
error!(LOGGER, "Communication with receiver failed on SenderInitiation send. Aborting transaction"); match e {
Error::FeeExceedsAmount {sender_amount, recipient_fee} =>
error!(
LOGGER,
"Recipient rejected the transfer because transaction fee ({}) exceeded amount ({}).",
amount_to_hr_string(recipient_fee),
amount_to_hr_string(sender_amount)
),
_ => error!(LOGGER, "Communication with receiver failed on SenderInitiation send. Aborting transaction"),
}
rollback_wallet()?; rollback_wallet()?;
return Err(e); return Err(e);
} }
@ -124,7 +133,16 @@ pub fn issue_send_tx(
// And send again // And send again
let res = client::send_partial_tx(&url, &partial_tx); let res = client::send_partial_tx(&url, &partial_tx);
if let Err(e) = res { if let Err(e) = res {
error!(LOGGER, "Communication with receiver failed on SenderConfirmation send. Aborting transaction"); match e {
Error::FeeExceedsAmount {sender_amount, recipient_fee} =>
error!(
LOGGER,
"Recipient rejected the transfer because transaction fee ({}) exceeded amount ({}).",
amount_to_hr_string(recipient_fee),
amount_to_hr_string(sender_amount)
),
_ => error!(LOGGER, "Communication with receiver failed on SenderConfirmation send. Aborting transaction"),
}
rollback_wallet()?; rollback_wallet()?;
return Err(e); return Err(e);
} }

View file

@ -66,6 +66,7 @@ pub fn tx_fee(input_len: usize, output_len: usize, base_fee: Option<u64>) -> u64
pub enum Error { pub enum Error {
NotEnoughFunds(u64), NotEnoughFunds(u64),
FeeDispute { sender_fee: u64, recipient_fee: u64 }, FeeDispute { sender_fee: u64, recipient_fee: u64 },
FeeExceedsAmount { sender_amount: u64, recipient_fee: u64 },
Keychain(keychain::Error), Keychain(keychain::Error),
Transaction(transaction::Error), Transaction(transaction::Error),
Secp(secp::Error), Secp(secp::Error),