Line data Source code
1 : // Copyright (c) 2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2014 The Bitcoin developers
3 : // Copyright (c) 2014-2015 The Dash developers
4 : // Copyright (c) 2015-2022 The PIVX Core developers
5 : // Distributed under the MIT software license, see the accompanying
6 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 :
8 : #include "core_io.h"
9 : #include "evo/providertx.h"
10 : #include "key_io.h"
11 : #include "keystore.h"
12 : #include "llmq/quorums_chainlocks.h"
13 : #include "net.h"
14 : #include "policy/policy.h"
15 : #include "primitives/transaction.h"
16 : #include "rpc/server.h"
17 : #include "script/script.h"
18 : #include "script/script_error.h"
19 : #include "script/sign.h"
20 : #include "script/standard.h"
21 : #include "uint256.h"
22 : #include "utilmoneystr.h"
23 : #include "validationinterface.h"
24 : #ifdef ENABLE_WALLET
25 : #include "sapling/address.h"
26 : #include "sapling/key_io_sapling.h"
27 : #include "wallet/rpcwallet.h"
28 : #include "wallet/wallet.h"
29 : #endif
30 :
31 : #include <future>
32 : #include <stdint.h>
33 :
34 : #include <univalue.h>
35 :
36 : template <typename Payload>
37 77 : static void PayloadToJSON(const CTransaction& tx, Payload& pl, UniValue& entry)
38 : {
39 77 : if (GetTxPayload(tx, pl)) {
40 0 : UniValue payloadObj;
41 77 : pl.ToJson(payloadObj);
42 154 : entry.pushKV("payload", payloadObj);
43 : }
44 77 : }
45 :
46 77 : static void PayloadToJSON(const CTransaction& tx, UniValue& entry)
47 : {
48 77 : switch(tx.nType) {
49 77 : case CTransaction::TxType::PROREG: {
50 77 : ProRegPL pl;
51 77 : PayloadToJSON(tx, pl, entry);
52 77 : break;
53 : }
54 0 : case CTransaction::TxType::PROUPSERV: {
55 0 : ProUpServPL pl;
56 0 : PayloadToJSON(tx, pl, entry);
57 0 : break;
58 : }
59 0 : case CTransaction::TxType::PROUPREG: {
60 0 : ProUpRegPL pl;
61 0 : PayloadToJSON(tx, pl, entry);
62 0 : break;
63 : }
64 0 : case CTransaction::TxType::PROUPREV: {
65 0 : ProUpRevPL pl;
66 0 : PayloadToJSON(tx, pl, entry);
67 0 : break;
68 : }
69 : }
70 77 : }
71 :
72 : extern int ComputeNextBlockAndDepth(const CBlockIndex* tip, const CBlockIndex* blockindex, const CBlockIndex*& next);
73 :
74 866 : static int ComputeConfirmations(const CBlockIndex* tip, const CBlockIndex* blockindex)
75 : {
76 866 : const CBlockIndex* next{nullptr};
77 866 : return ComputeNextBlockAndDepth(tip, blockindex, next);
78 : }
79 :
80 : // pwallet can be nullptr. If not null, the json could include information available only to the wallet.
81 1062 : void TxToJSON(CWallet* const pwallet, const CTransaction& tx, const CBlockIndex* tip, const CBlockIndex* blockindex, UniValue& entry)
82 : {
83 : // Call into TxToUniv() in bitcoin-common to decode the transaction hex.
84 : //
85 : // Blockchain contextual information (confirmations and blocktime) is not
86 : // available to code in bitcoin-common, so we query them here and push the
87 : // data into the returned UniValue.
88 2124 : TxToUniv(tx, uint256(), entry);
89 :
90 : // Sapling
91 1062 : if (pwallet && tx.IsShieldedTx()) {
92 : // Add information that only this wallet knows about the transaction if is possible
93 19 : if (pwallet->HasSaplingSPKM()) {
94 19 : std::vector<libzcash::SaplingPaymentAddress> addresses =
95 38 : pwallet->GetSaplingScriptPubKeyMan()->FindMySaplingAddresses(tx);
96 38 : UniValue addrs(UniValue::VARR);
97 28 : for (const auto& addr : addresses) {
98 18 : addrs.push_back(KeyIO::EncodePaymentAddress(addr));
99 : }
100 38 : entry.pushKV("shielded_addresses", addrs);
101 : }
102 : }
103 :
104 : // Special txes
105 1062 : if (tx.IsSpecialTx()) {
106 77 : PayloadToJSON(tx, entry);
107 : }
108 :
109 1062 : bool chainLock = false;
110 1062 : if (blockindex && tip) {
111 1732 : entry.pushKV("blockhash", blockindex->GetBlockHash().ToString());
112 866 : int confirmations = ComputeConfirmations(tip, blockindex);
113 866 : if (confirmations != -1) {
114 865 : entry.pushKV("confirmations", confirmations);
115 865 : entry.pushKV("time", blockindex->GetBlockTime());
116 865 : entry.pushKV("blocktime", blockindex->GetBlockTime());
117 865 : chainLock = llmq::chainLocksHandler->HasChainLock(blockindex->nHeight, blockindex->GetBlockHash());
118 : } else {
119 2 : entry.pushKV("confirmations", 0);
120 : }
121 : }
122 1062 : entry.pushKV("chainlock", chainLock);
123 1062 : }
124 :
125 3 : std::string GetSaplingTxHelpInfo()
126 : {
127 3 : return " \"valueBalance\": n, (numeric) The net value of spend transfers minus output transfers\n"
128 : " \"valueBalanceSat\": n, (numeric) `valueBalance` in sats\n"
129 : " \"vShieldSpend\": [ (array of json objects)\n"
130 : " {\n"
131 : " \"cv\": \"hex\", (string) A value commitment to the value of the input note\n"
132 : " \"anchor\": hex, (string) A Merkle root of the Sapling note commitment tree at some block height in the past\n"
133 : " \"nullifier\": hex, (string) The nullifier of the input note\n"
134 : " \"rk\": hex, (string) The randomized public key for spendAuthSig\n"
135 : " \"proof\": hex, (string) A zero-knowledge proof using the spend circuit\n"
136 : " \"spendAuthSig\": hex, (string) A signature authorizing this spend\n"
137 : " }\n"
138 : " ,...\n"
139 : " ],\n"
140 : " \"vShieldOutput\": [ (array of json objects)\n"
141 : " {\n"
142 : " \"cv\": hex, (string) A value commitment to the value of the output note\n"
143 : " \"cmu\": hex, (string) The u-coordinate of the note commitment for the output note\n"
144 : " \"ephemeralKey\": hex, (string) A Jubjub public key\n"
145 : " \"encCiphertext\": hex, (string) A ciphertext component for the encrypted output note\n"
146 : " \"outCiphertext\": hex, (string) A ciphertext component for the encrypted output note\n"
147 : " \"proof\": hex, (string) A zero-knowledge proof using the output circuit\n"
148 : " }\n"
149 : " ,...\n"
150 : " ],\n"
151 3 : " \"bindingSig\": hex, (string) Prove consistency of valueBalance with the value commitments in spend descriptions and output descriptions, and proves knowledge of the randomness used for the spend and output value commitments\n";
152 : }
153 :
154 975 : UniValue getrawtransaction(const JSONRPCRequest& request)
155 : {
156 975 : if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
157 1 : throw std::runtime_error(
158 : "getrawtransaction \"txid\" ( verbose \"blockhash\" )\n"
159 :
160 : "\nNOTE: By default this function only works for mempool transactions. If the -txindex option is\n"
161 : "enabled, it also works for blockchain transactions. If the block which contains the transaction\n"
162 : "is known, its hash can be provided even for nodes without -txindex. Note that if a blockhash is\n"
163 : "provided, only that block will be searched and if the transaction is in the mempool or other\n"
164 : "blocks, or if this node does not have the given block available, the transaction will not be found.\n"
165 : "DEPRECATED: for now, it also works for transactions with unspent outputs.\n"
166 :
167 : "\nReturn the raw transaction data.\n"
168 : "\nIf verbose is 'true', returns an Object with information about 'txid'.\n"
169 : "If verbose is 'false' or omitted, returns a string that is serialized, hex-encoded data for 'txid'.\n"
170 :
171 : "\nArguments:\n"
172 : "1. \"txid\" (string, required) The transaction id\n"
173 : "2. verbose (bool, optional, default=false) If false, return a string, otherwise return a json object\n"
174 : "3. \"blockhash\" (string, optional) The block in which to look for the transaction\n"
175 :
176 : "\nResult (if verbose is not set or set to false):\n"
177 : "\"data\" (string) The serialized, hex-encoded data for 'txid'\n"
178 :
179 : "\nResult (if verbose is set to true):\n"
180 : "{\n"
181 : " \"in_active_chain\": b, (bool) Whether specified block is in the active chain or not (only present with explicit \"blockhash\" argument)\n"
182 : " \"hex\" : \"data\", (string) The serialized, hex-encoded data for 'txid'\n"
183 : " \"txid\" : \"id\", (string) The transaction id (same as provided)\n"
184 : " \"size\" : n, (numeric) The serialized transaction size\n"
185 : " \"version\" : n, (numeric) The version\n"
186 : " \"type\" : n, (numeric) The type\n"
187 : " \"locktime\" : ttt, (numeric) The lock time\n"
188 : " \"vin\" : [ (array of json objects)\n"
189 : " {\n"
190 : " \"txid\": \"id\", (string) The transaction id\n"
191 : " \"vout\": n, (numeric) \n"
192 : " \"scriptSig\": { (json object) The script\n"
193 : " \"asm\": \"asm\", (string) asm\n"
194 : " \"hex\": \"hex\" (string) hex\n"
195 : " },\n"
196 : " \"sequence\": n (numeric) The script sequence number\n"
197 : " }\n"
198 : " ,...\n"
199 : " ],\n"
200 : " \"vout\" : [ (array of json objects)\n"
201 : " {\n"
202 : " \"value\" : x.xxx, (numeric) The value in PIV\n"
203 : " \"n\" : n, (numeric) index\n"
204 : " \"scriptPubKey\" : { (json object)\n"
205 : " \"asm\" : \"asm\", (string) the asm\n"
206 : " \"hex\" : \"hex\", (string) the hex\n"
207 : " \"reqSigs\" : n, (numeric) The required sigs\n"
208 : " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
209 : " \"addresses\" : [ (json array of string)\n"
210 : " \"pivxaddress\" (string) pivx address\n"
211 : " ,...\n"
212 : " ]\n"
213 : " }\n"
214 : " }\n"
215 : " ,...\n"
216 : " ],\n"
217 2 : + GetSaplingTxHelpInfo() +
218 : " \"shielded_addresses\" (json array of string) the shielded addresses involved in this transaction if possible (only for shielded transactions and the tx owner/viewer)\n"
219 : " \"extraPayloadSize\" : n (numeric) Size of extra payload. Only present if it's a special TX\n"
220 : " \"extraPayload\" : \"hex\" (string) Hex encoded extra payload data. Only present if it's a special TX\n"
221 : " \"blockhash\" : \"hash\", (string) the block hash\n"
222 : " \"confirmations\" : n, (numeric) The confirmations\n"
223 : " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT)\n"
224 : " \"blocktime\" : ttt (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
225 : "}\n"
226 :
227 : "\nExamples:\n"
228 5 : + HelpExampleCli("getrawtransaction", "\"mytxid\"")
229 5 : + HelpExampleCli("getrawtransaction", "\"mytxid\" true")
230 5 : + HelpExampleRpc("getrawtransaction", "\"mytxid\", true")
231 6 : + HelpExampleCli("getrawtransaction", "\"mytxid\" false \"myblockhash\"")
232 5 : + HelpExampleCli("getrawtransaction", "\"mytxid\" true \"myblockhash\"")
233 3 : );
234 :
235 1940 : LOCK(cs_main);
236 :
237 974 : bool in_active_chain = true;
238 975 : uint256 hash = ParseHashV(request.params[0], "parameter 1");
239 973 : CBlockIndex* blockindex = nullptr;
240 :
241 973 : bool fVerbose = false;
242 973 : if (!request.params[1].isNull()) {
243 969 : fVerbose = request.params[1].isNum() ? (request.params[1].get_int() != 0) : request.params[1].get_bool();
244 : }
245 :
246 973 : if (!request.params[2].isNull()) {
247 12 : uint256 blockhash = ParseHashV(request.params[2], "parameter 3");
248 4 : blockindex = LookupBlockIndex(blockhash);
249 4 : if (!blockindex) {
250 2 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block hash not found");
251 : }
252 6 : in_active_chain = chainActive.Contains(blockindex);
253 : }
254 :
255 968 : CTransactionRef tx;
256 968 : uint256 hash_block;
257 968 : if (!GetTransaction(hash, tx, hash_block, true, blockindex)) {
258 4 : std::string errmsg;
259 2 : if (blockindex) {
260 1 : if (!(blockindex->nStatus & BLOCK_HAVE_DATA)) {
261 0 : throw JSONRPCError(RPC_MISC_ERROR, "Block not available");
262 : }
263 1 : errmsg = "No such transaction found in the provided block";
264 : } else {
265 1 : errmsg = fTxIndex
266 : ? "No such mempool or blockchain transaction"
267 1 : : "No such mempool transaction. Use -txindex to enable blockchain transaction queries";
268 : }
269 4 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, errmsg + ". Use gettransaction for wallet transactions.");
270 : }
271 :
272 966 : if (!fVerbose) {
273 14 : return EncodeHexTx(*tx);
274 : }
275 :
276 1920 : UniValue result(UniValue::VOBJ);
277 962 : if (blockindex) result.pushKV("in_active_chain", in_active_chain);
278 958 : else blockindex = LookupBlockIndex(hash_block);
279 960 : CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
280 1920 : TxToJSON(pwallet, *tx, chainActive.Tip(), blockindex, result);
281 960 : return result;
282 : }
283 :
284 2641 : UniValue createrawtransaction(const JSONRPCRequest& request)
285 : {
286 2641 : if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
287 4 : throw std::runtime_error(
288 : "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,...} ( locktime )\n"
289 : "\nCreate a transaction spending the given inputs and sending to the given addresses.\n"
290 : "Returns hex-encoded raw transaction.\n"
291 : "Note that the transaction's inputs are not signed, and\n"
292 : "it is not stored in the wallet or transmitted to the network.\n"
293 :
294 : "\nArguments:\n"
295 : "1. \"inputs\" (string, required) A json array of json objects\n"
296 : " [\n"
297 : " {\n"
298 : " \"txid\":\"id\", (string, required) The transaction id\n"
299 : " \"vout\":n, (numeric, required) The output number\n"
300 : " \"sequence\":n (numeric, optional) The sequence number\n"
301 : " }\n"
302 : " ,...\n"
303 : " ]\n"
304 : "2. \"outputs\" (string, required) a json object with addresses as keys and amounts as values\n"
305 : " {\n"
306 : " \"address\": x.xxx (numeric, required) The key is the pivx address, the value is the pivx amount\n"
307 : " ,...\n"
308 : " }\n"
309 : "3. locktime (numeric, optional, default=0) Raw locktime. Non-0 value also locktime-activates inputs\n"
310 :
311 : "\nResult:\n"
312 : "\"transaction\" (string) hex string of the transaction\n"
313 :
314 8 : "\nExamples\n" +
315 36 : HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"{\\\"address\\\":0.01}\"") + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"address\\\":0.01}\""));
316 :
317 2637 : LOCK(cs_main);
318 2658 : RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VOBJ, UniValue::VNUM});
319 2631 : if (request.params[0].isNull() || request.params[1].isNull())
320 0 : throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, arguments 1 and 2 must be non-null");
321 :
322 5262 : UniValue inputs = request.params[0].get_array();
323 5262 : UniValue sendTo = request.params[1].get_obj();
324 :
325 2631 : CMutableTransaction rawTx;
326 :
327 2631 : if (request.params.size() > 2 && !request.params[2].isNull()) {
328 3 : int64_t nLockTime = request.params[2].get_int64();
329 3 : if (nLockTime < 0 || nLockTime > std::numeric_limits<uint32_t>::max())
330 4 : throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, locktime out of range");
331 1 : rawTx.nLockTime = nLockTime;
332 : }
333 :
334 5314 : for (unsigned int idx = 0; idx < inputs.size(); idx++) {
335 2695 : const UniValue& input = inputs[idx];
336 2695 : const UniValue& o = input.get_obj();
337 :
338 2697 : uint256 txid = ParseHashO(o, "txid");
339 :
340 2691 : const UniValue& vout_v = find_value(o, "vout");
341 2691 : if (!vout_v.isNum())
342 4 : throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
343 2689 : int nOutput = vout_v.get_int();
344 2689 : if (nOutput < 0)
345 2 : throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
346 :
347 2688 : uint32_t nSequence = (rawTx.nLockTime ? CTxIn::SEQUENCE_FINAL - 1 : CTxIn::SEQUENCE_FINAL);
348 :
349 : // set the sequence number if passed in the parameters object
350 2688 : const UniValue& sequenceObj = find_value(o, "sequence");
351 2688 : if (sequenceObj.isNum()) {
352 6 : int64_t seqNr64 = sequenceObj.get_int64();
353 6 : if (seqNr64 < 0 || seqNr64 > CTxIn::SEQUENCE_FINAL)
354 6 : throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, sequence number is out of range");
355 : else
356 3 : nSequence = (uint32_t)seqNr64;
357 : }
358 :
359 5385 : CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence);
360 :
361 2685 : rawTx.vin.push_back(in);
362 : }
363 :
364 5238 : std::set<CTxDestination> setAddress;
365 5235 : std::vector<std::string> addrList = sendTo.getKeys();
366 8931 : for (const std::string& name_ : addrList) {
367 12630 : CTxDestination address = DecodeDestination(name_);
368 6315 : if (!IsValidDestination(address))
369 2 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid PIVX address: ")+name_);
370 :
371 6314 : if (setAddress.count(address))
372 2 : throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ")+name_);
373 6313 : setAddress.insert(address);
374 :
375 12626 : CScript scriptPubKey = GetScriptForDestination(address);
376 6313 : CAmount nAmount = AmountFromValue(sendTo[name_]);
377 :
378 12625 : CTxOut out(nAmount, scriptPubKey);
379 6312 : rawTx.vout.push_back(out);
380 : }
381 :
382 7851 : return EncodeHexTx(rawTx);
383 : }
384 :
385 96 : UniValue decoderawtransaction(const JSONRPCRequest& request)
386 : {
387 96 : if (request.fHelp || request.params.size() != 1)
388 2 : throw std::runtime_error(
389 : "decoderawtransaction \"hexstring\"\n"
390 : "\nReturn a JSON object representing the serialized, hex-encoded transaction.\n"
391 :
392 : "\nArguments:\n"
393 : "1. \"hexstring\" (string, required) The transaction hex string\n"
394 :
395 : "\nResult:\n"
396 : "{\n"
397 : " \"txid\" : \"id\", (string) The transaction id\n"
398 : " \"size\" : n, (numeric) The transaction size\n"
399 : " \"version\" : n, (numeric) The version\n"
400 : " \"type\" : n, (numeric) The type\n"
401 : " \"locktime\" : ttt, (numeric) The lock time\n"
402 : " \"vin\" : [ (array of json objects)\n"
403 : " {\n"
404 : " \"txid\": \"id\", (string) The transaction id\n"
405 : " \"vout\": n, (numeric) The output number\n"
406 : " \"scriptSig\": { (json object) The script\n"
407 : " \"asm\": \"asm\", (string) asm\n"
408 : " \"hex\": \"hex\" (string) hex\n"
409 : " },\n"
410 : " \"sequence\": n (numeric) The script sequence number\n"
411 : " }\n"
412 : " ,...\n"
413 : " ],\n"
414 : " \"vout\" : [ (array of json objects)\n"
415 : " {\n"
416 : " \"value\" : x.xxx, (numeric) The value in PIV\n"
417 : " \"n\" : n, (numeric) index\n"
418 : " \"scriptPubKey\" : { (json object)\n"
419 : " \"asm\" : \"asm\", (string) the asm\n"
420 : " \"hex\" : \"hex\", (string) the hex\n"
421 : " \"reqSigs\" : n, (numeric) The required sigs\n"
422 : " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
423 : " \"addresses\" : [ (json array of string)\n"
424 : " \"12tvKAXCxZjSmdNbao16dKXC8tRWfcF5oc\" (string) pivx address\n"
425 : " ,...\n"
426 : " ]\n"
427 : " }\n"
428 : " }\n"
429 : " ,...\n"
430 : " ],\n"
431 4 : + GetSaplingTxHelpInfo() +
432 : " \"extraPayloadSize\" : n (numeric) Size of extra payload. Only present if it's a special TX\n"
433 : " \"extraPayload\" : \"hex\" (string) Hex encoded extra payload data. Only present if it's a special TX\n"
434 : "}\n"
435 :
436 4 : "\nExamples:\n" +
437 14 : HelpExampleCli("decoderawtransaction", "\"hexstring\"") + HelpExampleRpc("decoderawtransaction", "\"hexstring\""));
438 :
439 94 : LOCK(cs_main);
440 96 : RPCTypeCheck(request.params, {UniValue::VSTR});
441 :
442 188 : CMutableTransaction mtx;
443 :
444 94 : if (!DecodeHexTx(mtx, request.params[0].get_str()))
445 4 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
446 :
447 92 : UniValue result(UniValue::VOBJ);
448 92 : CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
449 92 : TxToJSON(pwallet, CTransaction(std::move(mtx)), nullptr, nullptr, result);
450 :
451 184 : return result;
452 : }
453 :
454 10 : UniValue decodescript(const JSONRPCRequest& request)
455 : {
456 10 : if (request.fHelp || request.params.size() != 1)
457 0 : throw std::runtime_error(
458 : "decodescript \"hexstring\"\n"
459 : "\nDecode a hex-encoded script.\n"
460 :
461 : "\nArguments:\n"
462 : "1. \"hexstring\" (string) the hex encoded script\n"
463 :
464 : "\nResult:\n"
465 : "{\n"
466 : " \"asm\":\"asm\", (string) Script public key\n"
467 : " \"hex\":\"hex\", (string) hex encoded public key\n"
468 : " \"type\":\"type\", (string) The output type\n"
469 : " \"reqSigs\": n, (numeric) The required signatures\n"
470 : " \"addresses\": [ (json array of string)\n"
471 : " \"address\" (string) pivx address\n"
472 : " ,...\n"
473 : " ],\n"
474 : " \"p2sh\",\"address\" (string) script address\n"
475 : "}\n"
476 :
477 0 : "\nExamples:\n" +
478 0 : HelpExampleCli("decodescript", "\"hexstring\"") + HelpExampleRpc("decodescript", "\"hexstring\""));
479 :
480 10 : LOCK(cs_main);
481 10 : RPCTypeCheck(request.params, {UniValue::VSTR});
482 :
483 10 : UniValue r(UniValue::VOBJ);
484 20 : CScript script;
485 10 : if (request.params[0].get_str().size() > 0) {
486 20 : std::vector<unsigned char> scriptData(ParseHexV(request.params[0], "argument"));
487 10 : script = CScript(scriptData.begin(), scriptData.end());
488 : } else {
489 : // Empty scripts are valid
490 : }
491 10 : ScriptPubKeyToUniv(script, r, false);
492 :
493 30 : r.pushKV("p2sh", EncodeDestination(CScriptID(script)));
494 20 : return r;
495 : }
496 :
497 : /** Pushes a JSON object for script verification or signing errors to vErrorsRet. */
498 13 : static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::string& strMessage)
499 : {
500 26 : UniValue entry(UniValue::VOBJ);
501 26 : entry.pushKV("txid", txin.prevout.hash.ToString());
502 13 : entry.pushKV("vout", (uint64_t)txin.prevout.n);
503 39 : entry.pushKV("scriptSig", HexStr(txin.scriptSig));
504 13 : entry.pushKV("sequence", (uint64_t)txin.nSequence);
505 13 : entry.pushKV("error", strMessage);
506 13 : vErrorsRet.push_back(entry);
507 13 : }
508 :
509 102778 : UniValue signrawtransaction(const JSONRPCRequest& request)
510 : {
511 102778 : CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
512 :
513 102778 : if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
514 1 : throw std::runtime_error(
515 : "signrawtransaction \"hexstring\" ( [{\"txid\":\"id\",\"vout\":n,\"scriptPubKey\":\"hex\",\"redeemScript\":\"hex\"},...] [\"privatekey1\",...] sighashtype )\n"
516 : "\nSign inputs for raw transaction (serialized, hex-encoded).\n"
517 : "The second optional argument (may be null) is an array of previous transaction outputs that\n"
518 : "this transaction depends on but may not yet be in the block chain.\n"
519 : "The third optional argument (may be null) is an array of base58-encoded private\n"
520 : "keys that, if given, will be the only keys used to sign the transaction.\n"
521 : #ifdef ENABLE_WALLET
522 2 : + HelpRequiringPassphrase(pwallet) + "\n"
523 : #endif
524 :
525 : "\nArguments:\n"
526 : "1. \"hexstring\" (string, required) The transaction hex string\n"
527 : "2. \"prevtxs\" (string, optional) An json array of previous dependent transaction outputs\n"
528 : " [ (json array of json objects, or 'null' if none provided)\n"
529 : " {\n"
530 : " \"txid\":\"id\", (string, required) The transaction id\n"
531 : " \"vout\":n, (numeric, required) The output number\n"
532 : " \"scriptPubKey\": \"hex\", (string, required) script key\n"
533 : " \"redeemScript\": \"hex\" (string, required for P2SH) redeem script\n"
534 : " \"amount\": value (numeric, required) The amount spent\n"
535 : " }\n"
536 : " ,...\n"
537 : " ]\n"
538 : "3. \"privkeys\" (string, optional) A json array of base58-encoded private keys for signing\n"
539 : " [ (json array of strings, or 'null' if none provided)\n"
540 : " \"privatekey\" (string) private key in base58-encoding\n"
541 : " ,...\n"
542 : " ]\n"
543 : "4. \"sighashtype\" (string, optional, default=ALL) The signature hash type. Must be one of\n"
544 : " \"ALL\"\n"
545 : " \"NONE\"\n"
546 : " \"SINGLE\"\n"
547 : " \"ALL|ANYONECANPAY\"\n"
548 : " \"NONE|ANYONECANPAY\"\n"
549 : " \"SINGLE|ANYONECANPAY\"\n"
550 :
551 : "\nResult:\n"
552 : "{\n"
553 : " \"hex\" : \"value\", (string) The hex-encoded raw transaction with signature(s)\n"
554 : " \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
555 : " \"errors\" : [ (json array of objects) Script verification errors (if there are any)\n"
556 : " {\n"
557 : " \"txid\" : \"hash\", (string) The hash of the referenced, previous transaction\n"
558 : " \"vout\" : n, (numeric) The index of the output to spent and used as input\n"
559 : " \"scriptSig\" : \"hex\", (string) The hex-encoded signature script\n"
560 : " \"sequence\" : n, (numeric) Script sequence number\n"
561 : " \"error\" : \"text\" (string) Verification or signing error related to the input\n"
562 : " }\n"
563 : " ,...\n"
564 : " ]\n"
565 : "}\n"
566 :
567 2 : "\nExamples:\n" +
568 7 : HelpExampleCli("signrawtransaction", "\"myhex\"") + HelpExampleRpc("signrawtransaction", "\"myhex\""));
569 :
570 : #ifdef ENABLE_WALLET
571 205554 : LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : nullptr);
572 : #else
573 : LOCK(cs_main);
574 : #endif
575 102783 : RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VARR, UniValue::VSTR}, true);
576 :
577 205554 : std::vector<unsigned char> txData(ParseHexV(request.params[0], "argument 1"));
578 205552 : CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
579 205552 : std::vector<CMutableTransaction> txVariants;
580 205551 : while (!ssData.empty()) {
581 102776 : try {
582 205552 : CMutableTransaction tx;
583 102776 : ssData >> tx;
584 102775 : txVariants.push_back(tx);
585 2 : } catch (const std::exception&) {
586 2 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
587 : }
588 : }
589 :
590 102775 : if (txVariants.empty())
591 0 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transaction");
592 :
593 : // mergedTx will end up with all the signatures; it
594 : // starts as a clone of the rawtx:
595 102779 : CMutableTransaction mergedTx(txVariants[0]);
596 :
597 : // Fetch previous transactions (inputs):
598 205550 : std::map<COutPoint, std::pair<CScript, CAmount>> mapPrevOut; // todo: check why do we have this for regtest..
599 102775 : if (Params().IsRegTestNet()) {
600 305657 : for (const CTxIn &txbase : mergedTx.vin)
601 : {
602 202888 : CTransactionRef tempTx;
603 202888 : uint256 hashBlock;
604 202888 : if (GetTransaction(txbase.prevout.hash, tempTx, hashBlock, true)) {
605 : // Copy results into mapPrevOut:
606 202878 : mapPrevOut[txbase.prevout] = std::make_pair(tempTx->vout[txbase.prevout.n].scriptPubKey, tempTx->vout[txbase.prevout.n].nValue);
607 : }
608 : }
609 : }
610 102771 : CCoinsView viewDummy;
611 205550 : CCoinsViewCache view(&viewDummy);
612 102775 : {
613 102775 : LOCK(mempool.cs);
614 102775 : CCoinsViewCache& viewChain = *pcoinsTip;
615 205550 : CCoinsViewMemPool viewMempool(&viewChain, mempool);
616 102775 : view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
617 :
618 305669 : for (const CTxIn& txin : mergedTx.vin) {
619 202894 : view.AccessCoin(txin.prevout); // Load entries from viewChain into view; can fail.
620 : }
621 :
622 102775 : view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
623 : }
624 :
625 102775 : bool fGivenKeys = false;
626 205550 : CBasicKeyStore tempKeystore;
627 102775 : if (request.params.size() > 2 && !request.params[2].isNull()) {
628 5 : fGivenKeys = true;
629 10 : UniValue keys = request.params[2].get_array();
630 9 : for (unsigned int idx = 0; idx < keys.size(); idx++) {
631 4 : UniValue k = keys[idx];
632 8 : CKey key = KeyIO::DecodeSecret(k.get_str());
633 4 : if (!key.IsValid())
634 0 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
635 4 : tempKeystore.AddKey(key);
636 : }
637 : }
638 : #ifdef ENABLE_WALLET
639 102770 : else if (pwallet)
640 102767 : EnsureWalletIsUnlocked(pwallet);
641 : #endif
642 :
643 : // Add previous txouts given in the RPC call:
644 102775 : if (request.params.size() > 1 && !request.params[1].isNull()) {
645 30 : UniValue prevTxs = request.params[1].get_array();
646 27 : for (unsigned int idx = 0; idx < prevTxs.size(); idx++) {
647 15 : const UniValue& p = prevTxs[idx];
648 15 : if (!p.isObject())
649 0 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
650 :
651 15 : UniValue prevOut = p.get_obj();
652 :
653 75 : RPCTypeCheckObj(prevOut,
654 : {
655 15 : {"txid", UniValueType(UniValue::VSTR)},
656 15 : {"vout", UniValueType(UniValue::VNUM)},
657 18 : {"scriptPubKey", UniValueType(UniValue::VSTR)},
658 60 : });
659 :
660 12 : uint256 txid = ParseHashO(prevOut, "txid");
661 :
662 12 : int nOut = find_value(prevOut, "vout").get_int();
663 12 : if (nOut < 0)
664 0 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
665 :
666 12 : COutPoint out(txid, nOut);
667 24 : std::vector<unsigned char> pkData(ParseHexO(prevOut, "scriptPubKey"));
668 24 : CScript scriptPubKey(pkData.begin(), pkData.end());
669 :
670 12 : {
671 12 : const Coin& coin = view.AccessCoin(out);
672 12 : if (!coin.IsSpent() && coin.out.scriptPubKey != scriptPubKey) {
673 0 : std::string err("Previous output scriptPubKey mismatch:\n");
674 0 : err = err + ScriptToAsmStr(coin.out.scriptPubKey) + "\nvs:\n"+
675 0 : ScriptToAsmStr(scriptPubKey);
676 0 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
677 : }
678 :
679 12 : Coin newcoin;
680 12 : newcoin.out.scriptPubKey = scriptPubKey;
681 12 : newcoin.out.nValue = 0;
682 12 : newcoin.nHeight = 1;
683 24 : if (prevOut.exists("amount")) {
684 4 : newcoin.out.nValue = AmountFromValue(find_value(prevOut, "amount"));
685 : }
686 12 : view.AddCoin(out, std::move(newcoin), true);
687 : }
688 :
689 : // if redeemScript given and not using the local wallet (private keys
690 : // given), add redeemScript to the tempKeystore so it can be signed:
691 12 : if (fGivenKeys && scriptPubKey.IsPayToScriptHash()) {
692 12 : RPCTypeCheckObj(prevOut,
693 : {
694 2 : {"txid", UniValueType(UniValue::VSTR)},
695 2 : {"vout", UniValueType(UniValue::VNUM)},
696 2 : {"scriptPubKey", UniValueType(UniValue::VSTR)},
697 2 : {"redeemScript", UniValueType(UniValue::VSTR)},
698 10 : });
699 4 : UniValue v = find_value(prevOut, "redeemScript");
700 2 : if (!v.isNull()) {
701 4 : std::vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
702 4 : CScript redeemScript(rsData.begin(), rsData.end());
703 2 : tempKeystore.AddCScript(redeemScript);
704 : }
705 : }
706 : }
707 : }
708 :
709 : #ifdef ENABLE_WALLET
710 102772 : const CKeyStore& keystore = ((fGivenKeys || !pwallet) ? tempKeystore : *pwallet);
711 : #else
712 : const CKeyStore& keystore = tempKeystore;
713 : #endif
714 :
715 102772 : int nHashType = SIGHASH_ALL;
716 102772 : if (request.params.size() > 3 && !request.params[3].isNull()) {
717 4 : static std::map<std::string, int> mapSigHashValues = {
718 4 : {std::string("ALL"), int(SIGHASH_ALL)},
719 4 : {std::string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY)},
720 4 : {std::string("NONE"), int(SIGHASH_NONE)},
721 4 : {std::string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY)},
722 4 : {std::string("SINGLE"), int(SIGHASH_SINGLE)},
723 4 : {std::string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)},
724 28 : };
725 8 : std::string strHashType = request.params[3].get_str();
726 4 : if (mapSigHashValues.count(strHashType))
727 3 : nHashType = mapSigHashValues[strHashType];
728 : else
729 2 : throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param");
730 : }
731 :
732 102771 : bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
733 :
734 : // Script verification errors
735 205542 : UniValue vErrors(UniValue::VARR);
736 :
737 : // Use CTransaction for the constant parts of the
738 : // transaction to avoid rehashing.
739 102771 : const CTransaction txConst(mergedTx);
740 : // Sign what we can:
741 305661 : for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
742 202890 : CTxIn& txin = mergedTx.vin[i];
743 202890 : const Coin& coin = view.AccessCoin(txin.prevout);
744 202890 : if (Params().IsRegTestNet()) {
745 405770 : if (mapPrevOut.count(txin.prevout) == 0 && coin.IsSpent())
746 : {
747 2 : TxInErrorToJSON(txin, vErrors, "Input not found");
748 5 : continue;
749 : }
750 : } else {
751 5 : if (coin.IsSpent()) {
752 3 : TxInErrorToJSON(txin, vErrors, "Input not found or already spent");
753 3 : continue;
754 : }
755 : }
756 :
757 405768 : const CScript& prevPubKey = (Params().IsRegTestNet() && mapPrevOut.count(txin.prevout) != 0 ? mapPrevOut[txin.prevout].first : coin.out.scriptPubKey);
758 405768 : const CAmount& amount = (Params().IsRegTestNet() && mapPrevOut.count(txin.prevout) != 0 ? mapPrevOut[txin.prevout].second : coin.out.nValue);
759 :
760 202885 : txin.scriptSig.clear();
761 :
762 : // if this is a P2CS script, select which key to use
763 202885 : bool fColdStake = false;
764 202885 : if (prevPubKey.IsPayToColdStaking()) {
765 : // if we have both keys, sign with the spender key
766 25 : fColdStake = !bool(IsMine(keystore, prevPubKey) & ISMINE_SPENDABLE_DELEGATED);
767 : }
768 :
769 405770 : SignatureData sigdata;
770 202885 : SigVersion sigversion = mergedTx.GetRequiredSigVersion();
771 : // Only sign SIGHASH_SINGLE if there's a corresponding output:
772 202885 : if (!fHashSingle || (i < mergedTx.vout.size()))
773 608655 : ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType),
774 : prevPubKey, sigdata, sigversion, fColdStake);
775 :
776 : // ... and merge in other signatures:
777 405770 : for (const CMutableTransaction& txv : txVariants) {
778 405768 : sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(txv, i));
779 : }
780 :
781 202885 : UpdateTransaction(mergedTx, i, sigdata);
782 :
783 202885 : ScriptError serror = SCRIPT_ERR_OK;
784 202885 : if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS,
785 202885 : TransactionSignatureChecker(&txConst, i, amount), sigversion, &serror)) {
786 16 : TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
787 : }
788 : }
789 102771 : bool fComplete = vErrors.empty();
790 :
791 102771 : UniValue result(UniValue::VOBJ);
792 308313 : result.pushKV("hex", EncodeHexTx(mergedTx));
793 102771 : result.pushKV("complete", fComplete);
794 102771 : if (!vErrors.empty()) {
795 24 : result.pushKV("errors", vErrors);
796 : }
797 :
798 205542 : return result;
799 : }
800 :
801 108627 : void TryATMP(const CMutableTransaction& mtx, bool fOverrideFees)
802 : {
803 108627 : const uint256& hashTx = mtx.GetHash();
804 108627 : std::promise<void> promise;
805 108627 : bool fLimitFree = true;
806 :
807 108627 : { // cs_main scope
808 108646 : LOCK(cs_main);
809 108627 : CCoinsViewCache& view = *pcoinsTip;
810 108627 : bool fHaveChain = false;
811 426907 : for (size_t o = 0; !fHaveChain && o < mtx.vout.size(); o++) {
812 318299 : const Coin& existingCoin = view.AccessCoin(COutPoint(hashTx, o));
813 318280 : fHaveChain = !existingCoin.IsSpent();
814 : }
815 108627 : bool fHaveMempool = mempool.exists(hashTx);
816 108627 : if (!fHaveMempool && !fHaveChain) {
817 108627 : CValidationState state;
818 108627 : bool fMissingInputs;
819 217254 : if (!AcceptToMemoryPool(mempool, state, MakeTransactionRef(std::move(mtx)), fLimitFree, &fMissingInputs, false, !fOverrideFees)) {
820 19 : if (state.IsInvalid()) {
821 78 : throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%s: %s", state.GetRejectReason(), state.GetDebugMessage()));
822 : } else {
823 2 : if (fMissingInputs) {
824 4 : throw JSONRPCError(RPC_TRANSACTION_ERROR, "Missing inputs");
825 : }
826 0 : throw JSONRPCError(RPC_TRANSACTION_ERROR, strprintf("%s: %s", state.GetRejectReason(), state.GetDebugMessage()));
827 : }
828 : } else {
829 : // If wallet is enabled, ensure that the wallet has been made aware
830 : // of the new transaction prior to returning. This prevents a race
831 : // where a user might call sendrawtransaction with a transaction
832 : // to/from their wallet, immediately call some wallet RPC, and get
833 : // a stale result because callbacks have not yet been processed.
834 217235 : CallFunctionInValidationInterfaceQueue([&promise] {
835 108608 : promise.set_value();
836 : });
837 : }
838 0 : } else if (fHaveChain) {
839 0 : throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
840 : }
841 :
842 : } // cs_main
843 :
844 325843 : promise.get_future().wait();
845 108608 : }
846 :
847 108608 : void RelayTx(const uint256& hashTx)
848 : {
849 108608 : if(!g_connman)
850 0 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
851 :
852 108608 : CInv inv(MSG_TX, hashTx);
853 108608 : g_connman->ForEachNode([&inv](CNode* pnode)
854 : {
855 8495 : pnode->PushInventory(inv);
856 8495 : });
857 108608 : }
858 :
859 108542 : UniValue sendrawtransaction(const JSONRPCRequest& request)
860 : {
861 108542 : if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
862 1 : throw std::runtime_error(
863 : "sendrawtransaction \"hexstring\" ( allowhighfees )\n"
864 : "\nSubmits raw transaction (serialized, hex-encoded) to local node and network.\n"
865 : "\nAlso see createrawtransaction and signrawtransaction calls.\n"
866 :
867 : "\nArguments:\n"
868 : "1. \"hexstring\" (string, required) The hex string of the raw transaction)\n"
869 : "2. allowhighfees (boolean, optional, default=false) Allow high fees\n"
870 :
871 : "\nResult:\n"
872 : "\"hex\" (string) The transaction hash in hex\n"
873 :
874 : "\nExamples:\n"
875 2 : "\nCreate a transaction\n" +
876 6 : HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") +
877 5 : "Sign the transaction, and get back the hex\n" + HelpExampleCli("signrawtransaction", "\"myhex\"") +
878 5 : "\nSend the transaction (signed hex)\n" + HelpExampleCli("sendrawtransaction", "\"signedhex\"") +
879 5 : "\nAs a json rpc call\n" + HelpExampleRpc("sendrawtransaction", "\"signedhex\""));
880 :
881 108541 : RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL});
882 :
883 : // parse hex string from parameter
884 108541 : CMutableTransaction mtx;
885 108541 : if (!DecodeHexTx(mtx, request.params[0].get_str()))
886 4 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
887 108539 : const uint256& hashTx = mtx.GetHash();
888 :
889 108539 : bool fOverrideFees = false;
890 108539 : if (request.params.size() > 1)
891 5926 : fOverrideFees = request.params[1].get_bool();
892 :
893 108539 : TryATMP(mtx, fOverrideFees);
894 108525 : RelayTx(hashTx);
895 :
896 217066 : return hashTx.GetHex();
897 : }
898 :
899 : // clang-format off
900 : static const CRPCCommand commands[] =
901 : { // category name actor (function) okSafe argNames
902 : // --------------------- ------------------------ ----------------------- ------ --------
903 : { "rawtransactions", "createrawtransaction", &createrawtransaction, true, {"inputs","outputs","locktime"} },
904 : { "rawtransactions", "decoderawtransaction", &decoderawtransaction, true, {"hexstring"} },
905 : { "rawtransactions", "decodescript", &decodescript, true, {"hexstring"} },
906 : { "rawtransactions", "getrawtransaction", &getrawtransaction, true, {"txid","verbose","blockhash"} },
907 : { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false, {"hexstring","allowhighfees"} },
908 : { "rawtransactions", "signrawtransaction", &signrawtransaction, false, {"hexstring","prevtxs","privkeys","sighashtype"} }, /* uses wallet if enabled */
909 : };
910 : // clang-format on
911 :
912 494 : void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC)
913 : {
914 3458 : for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
915 2964 : tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
916 494 : }
|