[wallet] Change feebumper from class to functions

Change feebumper from a stateful class into a namespace of stateless
functions.

Having the results of feebumper calls persist in an object makes process
separation between Qt and wallet awkward, because it means the feebumper object
either has to be serialized back and forth between Qt and wallet processes
between fee bump calls, or that the feebumper object needs to stay alive in the
wallet process with an object reference passed back to Qt. It's simpler just to
have fee bumper calls return their results immediately instead of storing them
in an object with an extended lifetime.

In addition to making feebumper stateless, also:

- Move LOCK calls from Qt code to feebumper
- Move TransactionCanBeBumped implementation from Qt code to feebumper
This commit is contained in:
Russell Yanofsky
2017-06-15 10:34:17 -04:00
committed by John Newbery
parent 37bdcca3c3
commit aed1d90aca
4 changed files with 114 additions and 138 deletions

View File

@@ -659,45 +659,39 @@ bool WalletModel::abandonTransaction(uint256 hash) const
bool WalletModel::transactionCanBeBumped(uint256 hash) const
{
LOCK2(cs_main, wallet->cs_wallet);
const CWalletTx *wtx = wallet->GetWalletTx(hash);
return wtx && SignalsOptInRBF(*(wtx->tx)) && !wtx->mapValue.count("replaced_by_txid");
return feebumper::TransactionCanBeBumped(wallet, hash);
}
bool WalletModel::bumpFee(uint256 hash)
{
std::unique_ptr<feebumper::FeeBumper> feeBump;
{
CCoinControl coin_control;
coin_control.signalRbf = true;
LOCK2(cs_main, wallet->cs_wallet);
feeBump.reset(new feebumper::FeeBumper(wallet, hash, coin_control, 0));
}
if (feeBump->getResult() != feebumper::Result::OK)
{
CCoinControl coin_control;
coin_control.signalRbf = true;
std::vector<std::string> errors;
CAmount old_fee;
CAmount new_fee;
CMutableTransaction mtx;
if (feebumper::CreateTransaction(wallet, hash, coin_control, 0 /* totalFee */, errors, old_fee, new_fee, mtx) != feebumper::Result::OK) {
QMessageBox::critical(0, tr("Fee bump error"), tr("Increasing transaction fee failed") + "<br />(" +
(feeBump->getErrors().size() ? QString::fromStdString(feeBump->getErrors()[0]) : "") +")");
(errors.size() ? QString::fromStdString(errors[0]) : "") +")");
return false;
}
// allow a user based fee verification
QString questionString = tr("Do you want to increase the fee?");
questionString.append("<br />");
CAmount oldFee = feeBump->getOldFee();
CAmount newFee = feeBump->getNewFee();
questionString.append("<table style=\"text-align: left;\">");
questionString.append("<tr><td>");
questionString.append(tr("Current fee:"));
questionString.append("</td><td>");
questionString.append(BitcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), oldFee));
questionString.append(BitcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), old_fee));
questionString.append("</td></tr><tr><td>");
questionString.append(tr("Increase:"));
questionString.append("</td><td>");
questionString.append(BitcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), newFee - oldFee));
questionString.append(BitcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), new_fee - old_fee));
questionString.append("</td></tr><tr><td>");
questionString.append(tr("New fee:"));
questionString.append("</td><td>");
questionString.append(BitcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), newFee));
questionString.append(BitcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), new_fee));
questionString.append("</td></tr></table>");
SendConfirmationDialog confirmationDialog(tr("Confirm fee bump"), questionString);
confirmationDialog.exec();
@@ -715,23 +709,15 @@ bool WalletModel::bumpFee(uint256 hash)
}
// sign bumped transaction
bool res = false;
{
LOCK2(cs_main, wallet->cs_wallet);
res = feeBump->signTransaction(wallet);
}
if (!res) {
if (!feebumper::SignTransaction(wallet, mtx)) {
QMessageBox::critical(0, tr("Fee bump error"), tr("Can't sign transaction."));
return false;
}
// commit the bumped transaction
{
LOCK2(cs_main, wallet->cs_wallet);
res = feeBump->commit(wallet);
}
if(!res) {
uint256 txid;
if (feebumper::CommitTransaction(wallet, hash, std::move(mtx), errors, txid) != feebumper::Result::OK) {
QMessageBox::critical(0, tr("Fee bump error"), tr("Could not commit transaction") + "<br />(" +
QString::fromStdString(feeBump->getErrors()[0])+")");
QString::fromStdString(errors[0])+")");
return false;
}
return true;