| 205 | } |
| 206 | |
| 207 | bool PartiallySignedTransaction::AddInput(PSBTInput& psbtin) |
| 208 | { |
| 209 | // Check required fields are present and this input is not a duplicate |
| 210 | if (psbtin.prev_txid.IsNull() || |
| 211 | psbtin.prev_out == std::nullopt || |
| 212 | std::find_if(inputs.begin(), inputs.end(), |
| 213 | [psbtin](const PSBTInput& psbt) { |
| 214 | return psbt.prev_txid == psbtin.prev_txid && psbt.prev_out == psbtin.prev_out; |
| 215 | } |
| 216 | ) != inputs.end()) { |
| 217 | return false; |
| 218 | } |
| 219 | |
| 220 | if (tx != std::nullopt) { |
| 221 | // This is a v0 psbt, so do the v0 AddInput |
| 222 | CTxIn txin(COutPoint(psbtin.prev_txid, *psbtin.prev_out)); |
| 223 | if (std::find(tx->vin.begin(), tx->vin.end(), txin) != tx->vin.end()) { |
| 224 | return false; |
| 225 | } |
| 226 | tx->vin.push_back(txin); |
| 227 | psbtin.partial_sigs.clear(); |
| 228 | psbtin.final_script_sig.clear(); |
| 229 | psbtin.final_script_witness.SetNull(); |
| 230 | inputs.push_back(psbtin); |
| 231 | return true; |
| 232 | } |
| 233 | |
| 234 | // No global tx, must be PSBTv2. |
| 235 | // Check inputs modifiable flag |
| 236 | if (m_tx_modifiable == std::nullopt || !m_tx_modifiable->test(0)) { |
| 237 | return false; |
| 238 | } |
| 239 | |
| 240 | // Determine if we need to iterate the inputs. |
| 241 | // For now, we only do this if the new input has a required time lock. |
| 242 | // The BIP states that we should also do this if m_tx_modifiable's bit 2 is set |
| 243 | // (Has SIGHASH_SINGLE flag) but since we are only adding inputs at the end of the vector, |
| 244 | // we don't care about that. |
| 245 | bool iterate_inputs = psbtin.time_locktime != std::nullopt || psbtin.height_locktime != std::nullopt; |
| 246 | if (iterate_inputs) { |
| 247 | uint32_t old_timelock; |
| 248 | if (!ComputeTimeLock(old_timelock)) { |
| 249 | return false; |
| 250 | } |
| 251 | |
| 252 | std::optional<uint32_t> time_lock = psbtin.time_locktime; |
| 253 | std::optional<uint32_t> height_lock = psbtin.height_locktime; |
| 254 | bool has_sigs = false; |
| 255 | for (const PSBTInput& input : inputs) { |
| 256 | if (input.time_locktime != std::nullopt && input.height_locktime == std::nullopt) { |
| 257 | height_lock.reset(); // Transaction can no longer have a height locktime |
| 258 | if (time_lock == std::nullopt) { |
| 259 | return false; |
| 260 | } |
| 261 | } else if (input.time_locktime == std::nullopt && input.height_locktime != std::nullopt) { |
| 262 | time_lock.reset(); // Transaction can no longer have a time locktime |
| 263 | if (height_lock == std::nullopt) { |
| 264 | return false; |