| 94 | } |
| 95 | |
| 96 | static UniValue FinishTransaction(const std::shared_ptr<CWallet> pwallet, const UniValue& options, CMutableTransaction& rawTx) |
| 97 | { |
| 98 | bool can_anti_fee_snipe = !options.exists("locktime"); |
| 99 | |
| 100 | for (const CTxIn& tx_in : rawTx.vin) { |
| 101 | // Checks sequence values consistent with DiscourageFeeSniping |
| 102 | can_anti_fee_snipe = can_anti_fee_snipe && (tx_in.nSequence == CTxIn::MAX_SEQUENCE_NONFINAL || tx_in.nSequence == MAX_BIP125_RBF_SEQUENCE); |
| 103 | } |
| 104 | |
| 105 | if (can_anti_fee_snipe) { |
| 106 | LOCK(pwallet->cs_wallet); |
| 107 | FastRandomContext rng_fast; |
| 108 | DiscourageFeeSniping(rawTx, rng_fast, pwallet->chain(), pwallet->GetLastBlockHash(), pwallet->GetLastBlockHeight()); |
| 109 | } |
| 110 | |
| 111 | // Make a blank psbt |
| 112 | PartiallySignedTransaction psbtx(rawTx, /*version=*/2); |
| 113 | |
| 114 | // First fill transaction with our data without signing, |
| 115 | // so external signers are not asked to sign more than once. |
| 116 | bool complete; |
| 117 | pwallet->FillPSBT(psbtx, {.sign = false, .bip32_derivs = true}, complete); |
| 118 | const auto err{pwallet->FillPSBT(psbtx, {.sign = true, .bip32_derivs = false}, complete)}; |
| 119 | if (err) { |
| 120 | throw JSONRPCPSBTError(*err); |
| 121 | } |
| 122 | |
| 123 | CMutableTransaction mtx; |
| 124 | complete = FinalizeAndExtractPSBT(psbtx, mtx); |
| 125 | |
| 126 | UniValue result(UniValue::VOBJ); |
| 127 | |
| 128 | const bool psbt_opt_in{options.exists("psbt") && options["psbt"].get_bool()}; |
| 129 | bool add_to_wallet{options.exists("add_to_wallet") ? options["add_to_wallet"].get_bool() : true}; |
| 130 | if (psbt_opt_in || !complete || !add_to_wallet) { |
| 131 | // Serialize the PSBT |
| 132 | DataStream ssTx{}; |
| 133 | ssTx << psbtx; |
| 134 | result.pushKV("psbt", EncodeBase64(ssTx.str())); |
| 135 | } |
| 136 | |
| 137 | if (complete) { |
| 138 | std::string hex{EncodeHexTx(CTransaction(mtx))}; |
| 139 | CTransactionRef tx(MakeTransactionRef(std::move(mtx))); |
| 140 | result.pushKV("txid", tx->GetHash().GetHex()); |
| 141 | if (add_to_wallet && !psbt_opt_in) { |
| 142 | pwallet->CommitTransaction(tx, {}, /*orderForm=*/{}); |
| 143 | } else { |
| 144 | result.pushKV("hex", hex); |
| 145 | } |
| 146 | } |
| 147 | result.pushKV("complete", complete); |
| 148 | |
| 149 | return result; |
| 150 | } |
| 151 | |
| 152 | static void PreventOutdatedOptions(const UniValue& options) |
| 153 | { |
no test coverage detected