diff options
Diffstat (limited to 'src/wallet/feebumper.cpp')
-rw-r--r-- | src/wallet/feebumper.cpp | 126 |
1 files changed, 0 insertions, 126 deletions
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp index 3761ca466a..1623ab9074 100644 --- a/src/wallet/feebumper.cpp +++ b/src/wallet/feebumper.cpp @@ -150,132 +150,6 @@ bool TransactionCanBeBumped(const CWallet& wallet, const uint256& txid) return res == feebumper::Result::OK; } -Result CreateTotalBumpTransaction(const CWallet* wallet, const uint256& txid, const CCoinControl& coin_control, CAmount total_fee, std::vector<std::string>& errors, - CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx) -{ - new_fee = total_fee; - - auto locked_chain = wallet->chain().lock(); - LOCK(wallet->cs_wallet); - errors.clear(); - auto it = wallet->mapWallet.find(txid); - if (it == wallet->mapWallet.end()) { - errors.push_back("Invalid or non-wallet transaction id"); - return Result::INVALID_ADDRESS_OR_KEY; - } - const CWalletTx& wtx = it->second; - - Result result = PreconditionChecks(*wallet, wtx, errors); - if (result != Result::OK) { - return result; - } - - // figure out which output was change - // if there was no change output or multiple change outputs, fail - int nOutput = -1; - for (size_t i = 0; i < wtx.tx->vout.size(); ++i) { - if (wallet->IsChange(wtx.tx->vout[i])) { - if (nOutput != -1) { - errors.push_back("Transaction has multiple change outputs"); - return Result::WALLET_ERROR; - } - nOutput = i; - } - } - if (nOutput == -1) { - errors.push_back("Transaction does not have a change output"); - return Result::WALLET_ERROR; - } - - // Calculate the expected size of the new transaction. - int64_t txSize = GetVirtualTransactionSize(*(wtx.tx)); - const int64_t maxNewTxSize = CalculateMaximumSignedTxSize(*wtx.tx, wallet); - if (maxNewTxSize < 0) { - errors.push_back("Transaction contains inputs that cannot be signed"); - return Result::INVALID_ADDRESS_OR_KEY; - } - - // calculate the old fee and fee-rate - isminefilter filter = wallet->GetLegacyScriptPubKeyMan() && wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) ? ISMINE_WATCH_ONLY : ISMINE_SPENDABLE; - old_fee = wtx.GetDebit(filter) - wtx.tx->GetValueOut(); - CFeeRate nOldFeeRate(old_fee, txSize); - // The wallet uses a conservative WALLET_INCREMENTAL_RELAY_FEE value to - // future proof against changes to network wide policy for incremental relay - // fee that our node may not be aware of. - CFeeRate nodeIncrementalRelayFee = wallet->chain().relayIncrementalFee(); - CFeeRate walletIncrementalRelayFee = CFeeRate(WALLET_INCREMENTAL_RELAY_FEE); - if (nodeIncrementalRelayFee > walletIncrementalRelayFee) { - walletIncrementalRelayFee = nodeIncrementalRelayFee; - } - - CAmount minTotalFee = nOldFeeRate.GetFee(maxNewTxSize) + nodeIncrementalRelayFee.GetFee(maxNewTxSize); - if (total_fee < minTotalFee) { - errors.push_back(strprintf("Insufficient totalFee, must be at least %s (oldFee %s + incrementalFee %s)", - FormatMoney(minTotalFee), FormatMoney(nOldFeeRate.GetFee(maxNewTxSize)), FormatMoney(nodeIncrementalRelayFee.GetFee(maxNewTxSize)))); - return Result::INVALID_PARAMETER; - } - CAmount requiredFee = GetRequiredFee(*wallet, maxNewTxSize); - if (total_fee < requiredFee) { - errors.push_back(strprintf("Insufficient totalFee (cannot be less than required fee %s)", - FormatMoney(requiredFee))); - return Result::INVALID_PARAMETER; - } - - // Check that in all cases the new fee doesn't violate maxTxFee - const CAmount max_tx_fee = wallet->m_default_max_tx_fee; - if (new_fee > max_tx_fee) { - errors.push_back(strprintf("Specified or calculated fee %s is too high (cannot be higher than -maxtxfee %s)", - FormatMoney(new_fee), FormatMoney(max_tx_fee))); - return Result::WALLET_ERROR; - } - - // check that fee rate is higher than mempool's minimum fee - // (no point in bumping fee if we know that the new tx won't be accepted to the mempool) - // This may occur if the user set TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps, - // in a rare situation where the mempool minimum fee increased significantly since the fee estimation just a - // moment earlier. In this case, we report an error to the user, who may use total_fee to make an adjustment. - CFeeRate minMempoolFeeRate = wallet->chain().mempoolMinFee(); - CFeeRate nNewFeeRate = CFeeRate(total_fee, maxNewTxSize); - if (nNewFeeRate.GetFeePerK() < minMempoolFeeRate.GetFeePerK()) { - errors.push_back(strprintf( - "New fee rate (%s) is lower than the minimum fee rate (%s) to get into the mempool -- " - "the totalFee value should be at least %s to add transaction", - FormatMoney(nNewFeeRate.GetFeePerK()), - FormatMoney(minMempoolFeeRate.GetFeePerK()), - FormatMoney(minMempoolFeeRate.GetFee(maxNewTxSize)))); - return Result::WALLET_ERROR; - } - - // Now modify the output to increase the fee. - // If the output is not large enough to pay the fee, fail. - CAmount nDelta = new_fee - old_fee; - assert(nDelta > 0); - mtx = CMutableTransaction{*wtx.tx}; - CTxOut* poutput = &(mtx.vout[nOutput]); - if (poutput->nValue < nDelta) { - errors.push_back("Change output is too small to bump the fee"); - return Result::WALLET_ERROR; - } - - // If the output would become dust, discard it (converting the dust to fee) - poutput->nValue -= nDelta; - if (poutput->nValue <= GetDustThreshold(*poutput, GetDiscardRate(*wallet))) { - wallet->WalletLogPrintf("Bumping fee and discarding dust output\n"); - new_fee += poutput->nValue; - mtx.vout.erase(mtx.vout.begin() + nOutput); - } - - // Mark new tx not replaceable, if requested. - if (!coin_control.m_signal_bip125_rbf.get_value_or(wallet->m_signal_rbf)) { - for (auto& input : mtx.vin) { - if (input.nSequence < 0xfffffffe) input.nSequence = 0xfffffffe; - } - } - - return Result::OK; -} - - Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCoinControl& coin_control, std::vector<std::string>& errors, CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx) { |