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