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