You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

rawtransaction.cpp 43KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. // Copyright (c) 2010 Satoshi Nakamoto
  2. // Copyright (c) 2009-2016 The Starwels developers
  3. // Distributed under the MIT software license, see the accompanying
  4. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  5. #include "base58.h"
  6. #include "chain.h"
  7. #include "coins.h"
  8. #include "consensus/validation.h"
  9. #include "core_io.h"
  10. #include "init.h"
  11. #include "keystore.h"
  12. #include "validation.h"
  13. #include "merkleblock.h"
  14. #include "net.h"
  15. #include "policy/policy.h"
  16. #include "policy/rbf.h"
  17. #include "primitives/transaction.h"
  18. #include "rpc/server.h"
  19. #include "script/script.h"
  20. #include "script/script_error.h"
  21. #include "script/sign.h"
  22. #include "script/standard.h"
  23. #include "txmempool.h"
  24. #include "uint256.h"
  25. #include "utilstrencodings.h"
  26. #ifdef ENABLE_WALLET
  27. #include "wallet/rpcwallet.h"
  28. #include "wallet/wallet.h"
  29. #endif
  30. #include <stdint.h>
  31. #include <univalue.h>
  32. void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
  33. {
  34. // Call into TxToUniv() in starwels-common to decode the transaction hex.
  35. //
  36. // Blockchain contextual information (confirmations and blocktime) is not
  37. // available to code in starwels-common, so we query them here and push the
  38. // data into the returned UniValue.
  39. TxToUniv(tx, uint256(), entry, true, RPCSerializationFlags());
  40. if (!hashBlock.IsNull()) {
  41. entry.push_back(Pair("blockhash", hashBlock.GetHex()));
  42. BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
  43. if (mi != mapBlockIndex.end() && (*mi).second) {
  44. CBlockIndex* pindex = (*mi).second;
  45. if (chainActive.Contains(pindex)) {
  46. entry.push_back(Pair("confirmations", 1 + chainActive.Height() - pindex->nHeight));
  47. entry.push_back(Pair("time", pindex->GetBlockTime()));
  48. entry.push_back(Pair("blocktime", pindex->GetBlockTime()));
  49. }
  50. else
  51. entry.push_back(Pair("confirmations", 0));
  52. }
  53. }
  54. }
  55. UniValue getrawtransaction(const JSONRPCRequest& request)
  56. {
  57. if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
  58. throw std::runtime_error(
  59. "getrawtransaction \"txid\" ( verbose )\n"
  60. "\nNOTE: By default this function only works for mempool transactions. If the -txindex option is\n"
  61. "enabled, it also works for blockchain transactions.\n"
  62. "DEPRECATED: for now, it also works for transactions with unspent outputs.\n"
  63. "\nReturn the raw transaction data.\n"
  64. "\nIf verbose is 'true', returns an Object with information about 'txid'.\n"
  65. "If verbose is 'false' or omitted, returns a string that is serialized, hex-encoded data for 'txid'.\n"
  66. "\nArguments:\n"
  67. "1. \"txid\" (string, required) The transaction id\n"
  68. "2. verbose (bool, optional, default=false) If false, return a string, otherwise return a json object\n"
  69. "\nResult (if verbose is not set or set to false):\n"
  70. "\"data\" (string) The serialized, hex-encoded data for 'txid'\n"
  71. "\nResult (if verbose is set to true):\n"
  72. "{\n"
  73. " \"hex\" : \"data\", (string) The serialized, hex-encoded data for 'txid'\n"
  74. " \"txid\" : \"id\", (string) The transaction id (same as provided)\n"
  75. " \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n"
  76. " \"size\" : n, (numeric) The serialized transaction size\n"
  77. " \"vsize\" : n, (numeric) The virtual transaction size (differs from size for witness transactions)\n"
  78. " \"version\" : n, (numeric) The version\n"
  79. " \"locktime\" : ttt, (numeric) The lock time\n"
  80. " \"vin\" : [ (array of json objects)\n"
  81. " {\n"
  82. " \"txid\": \"id\", (string) The transaction id\n"
  83. " \"vout\": n, (numeric) \n"
  84. " \"scriptSig\": { (json object) The script\n"
  85. " \"asm\": \"asm\", (string) asm\n"
  86. " \"hex\": \"hex\" (string) hex\n"
  87. " },\n"
  88. " \"sequence\": n (numeric) The script sequence number\n"
  89. " \"txinwitness\": [\"hex\", ...] (array of string) hex-encoded witness data (if any)\n"
  90. " }\n"
  91. " ,...\n"
  92. " ],\n"
  93. " \"vout\" : [ (array of json objects)\n"
  94. " {\n"
  95. " \"value\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n"
  96. " \"n\" : n, (numeric) index\n"
  97. " \"scriptPubKey\" : { (json object)\n"
  98. " \"asm\" : \"asm\", (string) the asm\n"
  99. " \"hex\" : \"hex\", (string) the hex\n"
  100. " \"reqSigs\" : n, (numeric) The required sigs\n"
  101. " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
  102. " \"addresses\" : [ (json array of string)\n"
  103. " \"address\" (string) starwels address\n"
  104. " ,...\n"
  105. " ]\n"
  106. " }\n"
  107. " }\n"
  108. " ,...\n"
  109. " ],\n"
  110. " \"blockhash\" : \"hash\", (string) the block hash\n"
  111. " \"confirmations\" : n, (numeric) The confirmations\n"
  112. " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT)\n"
  113. " \"blocktime\" : ttt (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
  114. "}\n"
  115. "\nExamples:\n"
  116. + HelpExampleCli("getrawtransaction", "\"mytxid\"")
  117. + HelpExampleCli("getrawtransaction", "\"mytxid\" true")
  118. + HelpExampleRpc("getrawtransaction", "\"mytxid\", true")
  119. );
  120. LOCK(cs_main);
  121. uint256 hash = ParseHashV(request.params[0], "parameter 1");
  122. // Accept either a bool (true) or a num (>=1) to indicate verbose output.
  123. bool fVerbose = false;
  124. if (!request.params[1].isNull()) {
  125. if (request.params[1].isNum()) {
  126. if (request.params[1].get_int() != 0) {
  127. fVerbose = true;
  128. }
  129. }
  130. else if(request.params[1].isBool()) {
  131. if(request.params[1].isTrue()) {
  132. fVerbose = true;
  133. }
  134. }
  135. else {
  136. throw JSONRPCError(RPC_TYPE_ERROR, "Invalid type provided. Verbose parameter must be a boolean.");
  137. }
  138. }
  139. CTransactionRef tx;
  140. uint256 hashBlock;
  141. if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true))
  142. throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string(fTxIndex ? "No such mempool or blockchain transaction"
  143. : "No such mempool transaction. Use -txindex to enable blockchain transaction queries") +
  144. ". Use gettransaction for wallet transactions.");
  145. if (!fVerbose)
  146. return EncodeHexTx(*tx, RPCSerializationFlags());
  147. UniValue result(UniValue::VOBJ);
  148. TxToJSON(*tx, hashBlock, result);
  149. return result;
  150. }
  151. UniValue gettxoutproof(const JSONRPCRequest& request)
  152. {
  153. if (request.fHelp || (request.params.size() != 1 && request.params.size() != 2))
  154. throw std::runtime_error(
  155. "gettxoutproof [\"txid\",...] ( blockhash )\n"
  156. "\nReturns a hex-encoded proof that \"txid\" was included in a block.\n"
  157. "\nNOTE: By default this function only works sometimes. This is when there is an\n"
  158. "unspent output in the utxo for this transaction. To make it always work,\n"
  159. "you need to maintain a transaction index, using the -txindex command line option or\n"
  160. "specify the block in which the transaction is included manually (by blockhash).\n"
  161. "\nArguments:\n"
  162. "1. \"txids\" (string) A json array of txids to filter\n"
  163. " [\n"
  164. " \"txid\" (string) A transaction hash\n"
  165. " ,...\n"
  166. " ]\n"
  167. "2. \"blockhash\" (string, optional) If specified, looks for txid in the block with this hash\n"
  168. "\nResult:\n"
  169. "\"data\" (string) A string that is a serialized, hex-encoded data for the proof.\n"
  170. );
  171. std::set<uint256> setTxids;
  172. uint256 oneTxid;
  173. UniValue txids = request.params[0].get_array();
  174. for (unsigned int idx = 0; idx < txids.size(); idx++) {
  175. const UniValue& txid = txids[idx];
  176. if (txid.get_str().length() != 64 || !IsHex(txid.get_str()))
  177. throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid txid ")+txid.get_str());
  178. uint256 hash(uint256S(txid.get_str()));
  179. if (setTxids.count(hash))
  180. throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated txid: ")+txid.get_str());
  181. setTxids.insert(hash);
  182. oneTxid = hash;
  183. }
  184. LOCK(cs_main);
  185. CBlockIndex* pblockindex = nullptr;
  186. uint256 hashBlock;
  187. if (!request.params[1].isNull())
  188. {
  189. hashBlock = uint256S(request.params[1].get_str());
  190. if (!mapBlockIndex.count(hashBlock))
  191. throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
  192. pblockindex = mapBlockIndex[hashBlock];
  193. } else {
  194. // Loop through txids and try to find which block they're in. Exit loop once a block is found.
  195. for (const auto& tx : setTxids) {
  196. const Coin& coin = AccessByTxid(*pcoinsTip, tx);
  197. if (!coin.IsSpent()) {
  198. pblockindex = chainActive[coin.nHeight];
  199. break;
  200. }
  201. }
  202. }
  203. if (pblockindex == nullptr)
  204. {
  205. CTransactionRef tx;
  206. if (!GetTransaction(oneTxid, tx, Params().GetConsensus(), hashBlock, false) || hashBlock.IsNull())
  207. throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not yet in block");
  208. if (!mapBlockIndex.count(hashBlock))
  209. throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction index corrupt");
  210. pblockindex = mapBlockIndex[hashBlock];
  211. }
  212. CBlock block;
  213. if(!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()))
  214. throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
  215. unsigned int ntxFound = 0;
  216. for (const auto& tx : block.vtx)
  217. if (setTxids.count(tx->GetHash()))
  218. ntxFound++;
  219. if (ntxFound != setTxids.size())
  220. throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Not all transactions found in specified or retrieved block");
  221. CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
  222. CMerkleBlock mb(block, setTxids);
  223. ssMB << mb;
  224. std::string strHex = HexStr(ssMB.begin(), ssMB.end());
  225. return strHex;
  226. }
  227. UniValue verifytxoutproof(const JSONRPCRequest& request)
  228. {
  229. if (request.fHelp || request.params.size() != 1)
  230. throw std::runtime_error(
  231. "verifytxoutproof \"proof\"\n"
  232. "\nVerifies that a proof points to a transaction in a block, returning the transaction it commits to\n"
  233. "and throwing an RPC error if the block is not in our best chain\n"
  234. "\nArguments:\n"
  235. "1. \"proof\" (string, required) The hex-encoded proof generated by gettxoutproof\n"
  236. "\nResult:\n"
  237. "[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof is invalid\n"
  238. );
  239. CDataStream ssMB(ParseHexV(request.params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
  240. CMerkleBlock merkleBlock;
  241. ssMB >> merkleBlock;
  242. UniValue res(UniValue::VARR);
  243. std::vector<uint256> vMatch;
  244. std::vector<unsigned int> vIndex;
  245. if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) != merkleBlock.header.hashMerkleRoot)
  246. return res;
  247. LOCK(cs_main);
  248. if (!mapBlockIndex.count(merkleBlock.header.GetHash()) || !chainActive.Contains(mapBlockIndex[merkleBlock.header.GetHash()]))
  249. throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain");
  250. for (const uint256& hash : vMatch)
  251. res.push_back(hash.GetHex());
  252. return res;
  253. }
  254. UniValue createrawtransaction(const JSONRPCRequest& request)
  255. {
  256. if (request.fHelp || request.params.size() < 2 || request.params.size() > 4)
  257. throw std::runtime_error(
  258. "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,\"data\":\"hex\",...} ( locktime ) ( replaceable )\n"
  259. "\nCreate a transaction spending the given inputs and creating new outputs.\n"
  260. "Outputs can be addresses or data.\n"
  261. "Returns hex-encoded raw transaction.\n"
  262. "Note that the transaction's inputs are not signed, and\n"
  263. "it is not stored in the wallet or transmitted to the network.\n"
  264. "\nArguments:\n"
  265. "1. \"inputs\" (array, required) A json array of json objects\n"
  266. " [\n"
  267. " {\n"
  268. " \"txid\":\"id\", (string, required) The transaction id\n"
  269. " \"vout\":n, (numeric, required) The output number\n"
  270. " \"sequence\":n (numeric, optional) The sequence number\n"
  271. " } \n"
  272. " ,...\n"
  273. " ]\n"
  274. "2. \"outputs\" (object, required) a json object with outputs\n"
  275. " {\n"
  276. " \"address\": x.xxx, (numeric or string, required) The key is the starwels address, the numeric value (can be string) is the " + CURRENCY_UNIT + " amount\n"
  277. " \"data\": \"hex\" (string, required) The key is \"data\", the value is hex encoded data\n"
  278. " ,...\n"
  279. " }\n"
  280. "3. locktime (numeric, optional, default=0) Raw locktime. Non-0 value also locktime-activates inputs\n"
  281. "4. replaceable (boolean, optional, default=false) Marks this transaction as BIP125 replaceable.\n"
  282. " Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible.\n"
  283. "\nResult:\n"
  284. "\"transaction\" (string) hex string of the transaction\n"
  285. "\nExamples:\n"
  286. + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"{\\\"address\\\":0.01}\"")
  287. + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"{\\\"data\\\":\\\"00010203\\\"}\"")
  288. + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"address\\\":0.01}\"")
  289. + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"data\\\":\\\"00010203\\\"}\"")
  290. );
  291. RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VOBJ, UniValue::VNUM}, true);
  292. if (request.params[0].isNull() || request.params[1].isNull())
  293. throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, arguments 1 and 2 must be non-null");
  294. UniValue inputs = request.params[0].get_array();
  295. UniValue sendTo = request.params[1].get_obj();
  296. CMutableTransaction rawTx;
  297. if (request.params.size() > 2 && !request.params[2].isNull()) {
  298. int64_t nLockTime = request.params[2].get_int64();
  299. if (nLockTime < 0 || nLockTime > std::numeric_limits<uint32_t>::max())
  300. throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, locktime out of range");
  301. rawTx.nLockTime = nLockTime;
  302. }
  303. bool rbfOptIn = request.params.size() > 3 ? request.params[3].isTrue() : false;
  304. for (unsigned int idx = 0; idx < inputs.size(); idx++) {
  305. const UniValue& input = inputs[idx];
  306. const UniValue& o = input.get_obj();
  307. uint256 txid = ParseHashO(o, "txid");
  308. const UniValue& vout_v = find_value(o, "vout");
  309. if (!vout_v.isNum())
  310. throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
  311. int nOutput = vout_v.get_int();
  312. if (nOutput < 0)
  313. throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
  314. uint32_t nSequence;
  315. if (rbfOptIn) {
  316. nSequence = MAX_BIP125_RBF_SEQUENCE;
  317. } else if (rawTx.nLockTime) {
  318. nSequence = std::numeric_limits<uint32_t>::max() - 1;
  319. } else {
  320. nSequence = std::numeric_limits<uint32_t>::max();
  321. }
  322. // set the sequence number if passed in the parameters object
  323. const UniValue& sequenceObj = find_value(o, "sequence");
  324. if (sequenceObj.isNum()) {
  325. int64_t seqNr64 = sequenceObj.get_int64();
  326. if (seqNr64 < 0 || seqNr64 > std::numeric_limits<uint32_t>::max()) {
  327. throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, sequence number is out of range");
  328. } else {
  329. nSequence = (uint32_t)seqNr64;
  330. }
  331. }
  332. CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence);
  333. rawTx.vin.push_back(in);
  334. }
  335. std::set<CStarwelsAddress> setAddress;
  336. std::vector<std::string> addrList = sendTo.getKeys();
  337. for (const std::string& name_ : addrList) {
  338. if (name_ == "data") {
  339. std::vector<unsigned char> data = ParseHexV(sendTo[name_].getValStr(),"Data");
  340. CTxOut out(0, CScript() << OP_RETURN << data);
  341. rawTx.vout.push_back(out);
  342. } else {
  343. CStarwelsAddress address(name_);
  344. if (!address.IsValid())
  345. throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Starwels address: ")+name_);
  346. if (setAddress.count(address))
  347. throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ")+name_);
  348. setAddress.insert(address);
  349. CScript scriptPubKey = GetScriptForDestination(address.Get());
  350. CAmount nAmount = AmountFromValue(sendTo[name_]);
  351. CTxOut out(nAmount, scriptPubKey);
  352. rawTx.vout.push_back(out);
  353. }
  354. }
  355. if (!request.params[3].isNull() && rbfOptIn != SignalsOptInRBF(rawTx)) {
  356. throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter combination: Sequence number(s) contradict replaceable option");
  357. }
  358. return EncodeHexTx(rawTx);
  359. }
  360. UniValue decoderawtransaction(const JSONRPCRequest& request)
  361. {
  362. if (request.fHelp || request.params.size() != 1)
  363. throw std::runtime_error(
  364. "decoderawtransaction \"hexstring\"\n"
  365. "\nReturn a JSON object representing the serialized, hex-encoded transaction.\n"
  366. "\nArguments:\n"
  367. "1. \"hexstring\" (string, required) The transaction hex string\n"
  368. "\nResult:\n"
  369. "{\n"
  370. " \"txid\" : \"id\", (string) The transaction id\n"
  371. " \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n"
  372. " \"size\" : n, (numeric) The transaction size\n"
  373. " \"vsize\" : n, (numeric) The virtual transaction size (differs from size for witness transactions)\n"
  374. " \"version\" : n, (numeric) The version\n"
  375. " \"locktime\" : ttt, (numeric) The lock time\n"
  376. " \"vin\" : [ (array of json objects)\n"
  377. " {\n"
  378. " \"txid\": \"id\", (string) The transaction id\n"
  379. " \"vout\": n, (numeric) The output number\n"
  380. " \"scriptSig\": { (json object) The script\n"
  381. " \"asm\": \"asm\", (string) asm\n"
  382. " \"hex\": \"hex\" (string) hex\n"
  383. " },\n"
  384. " \"txinwitness\": [\"hex\", ...] (array of string) hex-encoded witness data (if any)\n"
  385. " \"sequence\": n (numeric) The script sequence number\n"
  386. " }\n"
  387. " ,...\n"
  388. " ],\n"
  389. " \"vout\" : [ (array of json objects)\n"
  390. " {\n"
  391. " \"value\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n"
  392. " \"n\" : n, (numeric) index\n"
  393. " \"scriptPubKey\" : { (json object)\n"
  394. " \"asm\" : \"asm\", (string) the asm\n"
  395. " \"hex\" : \"hex\", (string) the hex\n"
  396. " \"reqSigs\" : n, (numeric) The required sigs\n"
  397. " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
  398. " \"addresses\" : [ (json array of string)\n"
  399. " \"12tvKAXCxZjSmdNbao16dKXC8tRWfcF5oc\" (string) starwels address\n"
  400. " ,...\n"
  401. " ]\n"
  402. " }\n"
  403. " }\n"
  404. " ,...\n"
  405. " ],\n"
  406. "}\n"
  407. "\nExamples:\n"
  408. + HelpExampleCli("decoderawtransaction", "\"hexstring\"")
  409. + HelpExampleRpc("decoderawtransaction", "\"hexstring\"")
  410. );
  411. LOCK(cs_main);
  412. RPCTypeCheck(request.params, {UniValue::VSTR});
  413. CMutableTransaction mtx;
  414. if (!DecodeHexTx(mtx, request.params[0].get_str(), true))
  415. throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
  416. UniValue result(UniValue::VOBJ);
  417. TxToUniv(CTransaction(std::move(mtx)), uint256(), result, false);
  418. return result;
  419. }
  420. UniValue decodescript(const JSONRPCRequest& request)
  421. {
  422. if (request.fHelp || request.params.size() != 1)
  423. throw std::runtime_error(
  424. "decodescript \"hexstring\"\n"
  425. "\nDecode a hex-encoded script.\n"
  426. "\nArguments:\n"
  427. "1. \"hexstring\" (string) the hex encoded script\n"
  428. "\nResult:\n"
  429. "{\n"
  430. " \"asm\":\"asm\", (string) Script public key\n"
  431. " \"hex\":\"hex\", (string) hex encoded public key\n"
  432. " \"type\":\"type\", (string) The output type\n"
  433. " \"reqSigs\": n, (numeric) The required signatures\n"
  434. " \"addresses\": [ (json array of string)\n"
  435. " \"address\" (string) starwels address\n"
  436. " ,...\n"
  437. " ],\n"
  438. " \"p2sh\",\"address\" (string) address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH).\n"
  439. "}\n"
  440. "\nExamples:\n"
  441. + HelpExampleCli("decodescript", "\"hexstring\"")
  442. + HelpExampleRpc("decodescript", "\"hexstring\"")
  443. );
  444. RPCTypeCheck(request.params, {UniValue::VSTR});
  445. UniValue r(UniValue::VOBJ);
  446. CScript script;
  447. if (request.params[0].get_str().size() > 0){
  448. std::vector<unsigned char> scriptData(ParseHexV(request.params[0], "argument"));
  449. script = CScript(scriptData.begin(), scriptData.end());
  450. } else {
  451. // Empty scripts are valid
  452. }
  453. ScriptPubKeyToUniv(script, r, false);
  454. UniValue type;
  455. type = find_value(r, "type");
  456. if (type.isStr() && type.get_str() != "scripthash") {
  457. // P2SH cannot be wrapped in a P2SH. If this script is already a P2SH,
  458. // don't return the address for a P2SH of the P2SH.
  459. r.push_back(Pair("p2sh", CStarwelsAddress(CScriptID(script)).ToString()));
  460. }
  461. return r;
  462. }
  463. /** Pushes a JSON object for script verification or signing errors to vErrorsRet. */
  464. static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::string& strMessage)
  465. {
  466. UniValue entry(UniValue::VOBJ);
  467. entry.push_back(Pair("txid", txin.prevout.hash.ToString()));
  468. entry.push_back(Pair("vout", (uint64_t)txin.prevout.n));
  469. UniValue witness(UniValue::VARR);
  470. for (unsigned int i = 0; i < txin.scriptWitness.stack.size(); i++) {
  471. witness.push_back(HexStr(txin.scriptWitness.stack[i].begin(), txin.scriptWitness.stack[i].end()));
  472. }
  473. entry.push_back(Pair("witness", witness));
  474. entry.push_back(Pair("scriptSig", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
  475. entry.push_back(Pair("sequence", (uint64_t)txin.nSequence));
  476. entry.push_back(Pair("error", strMessage));
  477. vErrorsRet.push_back(entry);
  478. }
  479. UniValue combinerawtransaction(const JSONRPCRequest& request)
  480. {
  481. if (request.fHelp || request.params.size() != 1)
  482. throw std::runtime_error(
  483. "combinerawtransaction [\"hexstring\",...]\n"
  484. "\nCombine multiple partially signed transactions into one transaction.\n"
  485. "The combined transaction may be another partially signed transaction or a \n"
  486. "fully signed transaction."
  487. "\nArguments:\n"
  488. "1. \"txs\" (string) A json array of hex strings of partially signed transactions\n"
  489. " [\n"
  490. " \"hexstring\" (string) A transaction hash\n"
  491. " ,...\n"
  492. " ]\n"
  493. "\nResult:\n"
  494. "\"hex\" (string) The hex-encoded raw transaction with signature(s)\n"
  495. "\nExamples:\n"
  496. + HelpExampleCli("combinerawtransaction", "[\"myhex1\", \"myhex2\", \"myhex3\"]")
  497. );
  498. UniValue txs = request.params[0].get_array();
  499. std::vector<CMutableTransaction> txVariants(txs.size());
  500. for (unsigned int idx = 0; idx < txs.size(); idx++) {
  501. if (!DecodeHexTx(txVariants[idx], txs[idx].get_str(), true)) {
  502. throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed for tx %d", idx));
  503. }
  504. }
  505. if (txVariants.empty()) {
  506. throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transactions");
  507. }
  508. // mergedTx will end up with all the signatures; it
  509. // starts as a clone of the rawtx:
  510. CMutableTransaction mergedTx(txVariants[0]);
  511. // Fetch previous transactions (inputs):
  512. CCoinsView viewDummy;
  513. CCoinsViewCache view(&viewDummy);
  514. {
  515. LOCK(cs_main);
  516. LOCK(mempool.cs);
  517. CCoinsViewCache &viewChain = *pcoinsTip;
  518. CCoinsViewMemPool viewMempool(&viewChain, mempool);
  519. view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
  520. for (const CTxIn& txin : mergedTx.vin) {
  521. view.AccessCoin(txin.prevout); // Load entries from viewChain into view; can fail.
  522. }
  523. view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
  524. }
  525. // Use CTransaction for the constant parts of the
  526. // transaction to avoid rehashing.
  527. const CTransaction txConst(mergedTx);
  528. // Sign what we can:
  529. for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
  530. CTxIn& txin = mergedTx.vin[i];
  531. const Coin& coin = view.AccessCoin(txin.prevout);
  532. if (coin.IsSpent()) {
  533. throw JSONRPCError(RPC_VERIFY_ERROR, "Input not found or already spent");
  534. }
  535. const CScript& prevPubKey = coin.out.scriptPubKey;
  536. const CAmount& amount = coin.out.nValue;
  537. SignatureData sigdata;
  538. // ... and merge in other signatures:
  539. for (const CMutableTransaction& txv : txVariants) {
  540. if (txv.vin.size() > i) {
  541. sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(txv, i));
  542. }
  543. }
  544. UpdateTransaction(mergedTx, i, sigdata);
  545. }
  546. return EncodeHexTx(mergedTx);
  547. }
  548. UniValue signrawtransaction(const JSONRPCRequest& request)
  549. {
  550. #ifdef ENABLE_WALLET
  551. CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
  552. #endif
  553. if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
  554. throw std::runtime_error(
  555. "signrawtransaction \"hexstring\" ( [{\"txid\":\"id\",\"vout\":n,\"scriptPubKey\":\"hex\",\"redeemScript\":\"hex\"},...] [\"privatekey1\",...] sighashtype )\n"
  556. "\nSign inputs for raw transaction (serialized, hex-encoded).\n"
  557. "The second optional argument (may be null) is an array of previous transaction outputs that\n"
  558. "this transaction depends on but may not yet be in the block chain.\n"
  559. "The third optional argument (may be null) is an array of base58-encoded private\n"
  560. "keys that, if given, will be the only keys used to sign the transaction.\n"
  561. #ifdef ENABLE_WALLET
  562. + HelpRequiringPassphrase(pwallet) + "\n"
  563. #endif
  564. "\nArguments:\n"
  565. "1. \"hexstring\" (string, required) The transaction hex string\n"
  566. "2. \"prevtxs\" (string, optional) An json array of previous dependent transaction outputs\n"
  567. " [ (json array of json objects, or 'null' if none provided)\n"
  568. " {\n"
  569. " \"txid\":\"id\", (string, required) The transaction id\n"
  570. " \"vout\":n, (numeric, required) The output number\n"
  571. " \"scriptPubKey\": \"hex\", (string, required) script key\n"
  572. " \"redeemScript\": \"hex\", (string, required for P2SH or P2WSH) redeem script\n"
  573. " \"amount\": value (numeric, required) The amount spent\n"
  574. " }\n"
  575. " ,...\n"
  576. " ]\n"
  577. "3. \"privkeys\" (string, optional) A json array of base58-encoded private keys for signing\n"
  578. " [ (json array of strings, or 'null' if none provided)\n"
  579. " \"privatekey\" (string) private key in base58-encoding\n"
  580. " ,...\n"
  581. " ]\n"
  582. "4. \"sighashtype\" (string, optional, default=ALL) The signature hash type. Must be one of\n"
  583. " \"ALL\"\n"
  584. " \"NONE\"\n"
  585. " \"SINGLE\"\n"
  586. " \"ALL|ANYONECANPAY\"\n"
  587. " \"NONE|ANYONECANPAY\"\n"
  588. " \"SINGLE|ANYONECANPAY\"\n"
  589. "\nResult:\n"
  590. "{\n"
  591. " \"hex\" : \"value\", (string) The hex-encoded raw transaction with signature(s)\n"
  592. " \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
  593. " \"errors\" : [ (json array of objects) Script verification errors (if there are any)\n"
  594. " {\n"
  595. " \"txid\" : \"hash\", (string) The hash of the referenced, previous transaction\n"
  596. " \"vout\" : n, (numeric) The index of the output to spent and used as input\n"
  597. " \"scriptSig\" : \"hex\", (string) The hex-encoded signature script\n"
  598. " \"sequence\" : n, (numeric) Script sequence number\n"
  599. " \"error\" : \"text\" (string) Verification or signing error related to the input\n"
  600. " }\n"
  601. " ,...\n"
  602. " ]\n"
  603. "}\n"
  604. "\nExamples:\n"
  605. + HelpExampleCli("signrawtransaction", "\"myhex\"")
  606. + HelpExampleRpc("signrawtransaction", "\"myhex\"")
  607. );
  608. #ifdef ENABLE_WALLET
  609. LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : nullptr);
  610. #else
  611. LOCK(cs_main);
  612. #endif
  613. RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VARR, UniValue::VSTR}, true);
  614. CMutableTransaction mtx;
  615. if (!DecodeHexTx(mtx, request.params[0].get_str(), true))
  616. throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
  617. // Fetch previous transactions (inputs):
  618. CCoinsView viewDummy;
  619. CCoinsViewCache view(&viewDummy);
  620. {
  621. LOCK(mempool.cs);
  622. CCoinsViewCache &viewChain = *pcoinsTip;
  623. CCoinsViewMemPool viewMempool(&viewChain, mempool);
  624. view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
  625. for (const CTxIn& txin : mtx.vin) {
  626. view.AccessCoin(txin.prevout); // Load entries from viewChain into view; can fail.
  627. }
  628. view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
  629. }
  630. bool fGivenKeys = false;
  631. CBasicKeyStore tempKeystore;
  632. if (request.params.size() > 2 && !request.params[2].isNull()) {
  633. fGivenKeys = true;
  634. UniValue keys = request.params[2].get_array();
  635. for (unsigned int idx = 0; idx < keys.size(); idx++) {
  636. UniValue k = keys[idx];
  637. CStarwelsSecret vchSecret;
  638. bool fGood = vchSecret.SetString(k.get_str());
  639. if (!fGood)
  640. throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
  641. CKey key = vchSecret.GetKey();
  642. if (!key.IsValid())
  643. throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
  644. tempKeystore.AddKey(key);
  645. }
  646. }
  647. #ifdef ENABLE_WALLET
  648. else if (pwallet) {
  649. EnsureWalletIsUnlocked(pwallet);
  650. }
  651. #endif
  652. // Add previous txouts given in the RPC call:
  653. if (request.params.size() > 1 && !request.params[1].isNull()) {
  654. UniValue prevTxs = request.params[1].get_array();
  655. for (unsigned int idx = 0; idx < prevTxs.size(); idx++) {
  656. const UniValue& p = prevTxs[idx];
  657. if (!p.isObject())
  658. throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
  659. UniValue prevOut = p.get_obj();
  660. RPCTypeCheckObj(prevOut,
  661. {
  662. {"txid", UniValueType(UniValue::VSTR)},
  663. {"vout", UniValueType(UniValue::VNUM)},
  664. {"scriptPubKey", UniValueType(UniValue::VSTR)},
  665. });
  666. uint256 txid = ParseHashO(prevOut, "txid");
  667. int nOut = find_value(prevOut, "vout").get_int();
  668. if (nOut < 0)
  669. throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
  670. COutPoint out(txid, nOut);
  671. std::vector<unsigned char> pkData(ParseHexO(prevOut, "scriptPubKey"));
  672. CScript scriptPubKey(pkData.begin(), pkData.end());
  673. {
  674. const Coin& coin = view.AccessCoin(out);
  675. if (!coin.IsSpent() && coin.out.scriptPubKey != scriptPubKey) {
  676. std::string err("Previous output scriptPubKey mismatch:\n");
  677. err = err + ScriptToAsmStr(coin.out.scriptPubKey) + "\nvs:\n"+
  678. ScriptToAsmStr(scriptPubKey);
  679. throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
  680. }
  681. Coin newcoin;
  682. newcoin.out.scriptPubKey = scriptPubKey;
  683. newcoin.out.nValue = 0;
  684. if (prevOut.exists("amount")) {
  685. newcoin.out.nValue = AmountFromValue(find_value(prevOut, "amount"));
  686. }
  687. newcoin.nHeight = 1;
  688. view.AddCoin(out, std::move(newcoin), true);
  689. }
  690. // if redeemScript given and not using the local wallet (private keys
  691. // given), add redeemScript to the tempKeystore so it can be signed:
  692. if (fGivenKeys && (scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash())) {
  693. RPCTypeCheckObj(prevOut,
  694. {
  695. {"txid", UniValueType(UniValue::VSTR)},
  696. {"vout", UniValueType(UniValue::VNUM)},
  697. {"scriptPubKey", UniValueType(UniValue::VSTR)},
  698. {"redeemScript", UniValueType(UniValue::VSTR)},
  699. });
  700. UniValue v = find_value(prevOut, "redeemScript");
  701. if (!v.isNull()) {
  702. std::vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
  703. CScript redeemScript(rsData.begin(), rsData.end());
  704. tempKeystore.AddCScript(redeemScript);
  705. }
  706. }
  707. }
  708. }
  709. #ifdef ENABLE_WALLET
  710. const CKeyStore& keystore = ((fGivenKeys || !pwallet) ? tempKeystore : *pwallet);
  711. #else
  712. const CKeyStore& keystore = tempKeystore;
  713. #endif
  714. int nHashType = SIGHASH_ALL;
  715. if (request.params.size() > 3 && !request.params[3].isNull()) {
  716. static std::map<std::string, int> mapSigHashValues = {
  717. {std::string("ALL"), int(SIGHASH_ALL)},
  718. {std::string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY)},
  719. {std::string("NONE"), int(SIGHASH_NONE)},
  720. {std::string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY)},
  721. {std::string("SINGLE"), int(SIGHASH_SINGLE)},
  722. {std::string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)},
  723. };
  724. std::string strHashType = request.params[3].get_str();
  725. if (mapSigHashValues.count(strHashType))
  726. nHashType = mapSigHashValues[strHashType];
  727. else
  728. throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param");
  729. }
  730. bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
  731. // Script verification errors
  732. UniValue vErrors(UniValue::VARR);
  733. // Use CTransaction for the constant parts of the
  734. // transaction to avoid rehashing.
  735. const CTransaction txConst(mtx);
  736. // Sign what we can:
  737. for (unsigned int i = 0; i < mtx.vin.size(); i++) {
  738. CTxIn& txin = mtx.vin[i];
  739. const Coin& coin = view.AccessCoin(txin.prevout);
  740. if (coin.IsSpent()) {
  741. TxInErrorToJSON(txin, vErrors, "Input not found or already spent");
  742. continue;
  743. }
  744. const CScript& prevPubKey = coin.out.scriptPubKey;
  745. const CAmount& amount = coin.out.nValue;
  746. SignatureData sigdata;
  747. // Only sign SIGHASH_SINGLE if there's a corresponding output:
  748. if (!fHashSingle || (i < mtx.vout.size()))
  749. ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mtx, i, amount, nHashType), prevPubKey, sigdata);
  750. sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(mtx, i));
  751. UpdateTransaction(mtx, i, sigdata);
  752. ScriptError serror = SCRIPT_ERR_OK;
  753. if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
  754. TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
  755. }
  756. }
  757. bool fComplete = vErrors.empty();
  758. UniValue result(UniValue::VOBJ);
  759. result.push_back(Pair("hex", EncodeHexTx(mtx)));
  760. result.push_back(Pair("complete", fComplete));
  761. if (!vErrors.empty()) {
  762. result.push_back(Pair("errors", vErrors));
  763. }
  764. return result;
  765. }
  766. UniValue sendrawtransaction(const JSONRPCRequest& request)
  767. {
  768. if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
  769. throw std::runtime_error(
  770. "sendrawtransaction \"hexstring\" ( allowhighfees )\n"
  771. "\nSubmits raw transaction (serialized, hex-encoded) to local node and network.\n"
  772. "\nAlso see createrawtransaction and signrawtransaction calls.\n"
  773. "\nArguments:\n"
  774. "1. \"hexstring\" (string, required) The hex string of the raw transaction)\n"
  775. "2. allowhighfees (boolean, optional, default=false) Allow high fees\n"
  776. "\nResult:\n"
  777. "\"hex\" (string) The transaction hash in hex\n"
  778. "\nExamples:\n"
  779. "\nCreate a transaction\n"
  780. + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") +
  781. "Sign the transaction, and get back the hex\n"
  782. + HelpExampleCli("signrawtransaction", "\"myhex\"") +
  783. "\nSend the transaction (signed hex)\n"
  784. + HelpExampleCli("sendrawtransaction", "\"signedhex\"") +
  785. "\nAs a json rpc call\n"
  786. + HelpExampleRpc("sendrawtransaction", "\"signedhex\"")
  787. );
  788. LOCK(cs_main);
  789. RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL});
  790. // parse hex string from parameter
  791. CMutableTransaction mtx;
  792. if (!DecodeHexTx(mtx, request.params[0].get_str()))
  793. throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
  794. CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
  795. const uint256& hashTx = tx->GetHash();
  796. CAmount nMaxRawTxFee = maxTxFee;
  797. if (request.params.size() > 1 && request.params[1].get_bool())
  798. nMaxRawTxFee = 0;
  799. CCoinsViewCache &view = *pcoinsTip;
  800. bool fHaveChain = false;
  801. for (size_t o = 0; !fHaveChain && o < tx->vout.size(); o++) {
  802. const Coin& existingCoin = view.AccessCoin(COutPoint(hashTx, o));
  803. fHaveChain = !existingCoin.IsSpent();
  804. }
  805. bool fHaveMempool = mempool.exists(hashTx);
  806. if (!fHaveMempool && !fHaveChain) {
  807. // push to local node and sync with wallets
  808. CValidationState state;
  809. bool fMissingInputs;
  810. bool fLimitFree = true;
  811. if (!AcceptToMemoryPool(mempool, state, std::move(tx), fLimitFree, &fMissingInputs, nullptr, false, nMaxRawTxFee)) {
  812. if (state.IsInvalid()) {
  813. throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
  814. } else {
  815. if (fMissingInputs) {
  816. throw JSONRPCError(RPC_TRANSACTION_ERROR, "Missing inputs");
  817. }
  818. throw JSONRPCError(RPC_TRANSACTION_ERROR, state.GetRejectReason());
  819. }
  820. }
  821. } else if (fHaveChain) {
  822. throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
  823. }
  824. if(!g_connman)
  825. throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
  826. CInv inv(MSG_TX, hashTx);
  827. g_connman->ForEachNode([&inv](CNode* pnode)
  828. {
  829. pnode->PushInventory(inv);
  830. });
  831. return hashTx.GetHex();
  832. }
  833. static const CRPCCommand commands[] =
  834. { // category name actor (function) okSafeMode
  835. // --------------------- ------------------------ ----------------------- ----------
  836. { "rawtransactions", "getrawtransaction", &getrawtransaction, true, {"txid","verbose"} },
  837. { "rawtransactions", "createrawtransaction", &createrawtransaction, true, {"inputs","outputs","locktime","replaceable"} },
  838. { "rawtransactions", "decoderawtransaction", &decoderawtransaction, true, {"hexstring"} },
  839. { "rawtransactions", "decodescript", &decodescript, true, {"hexstring"} },
  840. { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false, {"hexstring","allowhighfees"} },
  841. { "rawtransactions", "combinerawtransaction", &combinerawtransaction, true, {"txs"} },
  842. { "rawtransactions", "signrawtransaction", &signrawtransaction, false, {"hexstring","prevtxs","privkeys","sighashtype"} }, /* uses wallet if enabled */
  843. { "blockchain", "gettxoutproof", &gettxoutproof, true, {"txids", "blockhash"} },
  844. { "blockchain", "verifytxoutproof", &verifytxoutproof, true, {"proof"} },
  845. };
  846. void RegisterRawTransactionRPCCommands(CRPCTable &t)
  847. {
  848. for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
  849. t.appendCommand(commands[vcidx].name, &commands[vcidx]);
  850. }