| 3466 | } |
| 3467 | |
| 3468 | void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& fee_out, int& change_position, UniValue options) |
| 3469 | { |
| 3470 | // Make sure the results are valid at least up to the most recent block |
| 3471 | // the user could have gotten from another RPC command prior to now |
| 3472 | pwallet->BlockUntilSyncedToCurrentChain(); |
| 3473 | |
| 3474 | CCoinControl coinControl; |
| 3475 | change_position = -1; |
| 3476 | bool lockUnspents = false; |
| 3477 | UniValue subtractFeeFromOutputs; |
| 3478 | std::set<int> setSubtractFeeFromOutputs; |
| 3479 | |
| 3480 | if (!options.isNull()) { |
| 3481 | if (options.type() == UniValue::VBOOL) { |
| 3482 | // backward compatibility bool only fallback |
| 3483 | coinControl.fAllowWatchOnly = options.get_bool(); |
| 3484 | } |
| 3485 | else { |
| 3486 | RPCTypeCheckArgument(options, UniValue::VOBJ); |
| 3487 | RPCTypeCheckObj(options, |
| 3488 | { |
| 3489 | {"changeAddress", UniValueType(UniValue::VSTR)}, |
| 3490 | {"changePosition", UniValueType(UniValue::VNUM)}, |
| 3491 | {"change_type", UniValueType(UniValue::VSTR)}, |
| 3492 | {"includeWatching", UniValueType(UniValue::VBOOL)}, |
| 3493 | {"lockUnspents", UniValueType(UniValue::VBOOL)}, |
| 3494 | {"feeRate", UniValueType()}, // will be checked below |
| 3495 | {"subtractFeeFromOutputs", UniValueType(UniValue::VARR)}, |
| 3496 | {"replaceable", UniValueType(UniValue::VBOOL)}, |
| 3497 | {"conf_target", UniValueType(UniValue::VNUM)}, |
| 3498 | {"estimate_mode", UniValueType(UniValue::VSTR)}, |
| 3499 | }, |
| 3500 | true, true); |
| 3501 | |
| 3502 | if (options.exists("changeAddress")) { |
| 3503 | CTxDestination dest = DecodeDestination(options["changeAddress"].get_str()); |
| 3504 | |
| 3505 | if (!IsValidDestination(dest)) { |
| 3506 | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "changeAddress must be a valid bitcoin address"); |
| 3507 | } |
| 3508 | |
| 3509 | coinControl.destChange = dest; |
| 3510 | } |
| 3511 | |
| 3512 | if (options.exists("changePosition")) |
| 3513 | change_position = options["changePosition"].get_int(); |
| 3514 | |
| 3515 | if (options.exists("change_type")) { |
| 3516 | if (options.exists("changeAddress")) { |
| 3517 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both changeAddress and address_type options"); |
| 3518 | } |
| 3519 | coinControl.m_change_type = pwallet->m_default_change_type; |
| 3520 | if (!ParseOutputType(options["change_type"].get_str(), *coinControl.m_change_type)) { |
| 3521 | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown change type '%s'", options["change_type"].get_str())); |
| 3522 | } |
| 3523 | } |
| 3524 | |
| 3525 | if (options.exists("includeWatching")) |
no test coverage detected