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