| 146 | } |
| 147 | |
| 148 | CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, bool rbf, const CBlockIndex* active_chain_tip, std::map<CTxOut, PSBTOutput>* outputs_aux, bool allow_peg_in, bool allow_issuance) |
| 149 | { |
| 150 | if (outputs_in.isNull()) { |
| 151 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, output argument must be non-null"); |
| 152 | } |
| 153 | |
| 154 | UniValue inputs; |
| 155 | if (inputs_in.isNull()) { |
| 156 | inputs = UniValue::VARR; |
| 157 | } else { |
| 158 | inputs = inputs_in.get_array(); |
| 159 | } |
| 160 | |
| 161 | UniValue outputs = outputs_in.get_array(); |
| 162 | |
| 163 | CMutableTransaction rawTx; |
| 164 | |
| 165 | if (!locktime.isNull()) { |
| 166 | int64_t nLockTime = locktime.get_int64(); |
| 167 | if (nLockTime < 0 || nLockTime > LOCKTIME_MAX) |
| 168 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, locktime out of range"); |
| 169 | rawTx.nLockTime = nLockTime; |
| 170 | } |
| 171 | |
| 172 | for (unsigned int idx = 0; idx < inputs.size(); idx++) { |
| 173 | const UniValue& input = inputs[idx]; |
| 174 | const UniValue& o = input.get_obj(); |
| 175 | |
| 176 | uint256 txid = ParseHashO(o, "txid"); |
| 177 | |
| 178 | const UniValue& vout_v = find_value(o, "vout"); |
| 179 | if (!vout_v.isNum()) |
| 180 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key"); |
| 181 | int nOutput = vout_v.get_int(); |
| 182 | if (nOutput < 0) |
| 183 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout cannot be negative"); |
| 184 | |
| 185 | uint32_t nSequence; |
| 186 | if (rbf) { |
| 187 | nSequence = MAX_BIP125_RBF_SEQUENCE; /* CTxIn::SEQUENCE_FINAL - 2 */ |
| 188 | } else if (rawTx.nLockTime) { |
| 189 | nSequence = CTxIn::MAX_SEQUENCE_NONFINAL; /* CTxIn::SEQUENCE_FINAL - 1 */ |
| 190 | } else { |
| 191 | nSequence = CTxIn::SEQUENCE_FINAL; |
| 192 | } |
| 193 | |
| 194 | // set the sequence number if passed in the parameters object |
| 195 | const UniValue& sequenceObj = find_value(o, "sequence"); |
| 196 | if (sequenceObj.isNum()) { |
| 197 | int64_t seqNr64 = sequenceObj.get_int64(); |
| 198 | if (seqNr64 < 0 || seqNr64 > CTxIn::SEQUENCE_FINAL) { |
| 199 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, sequence number is out of range"); |
| 200 | } else { |
| 201 | nSequence = (uint32_t)seqNr64; |
| 202 | } |
| 203 | } |
| 204 | |
| 205 | CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence); |
no test coverage detected