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