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