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