Fetch and validate the coin control selected inputs. Coins could be internal (from the wallet) or external.
| 263 | // Fetch and validate the coin control selected inputs. |
| 264 | // Coins could be internal (from the wallet) or external. |
| 265 | util::Result<CoinsResult> FetchSelectedInputs(const CWallet& wallet, const CCoinControl& coin_control, |
| 266 | const CoinSelectionParams& coin_selection_params) |
| 267 | { |
| 268 | CoinsResult result; |
| 269 | const bool can_grind_r = wallet.CanGrindR(); |
| 270 | std::map<COutPoint, CAmount> map_of_bump_fees = wallet.chain().calculateIndividualBumpFees(coin_control.ListSelected(), coin_selection_params.m_effective_feerate); |
| 271 | for (const COutPoint& outpoint : coin_control.ListSelected()) { |
| 272 | int64_t input_bytes = coin_control.GetInputWeight(outpoint).value_or(-1); |
| 273 | if (input_bytes != -1) { |
| 274 | input_bytes = GetVirtualTransactionSize(input_bytes, 0, 0); |
| 275 | } |
| 276 | CTxOut txout; |
| 277 | if (auto txo = wallet.GetTXO(outpoint)) { |
| 278 | txout = txo->GetTxOut(); |
| 279 | if (input_bytes == -1) { |
| 280 | input_bytes = CalculateMaximumSignedInputSize(txout, &wallet, &coin_control); |
| 281 | } |
| 282 | const CWalletTx& parent_tx = txo->GetWalletTx(); |
| 283 | if (wallet.GetTxDepthInMainChain(parent_tx) == 0) { |
| 284 | if (parent_tx.tx->version == TRUC_VERSION && coin_control.m_version != TRUC_VERSION) { |
| 285 | return util::Error{strprintf(_("Can't spend unconfirmed version 3 pre-selected input with a version %d tx"), coin_control.m_version)}; |
| 286 | } else if (coin_control.m_version == TRUC_VERSION && parent_tx.tx->version != TRUC_VERSION) { |
| 287 | return util::Error{strprintf(_("Can't spend unconfirmed version %d pre-selected input with a version 3 tx"), parent_tx.tx->version)}; |
| 288 | } |
| 289 | } |
| 290 | } else { |
| 291 | // The input is external. We did not find the tx in mapWallet. |
| 292 | const auto out{coin_control.GetExternalOutput(outpoint)}; |
| 293 | if (!out) { |
| 294 | return util::Error{strprintf(_("Not found pre-selected input %s"), outpoint.ToString())}; |
| 295 | } |
| 296 | |
| 297 | txout = *out; |
| 298 | } |
| 299 | |
| 300 | if (input_bytes == -1) { |
| 301 | input_bytes = CalculateMaximumSignedInputSize(txout, outpoint, &coin_control.m_external_provider, can_grind_r, &coin_control); |
| 302 | } |
| 303 | |
| 304 | if (input_bytes == -1) { |
| 305 | return util::Error{strprintf(_("Not solvable pre-selected input %s"), outpoint.ToString())}; // Not solvable, can't estimate size for fee |
| 306 | } |
| 307 | |
| 308 | /* Set some defaults for depth, solvable, safe, time, and from_me as these don't matter for preset inputs since no selection is being done. */ |
| 309 | COutput output(outpoint, txout, /*depth=*/0, input_bytes, /*solvable=*/true, /*safe=*/true, /*time=*/0, /*from_me=*/false, coin_selection_params.m_effective_feerate); |
| 310 | output.ApplyBumpFee(map_of_bump_fees.at(output.outpoint)); |
| 311 | result.Add(OutputType::UNKNOWN, output); |
| 312 | } |
| 313 | return result; |
| 314 | } |
| 315 | |
| 316 | CoinsResult AvailableCoins(const CWallet& wallet, |
| 317 | const CCoinControl* coinControl, |