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