]> Git Repo - VerusCoin.git/blob - src/rpcrawtransaction.cpp
Auto merge of #887 - str4d:mining-slow-start, r=ebfull
[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 "consensus/validation.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 "primitives/transaction.h"
15 #include "rpcserver.h"
16 #include "script/script.h"
17 #include "script/script_error.h"
18 #include "script/sign.h"
19 #include "script/standard.h"
20 #include "uint256.h"
21 #ifdef ENABLE_WALLET
22 #include "wallet/wallet.h"
23 #endif
24
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
31 using namespace json_spirit;
32 using namespace std;
33
34 void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex)
35 {
36     txnouttype type;
37     vector<CTxDestination> addresses;
38     int nRequired;
39
40     out.push_back(Pair("asm", scriptPubKey.ToString()));
41     if (fIncludeHex)
42         out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
43
44     if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) {
45         out.push_back(Pair("type", GetTxnOutputType(type)));
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
58 void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
59 {
60     entry.push_back(Pair("txid", tx.GetHash().GetHex()));
61     entry.push_back(Pair("version", tx.nVersion));
62     entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
63     Array vin;
64     BOOST_FOREACH(const CTxIn& txin, tx.vin) {
65         Object in;
66         if (tx.IsCoinBase())
67             in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
68         else {
69             in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
70             in.push_back(Pair("vout", (int64_t)txin.prevout.n));
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         }
76         in.push_back(Pair("sequence", (int64_t)txin.nSequence));
77         vin.push_back(in);
78     }
79     entry.push_back(Pair("vin", vin));
80     Array vout;
81     for (unsigned int i = 0; i < tx.vout.size(); i++) {
82         const CTxOut& txout = tx.vout[i];
83         Object out;
84         out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
85         out.push_back(Pair("n", (int64_t)i));
86         Object o;
87         ScriptPubKeyToJSON(txout.scriptPubKey, o, true);
88         out.push_back(Pair("scriptPubKey", o));
89         vout.push_back(out);
90     }
91     entry.push_back(Pair("vout", vout));
92
93     Array vpour;
94     for (unsigned int i = 0; i < tx.vpour.size(); i++) {
95         const CPourTx& pourtx = tx.vpour[i];
96         Object pour;
97
98         pour.push_back(Pair("anchor", pourtx.anchor.GetHex()));
99
100         {
101             Array serials;
102             BOOST_FOREACH(const uint256 serial, pourtx.serials) {
103                 serials.push_back(serial.GetHex());
104             }
105             pour.push_back(Pair("serials", serials));
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
127         // TODO: #808
128         uint256 pubKeyHash;
129         pour.push_back(Pair("valid", pourtx.Verify(*pzcashParams, pubKeyHash)));
130
131         vpour.push_back(pour);
132     }
133
134     entry.push_back(Pair("vpour", vpour));
135
136     if (!hashBlock.IsNull()) {
137         entry.push_back(Pair("blockhash", hashBlock.GetHex()));
138         BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
139         if (mi != mapBlockIndex.end() && (*mi).second) {
140             CBlockIndex* pindex = (*mi).second;
141             if (chainActive.Contains(pindex)) {
142                 entry.push_back(Pair("confirmations", 1 + chainActive.Height() - pindex->nHeight));
143                 entry.push_back(Pair("time", pindex->GetBlockTime()));
144                 entry.push_back(Pair("blocktime", pindex->GetBlockTime()));
145             }
146             else
147                 entry.push_back(Pair("confirmations", 0));
148         }
149     }
150 }
151
152 Value getrawtransaction(const Array& params, bool fHelp)
153 {
154     if (fHelp || params.size() < 1 || params.size() > 2)
155         throw runtime_error(
156             "getrawtransaction \"txid\" ( verbose )\n"
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"
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         );
217
218     LOCK(cs_main);
219
220     uint256 hash = ParseHashV(params[0], "parameter 1");
221
222     bool fVerbose = false;
223     if (params.size() > 1)
224         fVerbose = (params[1].get_int() != 0);
225
226     CTransaction tx;
227     uint256 hashBlock;
228     if (!GetTransaction(hash, tx, hashBlock, true))
229         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
230
231     string strHex = EncodeHexTx(tx);
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
242 Value 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
322 Value 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
355 Value createrawtransaction(const Array& params, bool fHelp)
356 {
357     if (fHelp || params.size() != 2)
358         throw runtime_error(
359             "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,...}\n"
360             "\nCreate a transaction spending the given inputs and sending to the given addresses.\n"
361             "Returns hex-encoded raw transaction.\n"
362             "Note that the transaction's inputs are not signed, and\n"
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         );
387
388     LOCK(cs_main);
389     RPCTypeCheck(params, boost::assign::list_of(array_type)(obj_type));
390
391     Array inputs = params[0].get_array();
392     Object sendTo = params[1].get_obj();
393
394     CMutableTransaction rawTx;
395
396     BOOST_FOREACH(const Value& input, inputs) {
397         const Object& o = input.get_obj();
398
399         uint256 txid = ParseHashO(o, "txid");
400
401         const Value& vout_v = find_value(o, "vout");
402         if (vout_v.type() != int_type)
403             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
404         int nOutput = vout_v.get_int();
405         if (nOutput < 0)
406             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
407
408         CTxIn in(COutPoint(txid, nOutput));
409         rawTx.vin.push_back(in);
410     }
411
412     set<CBitcoinAddress> setAddress;
413     BOOST_FOREACH(const Pair& s, sendTo) {
414         CBitcoinAddress address(s.name_);
415         if (!address.IsValid())
416             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
417
418         if (setAddress.count(address))
419             throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
420         setAddress.insert(address);
421
422         CScript scriptPubKey = GetScriptForDestination(address.Get());
423         CAmount nAmount = AmountFromValue(s.value_);
424
425         CTxOut out(nAmount, scriptPubKey);
426         rawTx.vout.push_back(out);
427     }
428
429     return EncodeHexTx(rawTx);
430 }
431
432 Value decoderawtransaction(const Array& params, bool fHelp)
433 {
434     if (fHelp || params.size() != 1)
435         throw runtime_error(
436             "decoderawtransaction \"hexstring\"\n"
437             "\nReturn a JSON object representing the serialized, hex-encoded transaction.\n"
438
439             "\nArguments:\n"
440             "1. \"hex\"      (string, required) The transaction hex string\n"
441
442             "\nResult:\n"
443             "{\n"
444             "  \"txid\" : \"id\",        (string) The transaction id\n"
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"
476             "}\n"
477
478             "\nExamples:\n"
479             + HelpExampleCli("decoderawtransaction", "\"hexstring\"")
480             + HelpExampleRpc("decoderawtransaction", "\"hexstring\"")
481         );
482
483     LOCK(cs_main);
484     RPCTypeCheck(params, boost::assign::list_of(str_type));
485
486     CTransaction tx;
487
488     if (!DecodeHexTx(tx, params[0].get_str()))
489         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
490
491     Object result;
492     TxToJSON(tx, uint256(), result);
493
494     return result;
495 }
496
497 Value decodescript(const Array& params, bool fHelp)
498 {
499     if (fHelp || params.size() != 1)
500         throw runtime_error(
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         );
521
522     LOCK(cs_main);
523     RPCTypeCheck(params, boost::assign::list_of(str_type));
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
535     r.push_back(Pair("p2sh", CBitcoinAddress(CScriptID(script)).ToString()));
536     return r;
537 }
538
539 /** Pushes a JSON object for script verification or signing errors to vErrorsRet. */
540 static 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
551 Value signrawtransaction(const Array& params, bool fHelp)
552 {
553     if (fHelp || params.size() < 1 || params.size() > 4)
554         throw runtime_error(
555             "signrawtransaction \"hexstring\" ( [{\"txid\":\"id\",\"vout\":n,\"scriptPubKey\":\"hex\",\"redeemScript\":\"hex\"},...] [\"privatekey1\",...] sighashtype )\n"
556             "\nSign inputs for raw transaction (serialized, hex-encoded).\n"
557             "The second optional argument (may be null) is an array of previous transaction outputs that\n"
558             "this transaction depends on but may not yet be in the block chain.\n"
559             "The third optional argument (may be null) is an array of base58-encoded private\n"
560             "keys that, if given, will be the only keys used to sign the transaction.\n"
561 #ifdef ENABLE_WALLET
562             + HelpRequiringPassphrase() + "\n"
563 #endif
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"
568             "     [               (json array of json objects, or 'null' if none provided)\n"
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"
573             "         \"redeemScript\": \"hex\"    (string, required for P2SH) redeem script\n"
574             "       }\n"
575             "       ,...\n"
576             "    ]\n"
577             "3. \"privatekeys\"     (string, optional) A json array of base58-encoded private keys for signing\n"
578             "    [                  (json array of strings, or 'null' if none provided)\n"
579             "      \"privatekey\"   (string) private key in base58-encoding\n"
580             "      ,...\n"
581             "    ]\n"
582             "4. \"sighashtype\"     (string, optional, default=ALL) The signature hash type. Must be one of\n"
583             "       \"ALL\"\n"
584             "       \"NONE\"\n"
585             "       \"SINGLE\"\n"
586             "       \"ALL|ANYONECANPAY\"\n"
587             "       \"NONE|ANYONECANPAY\"\n"
588             "       \"SINGLE|ANYONECANPAY\"\n"
589
590             "\nResult:\n"
591             "{\n"
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"
604             "}\n"
605
606             "\nExamples:\n"
607             + HelpExampleCli("signrawtransaction", "\"myhex\"")
608             + HelpExampleRpc("signrawtransaction", "\"myhex\"")
609         );
610
611 #ifdef ENABLE_WALLET
612     LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
613 #else
614     LOCK(cs_main);
615 #endif
616     RPCTypeCheck(params, boost::assign::list_of(str_type)(array_type)(array_type)(str_type), true);
617
618     vector<unsigned char> txData(ParseHexV(params[0], "argument 1"));
619     CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
620     vector<CMutableTransaction> txVariants;
621     while (!ssData.empty()) {
622         try {
623             CMutableTransaction tx;
624             ssData >> tx;
625             txVariants.push_back(tx);
626         }
627         catch (const std::exception&) {
628             throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
629         }
630     }
631
632     if (txVariants.empty())
633         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transaction");
634
635     // mergedTx will end up with all the signatures; it
636     // starts as a clone of the rawtx:
637     CMutableTransaction mergedTx(txVariants[0]);
638
639     // Fetch previous transactions (inputs):
640     CCoinsView viewDummy;
641     CCoinsViewCache view(&viewDummy);
642     {
643         LOCK(mempool.cs);
644         CCoinsViewCache &viewChain = *pcoinsTip;
645         CCoinsViewMemPool viewMempool(&viewChain, mempool);
646         view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
647
648         BOOST_FOREACH(const CTxIn& txin, mergedTx.vin) {
649             const uint256& prevHash = txin.prevout.hash;
650             CCoins coins;
651             view.AccessCoins(prevHash); // this is certainly allowed to fail
652         }
653
654         view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
655     }
656
657     bool fGivenKeys = false;
658     CBasicKeyStore tempKeystore;
659     if (params.size() > 2 && params[2].type() != null_type) {
660         fGivenKeys = true;
661         Array keys = params[2].get_array();
662         BOOST_FOREACH(Value k, keys) {
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");
667             CKey key = vchSecret.GetKey();
668             if (!key.IsValid())
669                 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
670             tempKeystore.AddKey(key);
671         }
672     }
673 #ifdef ENABLE_WALLET
674     else if (pwalletMain)
675         EnsureWalletIsUnlocked();
676 #endif
677
678     // Add previous txouts given in the RPC call:
679     if (params.size() > 1 && params[1].type() != null_type) {
680         Array prevTxs = params[1].get_array();
681         BOOST_FOREACH(Value& p, prevTxs) {
682             if (p.type() != obj_type)
683                 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
684
685             Object prevOut = p.get_obj();
686
687             RPCTypeCheck(prevOut, boost::assign::map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type));
688
689             uint256 txid = ParseHashO(prevOut, "txid");
690
691             int nOut = find_value(prevOut, "vout").get_int();
692             if (nOut < 0)
693                 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
694
695             vector<unsigned char> pkData(ParseHexO(prevOut, "scriptPubKey"));
696             CScript scriptPubKey(pkData.begin(), pkData.end());
697
698             {
699                 CCoinsModifier coins = view.ModifyCoins(txid);
700                 if (coins->IsAvailable(nOut) && coins->vout[nOut].scriptPubKey != scriptPubKey) {
701                     string err("Previous output scriptPubKey mismatch:\n");
702                     err = err + coins->vout[nOut].scriptPubKey.ToString() + "\nvs:\n"+
703                         scriptPubKey.ToString();
704                     throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
705                 }
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
710             }
711
712             // if redeemScript given and not using the local wallet (private keys
713             // given), add redeemScript to the tempKeystore so it can be signed:
714             if (fGivenKeys && scriptPubKey.IsPayToScriptHash()) {
715                 RPCTypeCheck(prevOut, boost::assign::map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type)("redeemScript",str_type));
716                 Value v = find_value(prevOut, "redeemScript");
717                 if (!(v == Value::null)) {
718                     vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
719                     CScript redeemScript(rsData.begin(), rsData.end());
720                     tempKeystore.AddCScript(redeemScript);
721                 }
722             }
723         }
724     }
725
726 #ifdef ENABLE_WALLET
727     const CKeyStore& keystore = ((fGivenKeys || !pwalletMain) ? tempKeystore : *pwalletMain);
728 #else
729     const CKeyStore& keystore = tempKeystore;
730 #endif
731
732     int nHashType = SIGHASH_ALL;
733     if (params.size() > 3 && params[3].type() != null_type) {
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
747             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param");
748     }
749
750     bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
751
752     // Script verification errors
753     Array vErrors;
754
755     // Sign what we can:
756     for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
757         CTxIn& txin = mergedTx.vin[i];
758         const CCoins* coins = view.AccessCoins(txin.prevout.hash);
759         if (coins == NULL || !coins->IsAvailable(txin.prevout.n)) {
760             TxInErrorToJSON(txin, vErrors, "Input not found or already spent");
761             continue;
762         }
763         const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
764
765         txin.scriptSig.clear();
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);
769
770         // ... and merge in other signatures:
771         BOOST_FOREACH(const CMutableTransaction& txv, txVariants) {
772             txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
773         }
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         }
778     }
779     bool fComplete = vErrors.empty();
780
781     Object result;
782     result.push_back(Pair("hex", EncodeHexTx(mergedTx)));
783     result.push_back(Pair("complete", fComplete));
784     if (!vErrors.empty()) {
785         result.push_back(Pair("errors", vErrors));
786     }
787
788     return result;
789 }
790
791 Value sendrawtransaction(const Array& params, bool fHelp)
792 {
793     if (fHelp || params.size() < 1 || params.size() > 2)
794         throw runtime_error(
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
814     LOCK(cs_main);
815     RPCTypeCheck(params, boost::assign::list_of(str_type)(bool_type));
816
817     // parse hex string from parameter
818     CTransaction tx;
819     if (!DecodeHexTx(tx, params[0].get_str()))
820         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
821     uint256 hashTx = tx.GetHash();
822
823     bool fOverrideFees = false;
824     if (params.size() > 1)
825         fOverrideFees = params[1].get_bool();
826
827     CCoinsViewCache &view = *pcoinsTip;
828     const CCoins* existingCoins = view.AccessCoins(hashTx);
829     bool fHaveMempool = mempool.exists(hashTx);
830     bool fHaveChain = existingCoins && existingCoins->nHeight < 1000000000;
831     if (!fHaveMempool && !fHaveChain) {
832         // push to local node and sync with wallets
833         CValidationState state;
834         bool fMissingInputs;
835         if (!AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, !fOverrideFees)) {
836             if (state.IsInvalid()) {
837                 throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
838             } else {
839                 if (fMissingInputs) {
840                     throw JSONRPCError(RPC_TRANSACTION_ERROR, "Missing inputs");
841                 }
842                 throw JSONRPCError(RPC_TRANSACTION_ERROR, state.GetRejectReason());
843             }
844         }
845     } else if (fHaveChain) {
846         throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
847     }
848     RelayTransaction(tx);
849
850     return hashTx.GetHex();
851 }
This page took 0.072595 seconds and 4 git commands to generate.