| 258 | } |
| 259 | |
| 260 | static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInput) |
| 261 | { |
| 262 | std::vector<std::string> vStrInputParts = SplitString(strInput, ':'); |
| 263 | |
| 264 | // separate TXID:VOUT in string |
| 265 | if (vStrInputParts.size()<2) |
| 266 | throw std::runtime_error("TX input missing separator"); |
| 267 | |
| 268 | // extract and validate TXID |
| 269 | auto txid{Txid::FromHex(vStrInputParts[0])}; |
| 270 | if (!txid) { |
| 271 | throw std::runtime_error("invalid TX input txid"); |
| 272 | } |
| 273 | |
| 274 | static const unsigned int minTxOutSz = 9; |
| 275 | static const unsigned int maxVout = MAX_BLOCK_WEIGHT / (WITNESS_SCALE_FACTOR * minTxOutSz); |
| 276 | |
| 277 | // extract and validate vout |
| 278 | const std::string& strVout = vStrInputParts[1]; |
| 279 | const auto vout{ToIntegral<uint32_t>(strVout)}; |
| 280 | if (!vout || *vout > maxVout) { |
| 281 | throw std::runtime_error("invalid TX input vout '" + strVout + "'"); |
| 282 | } |
| 283 | |
| 284 | // extract the optional sequence number |
| 285 | uint32_t nSequenceIn = CTxIn::SEQUENCE_FINAL; |
| 286 | if (vStrInputParts.size() > 2) { |
| 287 | nSequenceIn = TrimAndParse<uint32_t>(vStrInputParts.at(2), "invalid TX sequence id"); |
| 288 | } |
| 289 | |
| 290 | // append to transaction input list |
| 291 | CTxIn txin{*txid, *vout, CScript{}, nSequenceIn}; |
| 292 | tx.vin.push_back(txin); |
| 293 | } |
| 294 | |
| 295 | static void MutateTxAddOutAddr(CMutableTransaction& tx, const std::string& strInput) |
| 296 | { |