Skip to content

Commit 7e30e3f

Browse files
committed
[MOVE-ONLY] Move fundrawtransaction to rpcwallet
1 parent 499d62a commit 7e30e3f

File tree

2 files changed

+149
-149
lines changed

2 files changed

+149
-149
lines changed

src/rpc/rawtransaction.cpp

Lines changed: 0 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -484,154 +484,6 @@ static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::
484484
vErrorsRet.push_back(entry);
485485
}
486486

487-
UniValue fundrawtransaction(const JSONRPCRequest& request)
488-
{
489-
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
490-
491-
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
492-
return NullUniValue;
493-
494-
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
495-
throw std::runtime_error(
496-
"fundrawtransaction \"hexstring\" ( options )\n"
497-
"\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
498-
"This will not modify existing inputs, and will add one change output to the outputs.\n"
499-
"Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
500-
"The inputs added will not be signed, use signrawtransaction for that.\n"
501-
"Note that all existing inputs must have their previous output transaction be in the wallet.\n"
502-
"Note that all inputs selected must be of standard form and P2SH scripts must be "
503-
"in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
504-
"You can see whether this is the case by checking the \"solvable\" field in the listunspent output.\n"
505-
"Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n"
506-
507-
"\nArguments:\n"
508-
"1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
509-
"2. options (object, optional)\n"
510-
" {\n"
511-
" \"changeAddress\" (string, optional, default pool address) The PIVX address to receive the change\n"
512-
" \"changePosition\" (numeric, optional, default random) The index of the change output\n"
513-
" \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n"
514-
" \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n"
515-
" \"feeRate\" (numeric, optional, default 0=estimate) Set a specific feerate (PIV per KB)\n"
516-
" \"subtractFeeFromOutputs\" (array, optional) A json array of integers.\n"
517-
" The fee will be equally deducted from the amount of each specified output.\n"
518-
" The outputs are specified by their zero-based index, before any change output is added.\n"
519-
" Those recipients will receive less PIV than you enter in their corresponding amount field.\n"
520-
" If no outputs are specified here, the sender pays the fee.\n"
521-
" [vout_index,...]\n"
522-
" }\n"
523-
"\nResult:\n"
524-
"{\n"
525-
" \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
526-
" \"fee\": n, (numeric) The fee added to the transaction\n"
527-
" \"changepos\": n (numeric) The position of the added change output, or -1\n"
528-
"}\n"
529-
"\"hex\" \n"
530-
"\nExamples:\n"
531-
"\nCreate a transaction with no inputs\n"
532-
+ HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
533-
"\nAdd sufficient unsigned inputs to meet the output value\n"
534-
+ HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
535-
"\nSign the transaction\n"
536-
+ HelpExampleCli("signrawtransaction", "\"fundedtransactionhex\"") +
537-
"\nSend the transaction\n"
538-
+ HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
539-
);
540-
541-
// Make sure the results are valid at least up to the most recent block
542-
// the user could have gotten from another RPC command prior to now
543-
pwallet->BlockUntilSyncedToCurrentChain();
544-
545-
RPCTypeCheck(request.params, {UniValue::VSTR});
546-
547-
CTxDestination changeAddress = CNoDestination();
548-
int changePosition = -1;
549-
bool includeWatching = false;
550-
bool lockUnspents = false;
551-
UniValue subtractFeeFromOutputs;
552-
std::set<int> setSubtractFeeFromOutputs;
553-
CFeeRate feeRate = CFeeRate(0);
554-
bool overrideEstimatedFeerate = false;
555-
556-
if (request.params.size() > 1) {
557-
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ});
558-
UniValue options = request.params[1];
559-
RPCTypeCheckObj(options,
560-
{
561-
{"changeAddress", UniValueType(UniValue::VSTR)},
562-
{"changePosition", UniValueType(UniValue::VNUM)},
563-
{"includeWatching", UniValueType(UniValue::VBOOL)},
564-
{"lockUnspents", UniValueType(UniValue::VBOOL)},
565-
{"feeRate", UniValueType()}, // will be checked below
566-
{"subtractFeeFromOutputs", UniValueType(UniValue::VARR)},
567-
},
568-
true, true);
569-
570-
if (options.exists("changeAddress")) {
571-
changeAddress = DecodeDestination(options["changeAddress"].get_str());
572-
573-
if (!IsValidDestination(changeAddress))
574-
throw JSONRPCError(RPC_INVALID_PARAMETER, "changeAddress must be a valid PIVX address");
575-
}
576-
577-
if (options.exists("changePosition"))
578-
changePosition = options["changePosition"].get_int();
579-
580-
if (options.exists("includeWatching"))
581-
includeWatching = options["includeWatching"].get_bool();
582-
583-
if (options.exists("lockUnspents"))
584-
lockUnspents = options["lockUnspents"].get_bool();
585-
586-
if (options.exists("feeRate")) {
587-
feeRate = CFeeRate(AmountFromValue(options["feeRate"]));
588-
overrideEstimatedFeerate = true;
589-
}
590-
591-
if (options.exists("subtractFeeFromOutputs")) {
592-
subtractFeeFromOutputs = options["subtractFeeFromOutputs"].get_array();
593-
}
594-
}
595-
596-
// parse hex string from parameter
597-
CMutableTransaction origTx;
598-
if (!DecodeHexTx(origTx, request.params[0].get_str()))
599-
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
600-
601-
if (origTx.vout.size() == 0)
602-
throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
603-
604-
if (changePosition != -1 && (changePosition < 0 || (unsigned int) changePosition > origTx.vout.size()))
605-
throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds");
606-
607-
for (unsigned int idx = 0; idx < subtractFeeFromOutputs.size(); idx++) {
608-
int pos = subtractFeeFromOutputs[idx].get_int();
609-
if (setSubtractFeeFromOutputs.count(pos))
610-
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, duplicated position: %d", pos));
611-
if (pos < 0)
612-
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, negative position: %d", pos));
613-
if (pos >= int(origTx.vout.size()))
614-
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, position too large: %d", pos));
615-
setSubtractFeeFromOutputs.insert(pos);
616-
}
617-
618-
CMutableTransaction tx(origTx);
619-
CAmount nFeeOut;
620-
std::string strFailReason;
621-
if(!pwallet->FundTransaction(tx, nFeeOut, overrideEstimatedFeerate, feeRate,
622-
changePosition, strFailReason, includeWatching,
623-
lockUnspents, setSubtractFeeFromOutputs, changeAddress)) {
624-
throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
625-
}
626-
627-
UniValue result(UniValue::VOBJ);
628-
result.pushKV("hex", EncodeHexTx(tx));
629-
result.pushKV("changepos", changePosition);
630-
result.pushKV("fee", ValueFromAmount(nFeeOut));
631-
632-
return result;
633-
}
634-
635487
UniValue signrawtransaction(const JSONRPCRequest& request)
636488
{
637489
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
@@ -1027,7 +879,6 @@ static const CRPCCommand commands[] =
1027879
{ "rawtransactions", "createrawtransaction", &createrawtransaction, true, {"inputs","outputs","locktime"} },
1028880
{ "rawtransactions", "decoderawtransaction", &decoderawtransaction, true, {"hexstring"} },
1029881
{ "rawtransactions", "decodescript", &decodescript, true, {"hexstring"} },
1030-
{ "rawtransactions", "fundrawtransaction", &fundrawtransaction, false, {"hexstring","options"} },
1031882
{ "rawtransactions", "getrawtransaction", &getrawtransaction, true, {"txid","verbose","blockhash"} },
1032883
{ "rawtransactions", "sendrawtransaction", &sendrawtransaction, false, {"hexstring","allowhighfees"} },
1033884
{ "rawtransactions", "signrawtransaction", &signrawtransaction, false, {"hexstring","prevtxs","privkeys","sighashtype"} }, /* uses wallet if enabled */

src/wallet/rpcwallet.cpp

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3800,6 +3800,154 @@ UniValue listunspent(const JSONRPCRequest& request)
38003800
return results;
38013801
}
38023802

