| 159 | } |
| 160 | |
| 161 | Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCoinControl& coin_control, std::vector<bilingual_str>& errors, |
| 162 | CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx) |
| 163 | { |
| 164 | // We are going to modify coin control later, copy to re-use |
| 165 | CCoinControl new_coin_control(coin_control); |
| 166 | |
| 167 | LOCK(wallet.cs_wallet); |
| 168 | errors.clear(); |
| 169 | auto it = wallet.mapWallet.find(txid); |
| 170 | if (it == wallet.mapWallet.end()) { |
| 171 | errors.push_back(Untranslated("Invalid or non-wallet transaction id")); |
| 172 | return Result::INVALID_ADDRESS_OR_KEY; |
| 173 | } |
| 174 | const CWalletTx& wtx = it->second; |
| 175 | |
| 176 | Result result = PreconditionChecks(wallet, wtx, errors); |
| 177 | if (result != Result::OK) { |
| 178 | return result; |
| 179 | } |
| 180 | |
| 181 | // Fill in recipients (and preserve a single change key per asset if there is one) |
| 182 | std::map<CAsset, CTxDestination> destinations; |
| 183 | std::vector<wallet::CRecipient> recipients; |
| 184 | for (const auto& output : wtx.tx->vout) { |
| 185 | // ELEMENTS: |
| 186 | bool is_change = OutputIsChange(wallet, output); |
| 187 | bool is_fee = output.IsFee(); |
| 188 | if (!output.nValue.IsExplicit() || !output.nAsset.IsExplicit()) { |
| 189 | errors.push_back(Untranslated("bumpfee can only be called on an unblinded transaction")); |
| 190 | return Result::WALLET_ERROR; |
| 191 | } |
| 192 | |
| 193 | if (!is_change && !is_fee) { |
| 194 | wallet::CRecipient recipient = {output.scriptPubKey, output.nValue.GetAmount(), output.nAsset.GetAsset(), CPubKey(output.nNonce.vchCommitment), false}; |
| 195 | recipients.push_back(recipient); |
| 196 | } else if (is_change) { |
| 197 | CTxDestination change_dest; |
| 198 | ExtractDestination(output.scriptPubKey, change_dest); |
| 199 | destinations[output.nAsset.GetAsset()] = change_dest; |
| 200 | } |
| 201 | } |
| 202 | new_coin_control.destChange = destinations; |
| 203 | |
| 204 | isminefilter filter = wallet.GetLegacyScriptPubKeyMan() && wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) ? ISMINE_WATCH_ONLY : ISMINE_SPENDABLE; |
| 205 | old_fee = CachedTxGetDebit(wallet, wtx, filter)[::policyAsset] - wtx.tx->GetValueOutMap()[::policyAsset]; |
| 206 | if (g_con_elementsmode) { |
| 207 | old_fee = GetFeeMap(*wtx.tx)[::policyAsset]; |
| 208 | } |
| 209 | |
| 210 | if (coin_control.m_feerate) { |
| 211 | // The user provided a feeRate argument. |
| 212 | // We calculate this here to avoid compiler warning on the cs_wallet lock |
| 213 | const int64_t maxTxSize{CalculateMaximumSignedTxSize(*wtx.tx, &wallet).vsize}; |
| 214 | Result res = CheckFeeRate(wallet, wtx, *new_coin_control.m_feerate, maxTxSize, errors); |
| 215 | if (res != Result::OK) { |
| 216 | return res; |
| 217 | } |
| 218 | } else { |
no test coverage detected