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