3803+
UniValue fundrawtransaction(const JSONRPCRequest& request)
3804+
{
3805+
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3806+
3807+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
3808+
return NullUniValue;
3809+
3810+
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
3811+
throw std::runtime_error(
3812+
"fundrawtransaction \"hexstring\" ( options )\n"
3813+
"\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
3814+
"This will not modify existing inputs, and will add one change output to the outputs.\n"
3815+
"Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
3816+
"The inputs added will not be signed, use signrawtransaction for that.\n"
3817+
"Note that all existing inputs must have their previous output transaction be in the wallet.\n"
3818+
"Note that all inputs selected must be of standard form and P2SH scripts must be "
3819+
"in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
3820+
"You can see whether this is the case by checking the \"solvable\" field in the listunspent output.\n"
3821+
"Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n"
3822+
3823+
"\nArguments:\n"
3824+
"1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
3825+
"2. options (object, optional)\n"
3826+
" {\n"
3827+
" \"changeAddress\" (string, optional, default pool address) The PIVX address to receive the change\n"
3828+
" \"changePosition\" (numeric, optional, default random) The index of the change output\n"
3829+
" \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n"
3830+
" \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n"
3831+
" \"feeRate\" (numeric, optional, default 0=estimate) Set a specific feerate (PIV per KB)\n"
3832+
" \"subtractFeeFromOutputs\" (array, optional) A json array of integers.\n"
3833+
" The fee will be equally deducted from the amount of each specified output.\n"
3834+
" The outputs are specified by their zero-based index, before any change output is added.\n"
3835+
" Those recipients will receive less PIV than you enter in their corresponding amount field.\n"
3836+
" If no outputs are specified here, the sender pays the fee.\n"
3837+
" [vout_index,...]\n"
3838+
" }\n"
3839+
"\nResult:\n"
3840+
"{\n"
3841+
" \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
3842+
" \"fee\": n, (numeric) The fee added to the transaction\n"
3843+
" \"changepos\": n (numeric) The position of the added change output, or -1\n"
3844+
"}\n"
3845+
"\"hex\" \n"
3846+
"\nExamples:\n"
3847+
"\nCreate a transaction with no inputs\n"
3848+
+ HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
3849+
"\nAdd sufficient unsigned inputs to meet the output value\n"
3850+
+ HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
3851+
"\nSign the transaction\n"
3852+
+ HelpExampleCli("signrawtransaction", "\"fundedtransactionhex\"") +
3853+
"\nSend the transaction\n"
3854+
+ HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
3855+
);
3856+
3857+
// Make sure the results are valid at least up to the most recent block
3858+
// the user could have gotten from another RPC command prior to now
3859+
pwallet->BlockUntilSyncedToCurrentChain();
3860+
3861+
RPCTypeCheck(request.params, {UniValue::VSTR});
3862+
3863+
CTxDestination changeAddress = CNoDestination();
3864+
int changePosition = -1;
3865+
bool includeWatching = false;
3866+
bool lockUnspents = false;
3867+
UniValue subtractFeeFromOutputs;
3868+
std::set<int> setSubtractFeeFromOutputs;
3869+
CFeeRate feeRate = CFeeRate(0);
3870+
bool overrideEstimatedFeerate = false;
3871+
3872+
if (request.params.size() > 1) {
3873+
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ});
3874+
UniValue options = request.params[1];
3875+
RPCTypeCheckObj(options,
3876+
{
3877+
{"changeAddress", UniValueType(UniValue::VSTR)},
3878+
{"changePosition", UniValueType(UniValue::VNUM)},
3879+
{"includeWatching", UniValueType(UniValue::VBOOL)},
3880+
{"lockUnspents", UniValueType(UniValue::VBOOL)},
3881+
{"feeRate", UniValueType()}, // will be checked below
3882+
{"subtractFeeFromOutputs", UniValueType(UniValue::VARR)},
3883+
},
3884+
true, true);
3885+
3886+
if (options.exists("changeAddress")) {
3887+
changeAddress = DecodeDestination(options["changeAddress"].get_str());
3888+
3889+
if (!IsValidDestination(changeAddress))
3890+
throw JSONRPCError(RPC_INVALID_PARAMETER, "changeAddress must be a valid PIVX address");
3891+
}
3892+
3893+
if (options.exists("changePosition"))
3894+
changePosition = options["changePosition"].get_int();
3895+
3896+
if (options.exists("includeWatching"))
3897+
includeWatching = options["includeWatching"].get_bool();
3898+
3899+
if (options.exists("lockUnspents"))
3900+
lockUnspents = options["lockUnspents"].get_bool();
3901+
3902+
if (options.exists("feeRate")) {
3903+
feeRate = CFeeRate(AmountFromValue(options["feeRate"]));
3904+
overrideEstimatedFeerate = true;
3905+
}
3906+
3907+
if (options.exists("subtractFeeFromOutputs")) {
3908+
subtractFeeFromOutputs = options["subtractFeeFromOutputs"].get_array();
3909+
}
3910+
}
3911+
3912+
// parse hex string from parameter
3913+
CMutableTransaction origTx;
3914+
if (!DecodeHexTx(origTx, request.params[0].get_str()))
3915+
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
3916+
3917+
if (origTx.vout.size() == 0)
3918+
throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
3919+
3920+
if (changePosition != -1 && (changePosition < 0 || (unsigned int) changePosition > origTx.vout.size()))
3921+
throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds");
3922+
3923+
for (unsigned int idx = 0; idx < subtractFeeFromOutputs.size(); idx++) {
3924+
int pos = subtractFeeFromOutputs[idx].get_int();
3925+
if (setSubtractFeeFromOutputs.count(pos))
3926+
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, duplicated position: %d", pos));
3927+
if (pos < 0)
3928+
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, negative position: %d", pos));
3929+
if (pos >= int(origTx.vout.size()))
3930+
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, position too large: %d", pos));
3931+
setSubtractFeeFromOutputs.insert(pos);
3932+
}
3933+
3934+
CMutableTransaction tx(origTx);
3935+
CAmount nFeeOut;
3936+
std::string strFailReason;
3937+
if(!pwallet->FundTransaction(tx, nFeeOut, overrideEstimatedFeerate, feeRate,
3938+
changePosition, strFailReason, includeWatching,
3939+
lockUnspents, setSubtractFeeFromOutputs, changeAddress)) {
3940+
throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
3941+
}
3942+
3943+
UniValue result(UniValue::VOBJ);
3944+
result.pushKV("hex", EncodeHexTx(tx));
3945+
result.pushKV("changepos", changePosition);
3946+
result.pushKV("fee", ValueFromAmount(nFeeOut));
3947+
3948+
return result;
3949+
}
3950+
38033951
UniValue lockunspent(const JSONRPCRequest& request)
38043952
{
38053953
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
@@ -4531,6 +4679,7 @@ static const CRPCCommand commands[] =
45314679
{ "wallet", "dumpprivkey", &dumpprivkey, true, {"address"} },
45324680
{ "wallet", "dumpwallet", &dumpwallet, true, {"filename"} },
45334681
{ "wallet", "encryptwallet", &encryptwallet, true, {"passphrase"} },
4682+
{ "wallet", "fundrawtransaction", &fundrawtransaction, false, {"hexstring","options"} },
45344683
{ "wallet", "getbalance", &getbalance, false, {"minconf","include_watchonly","include_delegated","include_shield"} },
45354684
{ "wallet", "getcoldstakingbalance", &getcoldstakingbalance, false, {} },
45364685
{ "wallet", "getdelegatedbalance", &getdelegatedbalance, false, {} },

0 commit comments

Comments
 (0)