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