]> Git Repo - VerusCoin.git/blame - src/rpcrawtransaction.cpp
Rename mapSerials to mapNullifiers.
[VerusCoin.git] / src / rpcrawtransaction.cpp
CommitLineData
a2709fad 1// Copyright (c) 2010 Satoshi Nakamoto
8ac2a4e1 2// Copyright (c) 2009-2015 The Bitcoin Core developers
72fb3d29 3// Distributed under the MIT software license, see the accompanying
a2709fad
GA
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
a2709fad 6#include "base58.h"
da29ecbc 7#include "consensus/validation.h"
ae775b5b 8#include "core_io.h"
a2709fad 9#include "init.h"
c037531d
PK
10#include "keystore.h"
11#include "main.h"
59ed61b3 12#include "merkleblock.h"
771ffb5e 13#include "net.h"
da29ecbc 14#include "primitives/transaction.h"
c037531d 15#include "rpcserver.h"
c4408a6c 16#include "script/script.h"
8ac2a4e1 17#include "script/script_error.h"
e088d65a 18#include "script/sign.h"
611116d4 19#include "script/standard.h"
51ed9ec9 20#include "uint256.h"
48ba56cd 21#ifdef ENABLE_WALLET
50c72f23 22#include "wallet/wallet.h"
48ba56cd 23#endif
a2709fad 24
51ed9ec9
BD
25#include <stdint.h>
26
27#include <boost/assign/list_of.hpp>
28#include "json/json_spirit_utils.h"
29#include "json/json_spirit_value.h"
30
a2709fad 31using namespace json_spirit;
611116d4 32using namespace std;
a2709fad 33
be066fad 34void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex)
a2709fad
GA
35{
36 txnouttype type;
37 vector<CTxDestination> addresses;
38 int nRequired;
39
40 out.push_back(Pair("asm", scriptPubKey.ToString()));
be066fad
PT
41 if (fIncludeHex)
42 out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
a2709fad 43
3ce7e669 44 if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) {
22de68df 45 out.push_back(Pair("type", GetTxnOutputType(type)));
a2709fad
GA
46 return;
47 }
48
49 out.push_back(Pair("reqSigs", nRequired));
50 out.push_back(Pair("type", GetTxnOutputType(type)));
51
52 Array a;
53 BOOST_FOREACH(const CTxDestination& addr, addresses)
54 a.push_back(CBitcoinAddress(addr).ToString());
55 out.push_back(Pair("addresses", a));
56}
57
bdab0cf5 58void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
a2709fad
GA
59{
60 entry.push_back(Pair("txid", tx.GetHash().GetHex()));
61 entry.push_back(Pair("version", tx.nVersion));
4b61a6a4 62 entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
a2709fad 63 Array vin;
3ce7e669 64 BOOST_FOREACH(const CTxIn& txin, tx.vin) {
a2709fad
GA
65 Object in;
66 if (tx.IsCoinBase())
67 in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
3ce7e669 68 else {
a2709fad 69 in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
4b61a6a4 70 in.push_back(Pair("vout", (int64_t)txin.prevout.n));
a2709fad
GA
71 Object o;
72 o.push_back(Pair("asm", txin.scriptSig.ToString()));
73 o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
74 in.push_back(Pair("scriptSig", o));
75 }
4b61a6a4 76 in.push_back(Pair("sequence", (int64_t)txin.nSequence));
a2709fad
GA
77 vin.push_back(in);
78 }
79 entry.push_back(Pair("vin", vin));
80 Array vout;
3ce7e669 81 for (unsigned int i = 0; i < tx.vout.size(); i++) {
a2709fad
GA
82 const CTxOut& txout = tx.vout[i];
83 Object out;
84 out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
4b61a6a4 85 out.push_back(Pair("n", (int64_t)i));
a2709fad 86 Object o;
a702a0b6 87 ScriptPubKeyToJSON(txout.scriptPubKey, o, true);
a2709fad
GA
88 out.push_back(Pair("scriptPubKey", o));
89 vout.push_back(out);
90 }
91 entry.push_back(Pair("vout", vout));
92
8675d94b
SB
93 Array vjoinsplit;
94 for (unsigned int i = 0; i < tx.vjoinsplit.size(); i++) {
95 const JSDescription& pourtx = tx.vjoinsplit[i];
63ea9b75
SB
96 Object pour;
97
98 pour.push_back(Pair("anchor", pourtx.anchor.GetHex()));
99
100 {
bfeaf004
SB
101 Array nullifiers;
102 BOOST_FOREACH(const uint256 serial, pourtx.nullifiers) {
103 nullifiers.push_back(serial.GetHex());
63ea9b75 104 }
bfeaf004 105 pour.push_back(Pair("nullifiers", nullifiers));
63ea9b75
SB
106 }
107
108 {
109 Array commitments;
110 BOOST_FOREACH(const uint256 commitment, pourtx.commitments) {
111 commitments.push_back(commitment.GetHex());
112 }
113 pour.push_back(Pair("commitments", commitments));
114 }
115
116 {
117 Array macs;
118 BOOST_FOREACH(const uint256 mac, pourtx.macs) {
119 macs.push_back(mac.GetHex());
120 }
121 pour.push_back(Pair("macs", macs));
122 }
123
124 pour.push_back(Pair("vpub_old", ValueFromAmount(pourtx.vpub_old)));
125 pour.push_back(Pair("vpub_new", ValueFromAmount(pourtx.vpub_new)));
126
21406393
SB
127 // TODO: #808
128 uint256 pubKeyHash;
2dc35992 129 pour.push_back(Pair("valid", pourtx.Verify(*pzcashParams, pubKeyHash)));
63ea9b75 130
8675d94b 131 vjoinsplit.push_back(pour);
63ea9b75
SB
132 }
133
8675d94b 134 entry.push_back(Pair("vjoinsplit", vjoinsplit));
63ea9b75 135
4f152496 136 if (!hashBlock.IsNull()) {
a2709fad 137 entry.push_back(Pair("blockhash", hashBlock.GetHex()));
145d5be8 138 BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
3ce7e669 139 if (mi != mapBlockIndex.end() && (*mi).second) {
a2709fad 140 CBlockIndex* pindex = (*mi).second;
3ce7e669 141 if (chainActive.Contains(pindex)) {
4c6d41b8 142 entry.push_back(Pair("confirmations", 1 + chainActive.Height() - pindex->nHeight));
209377a7 143 entry.push_back(Pair("time", pindex->GetBlockTime()));
144 entry.push_back(Pair("blocktime", pindex->GetBlockTime()));
a2709fad
GA
145 }
146 else
147 entry.push_back(Pair("confirmations", 0));
148 }
149 }
150}
151
152Value getrawtransaction(const Array& params, bool fHelp)
153{
154 if (fHelp || params.size() < 1 || params.size() > 2)
155 throw runtime_error(
a6099ef3 156 "getrawtransaction \"txid\" ( verbose )\n"
3e61eb9c
CL
157 "\nNOTE: By default this function only works sometimes. This is when the tx is in the mempool\n"
158 "or there is an 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.\n"
a6099ef3 160 "\nReturn the raw transaction data.\n"
161 "\nIf verbose=0, returns a string that is serialized, hex-encoded data for 'txid'.\n"
162 "If verbose is non-zero, returns an Object with information about 'txid'.\n"
163
164 "\nArguments:\n"
165 "1. \"txid\" (string, required) The transaction id\n"
166 "2. verbose (numeric, optional, default=0) If 0, return a string, other return a json object\n"
167
168 "\nResult (if verbose is not set or set to 0):\n"
169 "\"data\" (string) The serialized, hex-encoded data for 'txid'\n"
170
171 "\nResult (if verbose > 0):\n"
172 "{\n"
173 " \"hex\" : \"data\", (string) The serialized, hex-encoded data for 'txid'\n"
174 " \"txid\" : \"id\", (string) The transaction id (same as provided)\n"
175 " \"version\" : n, (numeric) The version\n"
176 " \"locktime\" : ttt, (numeric) The lock time\n"
177 " \"vin\" : [ (array of json objects)\n"
178 " {\n"
179 " \"txid\": \"id\", (string) The transaction id\n"
180 " \"vout\": n, (numeric) \n"
181 " \"scriptSig\": { (json object) The script\n"
182 " \"asm\": \"asm\", (string) asm\n"
183 " \"hex\": \"hex\" (string) hex\n"
184 " },\n"
185 " \"sequence\": n (numeric) The script sequence number\n"
186 " }\n"
187 " ,...\n"
188 " ],\n"
189 " \"vout\" : [ (array of json objects)\n"
190 " {\n"
191 " \"value\" : x.xxx, (numeric) The value in btc\n"
192 " \"n\" : n, (numeric) index\n"
193 " \"scriptPubKey\" : { (json object)\n"
194 " \"asm\" : \"asm\", (string) the asm\n"
195 " \"hex\" : \"hex\", (string) the hex\n"
196 " \"reqSigs\" : n, (numeric) The required sigs\n"
197 " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
198 " \"addresses\" : [ (json array of string)\n"
199 " \"bitcoinaddress\" (string) bitcoin address\n"
200 " ,...\n"
201 " ]\n"
202 " }\n"
203 " }\n"
204 " ,...\n"
205 " ],\n"
206 " \"blockhash\" : \"hash\", (string) the block hash\n"
207 " \"confirmations\" : n, (numeric) The confirmations\n"
208 " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT)\n"
209 " \"blocktime\" : ttt (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
210 "}\n"
211
212 "\nExamples:\n"
213 + HelpExampleCli("getrawtransaction", "\"mytxid\"")
214 + HelpExampleCli("getrawtransaction", "\"mytxid\" 1")
215 + HelpExampleRpc("getrawtransaction", "\"mytxid\", 1")
216 );
a2709fad 217
4401b2d7
EL
218 LOCK(cs_main);
219
2d43f88e 220 uint256 hash = ParseHashV(params[0], "parameter 1");
a2709fad
GA
221
222 bool fVerbose = false;
223 if (params.size() > 1)
224 fVerbose = (params[1].get_int() != 0);
225
226 CTransaction tx;
4f152496 227 uint256 hashBlock;
450cbb09 228 if (!GetTransaction(hash, tx, hashBlock, true))
738835d7 229 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
a2709fad 230
ae775b5b 231 string strHex = EncodeHexTx(tx);
a2709fad
GA
232
233 if (!fVerbose)
234 return strHex;
235
236 Object result;
237 result.push_back(Pair("hex", strHex));
238 TxToJSON(tx, hashBlock, result);
239 return result;
240}
241
59ed61b3
MC
242Value gettxoutproof(const Array& params, bool fHelp)
243{
244 if (fHelp || (params.size() != 1 && params.size() != 2))
245 throw runtime_error(
246 "gettxoutproof [\"txid\",...] ( blockhash )\n"
247 "\nReturns a hex-encoded proof that \"txid\" was included in a block.\n"
248 "\nNOTE: By default this function only works sometimes. This is when there is an\n"
249 "unspent output in the utxo for this transaction. To make it always work,\n"
250 "you need to maintain a transaction index, using the -txindex command line option or\n"
251 "specify the block in which the transaction is included in manually (by blockhash).\n"
252 "\nReturn the raw transaction data.\n"
253 "\nArguments:\n"
254 "1. \"txids\" (string) A json array of txids to filter\n"
255 " [\n"
256 " \"txid\" (string) A transaction hash\n"
257 " ,...\n"
258 " ]\n"
259 "2. \"block hash\" (string, optional) If specified, looks for txid in the block with this hash\n"
260 "\nResult:\n"
261 "\"data\" (string) A string that is a serialized, hex-encoded data for the proof.\n"
262 );
263
264 set<uint256> setTxids;
265 uint256 oneTxid;
266 Array txids = params[0].get_array();
267 BOOST_FOREACH(Value& txid, txids) {
268 if (txid.get_str().length() != 64 || !IsHex(txid.get_str()))
269 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid txid ")+txid.get_str());
270 uint256 hash(uint256S(txid.get_str()));
271 if (setTxids.count(hash))
272 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated txid: ")+txid.get_str());
273 setTxids.insert(hash);
274 oneTxid = hash;
275 }
276
277 LOCK(cs_main);
278
279 CBlockIndex* pblockindex = NULL;
280
281 uint256 hashBlock;
282 if (params.size() > 1)
283 {
284 hashBlock = uint256S(params[1].get_str());
285 if (!mapBlockIndex.count(hashBlock))
286 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
287 pblockindex = mapBlockIndex[hashBlock];
288 } else {
289 CCoins coins;
290 if (pcoinsTip->GetCoins(oneTxid, coins) && coins.nHeight > 0 && coins.nHeight <= chainActive.Height())
291 pblockindex = chainActive[coins.nHeight];
292 }
293
294 if (pblockindex == NULL)
295 {
296 CTransaction tx;
297 if (!GetTransaction(oneTxid, tx, hashBlock, false) || hashBlock.IsNull())
298 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not yet in block");
299 if (!mapBlockIndex.count(hashBlock))
300 throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction index corrupt");
301 pblockindex = mapBlockIndex[hashBlock];
302 }
303
304 CBlock block;
305 if(!ReadBlockFromDisk(block, pblockindex))
306 throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
307
308 unsigned int ntxFound = 0;
309 BOOST_FOREACH(const CTransaction&tx, block.vtx)
310 if (setTxids.count(tx.GetHash()))
311 ntxFound++;
312 if (ntxFound != setTxids.size())
313 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "(Not all) transactions not found in specified block");
314
315 CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION);
316 CMerkleBlock mb(block, setTxids);
317 ssMB << mb;
318 std::string strHex = HexStr(ssMB.begin(), ssMB.end());
319 return strHex;
320}
321
322Value verifytxoutproof(const Array& params, bool fHelp)
323{
324 if (fHelp || params.size() != 1)
325 throw runtime_error(
326 "verifytxoutproof \"proof\"\n"
327 "\nVerifies that a proof points to a transaction in a block, returning the transaction it commits to\n"
328 "and throwing an RPC error if the block is not in our best chain\n"
329 "\nArguments:\n"
330 "1. \"proof\" (string, required) The hex-encoded proof generated by gettxoutproof\n"
331 "\nResult:\n"
332 "[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof is invalid\n"
333 );
334
335 CDataStream ssMB(ParseHexV(params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION);
336 CMerkleBlock merkleBlock;
337 ssMB >> merkleBlock;
338
339 Array res;
340
341 vector<uint256> vMatch;
342 if (merkleBlock.txn.ExtractMatches(vMatch) != merkleBlock.header.hashMerkleRoot)
343 return res;
344
345 LOCK(cs_main);
346
347 if (!mapBlockIndex.count(merkleBlock.header.GetHash()) || !chainActive.Contains(mapBlockIndex[merkleBlock.header.GetHash()]))
348 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain");
349
350 BOOST_FOREACH(const uint256& hash, vMatch)
351 res.push_back(hash.GetHex());
352 return res;
353}
354
a2709fad
GA
355Value createrawtransaction(const Array& params, bool fHelp)
356{
357 if (fHelp || params.size() != 2)
358 throw runtime_error(
a6099ef3 359 "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,...}\n"
360 "\nCreate a transaction spending the given inputs and sending to the given addresses.\n"
a2709fad
GA
361 "Returns hex-encoded raw transaction.\n"
362 "Note that the transaction's inputs are not signed, and\n"
a6099ef3 363 "it is not stored in the wallet or transmitted to the network.\n"
364
365 "\nArguments:\n"
366 "1. \"transactions\" (string, required) A json array of json objects\n"
367 " [\n"
368 " {\n"
369 " \"txid\":\"id\", (string, required) The transaction id\n"
370 " \"vout\":n (numeric, required) The output number\n"
371 " }\n"
372 " ,...\n"
373 " ]\n"
374 "2. \"addresses\" (string, required) a json object with addresses as keys and amounts as values\n"
375 " {\n"
376 " \"address\": x.xxx (numeric, required) The key is the bitcoin address, the value is the btc amount\n"
377 " ,...\n"
378 " }\n"
379
380 "\nResult:\n"
381 "\"transaction\" (string) hex string of the transaction\n"
382
383 "\nExamples\n"
384 + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"{\\\"address\\\":0.01}\"")
385 + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"address\\\":0.01}\"")
386 );
a2709fad 387
4401b2d7 388 LOCK(cs_main);
856e862f 389 RPCTypeCheck(params, boost::assign::list_of(array_type)(obj_type));
a2709fad
GA
390
391 Array inputs = params[0].get_array();
392 Object sendTo = params[1].get_obj();
393
4949004d 394 CMutableTransaction rawTx;
a2709fad 395
3ce7e669 396 BOOST_FOREACH(const Value& input, inputs) {
a2709fad
GA
397 const Object& o = input.get_obj();
398
2d43f88e 399 uint256 txid = ParseHashO(o, "txid");
a2709fad
GA
400
401 const Value& vout_v = find_value(o, "vout");
402 if (vout_v.type() != int_type)
738835d7 403 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
a2709fad
GA
404 int nOutput = vout_v.get_int();
405 if (nOutput < 0)
738835d7 406 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
a2709fad 407
2d43f88e 408 CTxIn in(COutPoint(txid, nOutput));
a2709fad
GA
409 rawTx.vin.push_back(in);
410 }
411
412 set<CBitcoinAddress> setAddress;
3ce7e669 413 BOOST_FOREACH(const Pair& s, sendTo) {
a2709fad
GA
414 CBitcoinAddress address(s.name_);
415 if (!address.IsValid())
738835d7 416 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
a2709fad
GA
417
418 if (setAddress.count(address))
738835d7 419 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
a2709fad
GA
420 setAddress.insert(address);
421
0be990ba 422 CScript scriptPubKey = GetScriptForDestination(address.Get());
a372168e 423 CAmount nAmount = AmountFromValue(s.value_);
a2709fad
GA
424
425 CTxOut out(nAmount, scriptPubKey);
426 rawTx.vout.push_back(out);
427 }
428
ae775b5b 429 return EncodeHexTx(rawTx);
a2709fad
GA
430}
431
432Value decoderawtransaction(const Array& params, bool fHelp)
433{
434 if (fHelp || params.size() != 1)
435 throw runtime_error(
a6099ef3 436 "decoderawtransaction \"hexstring\"\n"
437 "\nReturn a JSON object representing the serialized, hex-encoded transaction.\n"
438
439 "\nArguments:\n"
e0c06d2c 440 "1. \"hex\" (string, required) The transaction hex string\n"
a6099ef3 441
442 "\nResult:\n"
443 "{\n"
e0c06d2c 444 " \"txid\" : \"id\", (string) The transaction id\n"
a6099ef3 445 " \"version\" : n, (numeric) The version\n"
446 " \"locktime\" : ttt, (numeric) The lock time\n"
447 " \"vin\" : [ (array of json objects)\n"
448 " {\n"
449 " \"txid\": \"id\", (string) The transaction id\n"
450 " \"vout\": n, (numeric) The output number\n"
451 " \"scriptSig\": { (json object) The script\n"
452 " \"asm\": \"asm\", (string) asm\n"
453 " \"hex\": \"hex\" (string) hex\n"
454 " },\n"
455 " \"sequence\": n (numeric) The script sequence number\n"
456 " }\n"
457 " ,...\n"
458 " ],\n"
459 " \"vout\" : [ (array of json objects)\n"
460 " {\n"
461 " \"value\" : x.xxx, (numeric) The value in btc\n"
462 " \"n\" : n, (numeric) index\n"
463 " \"scriptPubKey\" : { (json object)\n"
464 " \"asm\" : \"asm\", (string) the asm\n"
465 " \"hex\" : \"hex\", (string) the hex\n"
466 " \"reqSigs\" : n, (numeric) The required sigs\n"
467 " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
468 " \"addresses\" : [ (json array of string)\n"
469 " \"12tvKAXCxZjSmdNbao16dKXC8tRWfcF5oc\" (string) bitcoin address\n"
470 " ,...\n"
471 " ]\n"
472 " }\n"
473 " }\n"
474 " ,...\n"
475 " ],\n"
a6099ef3 476 "}\n"
477
478 "\nExamples:\n"
479 + HelpExampleCli("decoderawtransaction", "\"hexstring\"")
480 + HelpExampleRpc("decoderawtransaction", "\"hexstring\"")
481 );
a2709fad 482
4401b2d7 483 LOCK(cs_main);
856e862f 484 RPCTypeCheck(params, boost::assign::list_of(str_type));
ae775b5b 485
a2709fad 486 CTransaction tx;
ae775b5b
JG
487
488 if (!DecodeHexTx(tx, params[0].get_str()))
738835d7 489 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
a2709fad
GA
490
491 Object result;
4f152496 492 TxToJSON(tx, uint256(), result);
a2709fad
GA
493
494 return result;
495}
496
be066fad
PT
497Value decodescript(const Array& params, bool fHelp)
498{
499 if (fHelp || params.size() != 1)
500 throw runtime_error(
a6099ef3 501 "decodescript \"hex\"\n"
502 "\nDecode a hex-encoded script.\n"
503 "\nArguments:\n"
504 "1. \"hex\" (string) the hex encoded script\n"
505 "\nResult:\n"
506 "{\n"
507 " \"asm\":\"asm\", (string) Script public key\n"
508 " \"hex\":\"hex\", (string) hex encoded public key\n"
509 " \"type\":\"type\", (string) The output type\n"
510 " \"reqSigs\": n, (numeric) The required signatures\n"
511 " \"addresses\": [ (json array of string)\n"
512 " \"address\" (string) bitcoin address\n"
513 " ,...\n"
514 " ],\n"
515 " \"p2sh\",\"address\" (string) script address\n"
516 "}\n"
517 "\nExamples:\n"
518 + HelpExampleCli("decodescript", "\"hexstring\"")
519 + HelpExampleRpc("decodescript", "\"hexstring\"")
520 );
be066fad 521
4401b2d7 522 LOCK(cs_main);
856e862f 523 RPCTypeCheck(params, boost::assign::list_of(str_type));
be066fad
PT
524
525 Object r;
526 CScript script;
527 if (params[0].get_str().size() > 0){
528 vector<unsigned char> scriptData(ParseHexV(params[0], "argument"));
529 script = CScript(scriptData.begin(), scriptData.end());
530 } else {
531 // Empty scripts are valid
532 }
533 ScriptPubKeyToJSON(script, r, false);
534
066e2a14 535 r.push_back(Pair("p2sh", CBitcoinAddress(CScriptID(script)).ToString()));
be066fad
PT
536 return r;
537}
538
8ac2a4e1 539/** Pushes a JSON object for script verification or signing errors to vErrorsRet. */
540static void TxInErrorToJSON(const CTxIn& txin, Array& vErrorsRet, const std::string& strMessage)
541{
542 Object entry;
543 entry.push_back(Pair("txid", txin.prevout.hash.ToString()));
544 entry.push_back(Pair("vout", (uint64_t)txin.prevout.n));
545 entry.push_back(Pair("scriptSig", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
546 entry.push_back(Pair("sequence", (uint64_t)txin.nSequence));
547 entry.push_back(Pair("error", strMessage));
548 vErrorsRet.push_back(entry);
549}
550
a2709fad
GA
551Value signrawtransaction(const Array& params, bool fHelp)
552{
3c3666d6 553 if (fHelp || params.size() < 1 || params.size() > 4)
a2709fad 554 throw runtime_error(
a6099ef3 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"
729b1806 558 "this transaction depends on but may not yet be in the block chain.\n"
a6099ef3 559 "The third optional argument (may be null) is an array of base58-encoded private\n"
a2709fad 560 "keys that, if given, will be the only keys used to sign the transaction.\n"
48ba56cd 561#ifdef ENABLE_WALLET
a6099ef3 562 + HelpRequiringPassphrase() + "\n"
48ba56cd 563#endif
a6099ef3 564
565 "\nArguments:\n"
566 "1. \"hexstring\" (string, required) The transaction hex string\n"
567 "2. \"prevtxs\" (string, optional) An json array of previous dependent transaction outputs\n"
041f71bb 568 " [ (json array of json objects, or 'null' if none provided)\n"
a6099ef3 569 " {\n"
570 " \"txid\":\"id\", (string, required) The transaction id\n"
571 " \"vout\":n, (numeric, required) The output number\n"
572 " \"scriptPubKey\": \"hex\", (string, required) script key\n"
6265ecc8 573 " \"redeemScript\": \"hex\" (string, required for P2SH) redeem script\n"
a6099ef3 574 " }\n"
575 " ,...\n"
576 " ]\n"
577 "3. \"privatekeys\" (string, optional) A json array of base58-encoded private keys for signing\n"
041f71bb 578 " [ (json array of strings, or 'null' if none provided)\n"
a6099ef3 579 " \"privatekey\" (string) private key in base58-encoding\n"
580 " ,...\n"
581 " ]\n"
ab643811 582 "4. \"sighashtype\" (string, optional, default=ALL) The signature hash type. Must be one of\n"
a6099ef3 583 " \"ALL\"\n"
584 " \"NONE\"\n"
585 " \"SINGLE\"\n"
586 " \"ALL|ANYONECANPAY\"\n"
587 " \"NONE|ANYONECANPAY\"\n"
588 " \"SINGLE|ANYONECANPAY\"\n"
589
590 "\nResult:\n"
591 "{\n"
8ac2a4e1 592 " \"hex\" : \"value\", (string) The hex-encoded raw transaction with signature(s)\n"
593 " \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
594 " \"errors\" : [ (json array of objects) Script verification errors (if there are any)\n"
595 " {\n"
596 " \"txid\" : \"hash\", (string) The hash of the referenced, previous transaction\n"
597 " \"vout\" : n, (numeric) The index of the output to spent and used as input\n"
598 " \"scriptSig\" : \"hex\", (string) The hex-encoded signature script\n"
599 " \"sequence\" : n, (numeric) Script sequence number\n"
600 " \"error\" : \"text\" (string) Verification or signing error related to the input\n"
601 " }\n"
602 " ,...\n"
603 " ]\n"
a6099ef3 604 "}\n"
605
606 "\nExamples:\n"
607 + HelpExampleCli("signrawtransaction", "\"myhex\"")
608 + HelpExampleRpc("signrawtransaction", "\"myhex\"")
609 );
a2709fad 610
4401b2d7
EL
611#ifdef ENABLE_WALLET
612 LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
613#else
614 LOCK(cs_main);
615#endif
856e862f 616 RPCTypeCheck(params, boost::assign::list_of(str_type)(array_type)(array_type)(str_type), true);
a2709fad 617
2d43f88e 618 vector<unsigned char> txData(ParseHexV(params[0], "argument 1"));
a2709fad 619 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
4949004d 620 vector<CMutableTransaction> txVariants;
3ce7e669 621 while (!ssData.empty()) {
a2709fad 622 try {
4949004d 623 CMutableTransaction tx;
a2709fad
GA
624 ssData >> tx;
625 txVariants.push_back(tx);
626 }
27df4123 627 catch (const std::exception&) {
738835d7 628 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
a2709fad
GA
629 }
630 }
631
632 if (txVariants.empty())
738835d7 633 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transaction");
a2709fad
GA
634
635 // mergedTx will end up with all the signatures; it
636 // starts as a clone of the rawtx:
4949004d 637 CMutableTransaction mergedTx(txVariants[0]);
a2709fad
GA
638
639 // Fetch previous transactions (inputs):
450cbb09 640 CCoinsView viewDummy;
7c70438d 641 CCoinsViewCache view(&viewDummy);
a2709fad 642 {
450cbb09 643 LOCK(mempool.cs);
ae8bfd12 644 CCoinsViewCache &viewChain = *pcoinsTip;
7c70438d 645 CCoinsViewMemPool viewMempool(&viewChain, mempool);
450cbb09
PW
646 view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
647
648 BOOST_FOREACH(const CTxIn& txin, mergedTx.vin) {
a2709fad 649 const uint256& prevHash = txin.prevout.hash;
450cbb09 650 CCoins coins;
629d75fa 651 view.AccessCoins(prevHash); // this is certainly allowed to fail
a2709fad 652 }
450cbb09 653
ae8bfd12 654 view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
a2709fad
GA
655 }
656
03346a61
GA
657 bool fGivenKeys = false;
658 CBasicKeyStore tempKeystore;
3ce7e669 659 if (params.size() > 2 && params[2].type() != null_type) {
03346a61
GA
660 fGivenKeys = true;
661 Array keys = params[2].get_array();
3ce7e669 662 BOOST_FOREACH(Value k, keys) {
03346a61
GA
663 CBitcoinSecret vchSecret;
664 bool fGood = vchSecret.SetString(k.get_str());
665 if (!fGood)
666 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
dfa23b94 667 CKey key = vchSecret.GetKey();
aa768f18
PJ
668 if (!key.IsValid())
669 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
03346a61
GA
670 tempKeystore.AddKey(key);
671 }
672 }
48ba56cd 673#ifdef ENABLE_WALLET
4401b2d7 674 else if (pwalletMain)
03346a61 675 EnsureWalletIsUnlocked();
48ba56cd 676#endif
03346a61 677
a2709fad 678 // Add previous txouts given in the RPC call:
3ce7e669 679 if (params.size() > 1 && params[1].type() != null_type) {
a2709fad 680 Array prevTxs = params[1].get_array();
3ce7e669 681 BOOST_FOREACH(Value& p, prevTxs) {
a2709fad 682 if (p.type() != obj_type)
738835d7 683 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
a2709fad
GA
684
685 Object prevOut = p.get_obj();
686
856e862f 687 RPCTypeCheck(prevOut, boost::assign::map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type));
a2709fad 688
2d43f88e 689 uint256 txid = ParseHashO(prevOut, "txid");
a2709fad
GA
690
691 int nOut = find_value(prevOut, "vout").get_int();
692 if (nOut < 0)
738835d7 693 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
a2709fad 694
2d43f88e 695 vector<unsigned char> pkData(ParseHexO(prevOut, "scriptPubKey"));
a2709fad
GA
696 CScript scriptPubKey(pkData.begin(), pkData.end());
697
f28aec01
PW
698 {
699 CCoinsModifier coins = view.ModifyCoins(txid);
700 if (coins->IsAvailable(nOut) && coins->vout[nOut].scriptPubKey != scriptPubKey) {
a2709fad 701 string err("Previous output scriptPubKey mismatch:\n");
f28aec01 702 err = err + coins->vout[nOut].scriptPubKey.ToString() + "\nvs:\n"+
a2709fad 703 scriptPubKey.ToString();
738835d7 704 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
a2709fad 705 }
f28aec01
PW
706 if ((unsigned int)nOut >= coins->vout.size())
707 coins->vout.resize(nOut+1);
708 coins->vout[nOut].scriptPubKey = scriptPubKey;
709 coins->vout[nOut].nValue = 0; // we don't know the actual output value
a2709fad 710 }
a2709fad 711
03346a61
GA
712 // if redeemScript given and not using the local wallet (private keys
713 // given), add redeemScript to the tempKeystore so it can be signed:
3ce7e669 714 if (fGivenKeys && scriptPubKey.IsPayToScriptHash()) {
856e862f 715 RPCTypeCheck(prevOut, boost::assign::map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type)("redeemScript",str_type));
21c6d3ae 716 Value v = find_value(prevOut, "redeemScript");
3ce7e669 717 if (!(v == Value::null)) {
21c6d3ae
GM
718 vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
719 CScript redeemScript(rsData.begin(), rsData.end());
720 tempKeystore.AddCScript(redeemScript);
721 }
03346a61 722 }
a2709fad
GA
723 }
724 }
cc6dfd1f 725
48ba56cd 726#ifdef ENABLE_WALLET
b0730874 727 const CKeyStore& keystore = ((fGivenKeys || !pwalletMain) ? tempKeystore : *pwalletMain);
48ba56cd
WL
728#else
729 const CKeyStore& keystore = tempKeystore;
730#endif
a2709fad 731
3c3666d6 732 int nHashType = SIGHASH_ALL;
3ce7e669 733 if (params.size() > 3 && params[3].type() != null_type) {
3c3666d6
GA
734 static map<string, int> mapSigHashValues =
735 boost::assign::map_list_of
736 (string("ALL"), int(SIGHASH_ALL))
737 (string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY))
738 (string("NONE"), int(SIGHASH_NONE))
739 (string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY))
740 (string("SINGLE"), int(SIGHASH_SINGLE))
741 (string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY))
742 ;
743 string strHashType = params[3].get_str();
744 if (mapSigHashValues.count(strHashType))
745 nHashType = mapSigHashValues[strHashType];
746 else
738835d7 747 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param");
3c3666d6
GA
748 }
749
d5e7b611
GA
750 bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
751
8ac2a4e1 752 // Script verification errors
753 Array vErrors;
754
a2709fad 755 // Sign what we can:
3ce7e669 756 for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
a2709fad 757 CTxIn& txin = mergedTx.vin[i];
629d75fa
PW
758 const CCoins* coins = view.AccessCoins(txin.prevout.hash);
759 if (coins == NULL || !coins->IsAvailable(txin.prevout.n)) {
8ac2a4e1 760 TxInErrorToJSON(txin, vErrors, "Input not found or already spent");
a2709fad
GA
761 continue;
762 }
629d75fa 763 const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
a2709fad
GA
764
765 txin.scriptSig.clear();
d5e7b611
GA
766 // Only sign SIGHASH_SINGLE if there's a corresponding output:
767 if (!fHashSingle || (i < mergedTx.vout.size()))
768 SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
a2709fad
GA
769
770 // ... and merge in other signatures:
3ce7e669 771 BOOST_FOREACH(const CMutableTransaction& txv, txVariants) {
a2709fad
GA
772 txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
773 }
8ac2a4e1 774 ScriptError serror = SCRIPT_ERR_OK;
775 if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i), &serror)) {
776 TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
777 }
a2709fad 778 }
8ac2a4e1 779 bool fComplete = vErrors.empty();
a2709fad
GA
780
781 Object result;
ae775b5b 782 result.push_back(Pair("hex", EncodeHexTx(mergedTx)));
a2709fad 783 result.push_back(Pair("complete", fComplete));
8ac2a4e1 784 if (!vErrors.empty()) {
785 result.push_back(Pair("errors", vErrors));
786 }
a2709fad
GA
787
788 return result;
789}
790
791Value sendrawtransaction(const Array& params, bool fHelp)
792{
9d14e689 793 if (fHelp || params.size() < 1 || params.size() > 2)
a2709fad 794 throw runtime_error(
a6099ef3 795 "sendrawtransaction \"hexstring\" ( allowhighfees )\n"
796 "\nSubmits raw transaction (serialized, hex-encoded) to local node and network.\n"
797 "\nAlso see createrawtransaction and signrawtransaction calls.\n"
798 "\nArguments:\n"
799 "1. \"hexstring\" (string, required) The hex string of the raw transaction)\n"
800 "2. allowhighfees (boolean, optional, default=false) Allow high fees\n"
801 "\nResult:\n"
802 "\"hex\" (string) The transaction hash in hex\n"
803 "\nExamples:\n"
804 "\nCreate a transaction\n"
805 + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") +
806 "Sign the transaction, and get back the hex\n"
807 + HelpExampleCli("signrawtransaction", "\"myhex\"") +
808 "\nSend the transaction (signed hex)\n"
809 + HelpExampleCli("sendrawtransaction", "\"signedhex\"") +
810 "\nAs a json rpc call\n"
811 + HelpExampleRpc("sendrawtransaction", "\"signedhex\"")
812 );
813
4401b2d7 814 LOCK(cs_main);
856e862f 815 RPCTypeCheck(params, boost::assign::list_of(str_type)(bool_type));
a2709fad 816
a2709fad 817 // parse hex string from parameter
a2709fad 818 CTransaction tx;
ae775b5b
JG
819 if (!DecodeHexTx(tx, params[0].get_str()))
820 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
821 uint256 hashTx = tx.GetHash();
a2709fad 822
9d14e689
GM
823 bool fOverrideFees = false;
824 if (params.size() > 1)
825 fOverrideFees = params[1].get_bool();
826
ae8bfd12 827 CCoinsViewCache &view = *pcoinsTip;
629d75fa 828 const CCoins* existingCoins = view.AccessCoins(hashTx);
1d46fe33 829 bool fHaveMempool = mempool.exists(hashTx);
629d75fa 830 bool fHaveChain = existingCoins && existingCoins->nHeight < 1000000000;
1d46fe33
WL
831 if (!fHaveMempool && !fHaveChain) {
832 // push to local node and sync with wallets
833 CValidationState state;
de8e801d
PW
834 bool fMissingInputs;
835 if (!AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, !fOverrideFees)) {
836 if (state.IsInvalid()) {
1d46fe33 837 throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
de8e801d
PW
838 } else {
839 if (fMissingInputs) {
840 throw JSONRPCError(RPC_TRANSACTION_ERROR, "Missing inputs");
841 }
1d46fe33 842 throw JSONRPCError(RPC_TRANSACTION_ERROR, state.GetRejectReason());
de8e801d 843 }
450cbb09 844 }
1d46fe33
WL
845 } else if (fHaveChain) {
846 throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
771ffb5e 847 }
d38da59b 848 RelayTransaction(tx);
a2709fad 849
771ffb5e 850 return hashTx.GetHex();
a2709fad 851}
This page took 0.302543 seconds and 4 git commands to generate.