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