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.
7 #include "consensus/upgrades.h"
8 #include "consensus/validation.h"
13 #include "merkleblock.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"
23 #include "wallet/wallet.h"
26 #include "komodo_defs.h"
30 #include <boost/assign/list_of.hpp>
36 void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex)
39 vector<CTxDestination> addresses;
42 out.push_back(Pair("asm", scriptPubKey.ToString()));
44 out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
46 if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) {
47 out.push_back(Pair("type", GetTxnOutputType(type)));
51 out.push_back(Pair("reqSigs", nRequired));
52 out.push_back(Pair("type", GetTxnOutputType(type)));
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));
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);
67 joinsplit.push_back(Pair("vpub_old", ValueFromAmount(jsdescription.vpub_old)));
68 joinsplit.push_back(Pair("vpub_new", ValueFromAmount(jsdescription.vpub_new)));
70 joinsplit.push_back(Pair("anchor", jsdescription.anchor.GetHex()));
73 UniValue nullifiers(UniValue::VARR);
74 BOOST_FOREACH(const uint256 nf, jsdescription.nullifiers) {
75 nullifiers.push_back(nf.GetHex());
77 joinsplit.push_back(Pair("nullifiers", nullifiers));
81 UniValue commitments(UniValue::VARR);
82 BOOST_FOREACH(const uint256 commitment, jsdescription.commitments) {
83 commitments.push_back(commitment.GetHex());
85 joinsplit.push_back(Pair("commitments", commitments));
88 joinsplit.push_back(Pair("onetimePubKey", jsdescription.ephemeralKey.GetHex()));
89 joinsplit.push_back(Pair("randomSeed", jsdescription.randomSeed.GetHex()));
92 UniValue macs(UniValue::VARR);
93 BOOST_FOREACH(const uint256 mac, jsdescription.macs) {
94 macs.push_back(mac.GetHex());
96 joinsplit.push_back(Pair("macs", macs));
99 CDataStream ssProof(SER_NETWORK, PROTOCOL_VERSION);
100 ssProof << jsdescription.proof;
101 joinsplit.push_back(Pair("proof", HexStr(ssProof.begin(), ssProof.end())));
104 UniValue ciphertexts(UniValue::VARR);
105 for (const ZCNoteEncryption::Ciphertext ct : jsdescription.ciphertexts) {
106 ciphertexts.push_back(HexStr(ct.begin(), ct.end()));
108 joinsplit.push_back(Pair("ciphertexts", ciphertexts));
111 vjoinsplit.push_back(joinsplit);
116 uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
118 void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
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)));
126 entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
127 if (tx.fOverwintered) {
128 entry.push_back(Pair("expiryheight", (int64_t)tx.nExpiryHeight));
130 UniValue vin(UniValue::VARR);
131 BOOST_FOREACH(const CTxIn& txin, tx.vin) {
132 UniValue in(UniValue::VOBJ);
134 in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
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));
143 in.push_back(Pair("sequence", (int64_t)txin.nSequence));
146 entry.push_back(Pair("vin", vin));
147 BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
148 CBlockIndex *tipindex,*pindex = it->second;
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 )
157 interest = komodo_interest(pindex->nHeight,txout.nValue,tx.nLockTime,tipindex->nTime);
158 out.push_back(Pair("interest", ValueFromAmount(interest)));
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));
167 entry.push_back(Pair("vout", vout));
169 UniValue vjoinsplit = TxJoinSplitToJSON(tx);
170 entry.push_back(Pair("vjoinsplit", vjoinsplit));
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()));
183 entry.push_back(Pair("confirmations", 0));
188 UniValue getrawtransaction(const UniValue& params, bool fHelp)
190 if (fHelp || params.size() < 1 || params.size() > 2)
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"
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"
204 "\nResult (if verbose is not set or set to 0):\n"
205 "\"data\" (string) The serialized, hex-encoded data for 'txid'\n"
207 "\nResult (if verbose > 0):\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"
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"
222 " \"sequence\": n (numeric) The script sequence number\n"
226 " \"vout\" : [ (array of json objects)\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"
243 " \"vjoinsplit\" : [ (array of json objects, only for version >= 2)\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"
252 " \"commitments\" : [ (json array of string)\n"
253 " \"hex\" (string) output note commitment\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"
262 " \"proof\" : \"hex\", (string) the zero-knowledge proof\n"
263 " \"ciphertexts\" : [ (json array of string)\n"
264 " \"hex\" (string) output note ciphertext\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"
277 + HelpExampleCli("getrawtransaction", "\"mytxid\"")
278 + HelpExampleCli("getrawtransaction", "\"mytxid\" 1")
279 + HelpExampleRpc("getrawtransaction", "\"mytxid\", 1")
284 uint256 hash = ParseHashV(params[0], "parameter 1");
286 bool fVerbose = false;
287 if (params.size() > 1)
288 fVerbose = (params[1].get_int() != 0);
292 if (!GetTransaction(hash, tx, hashBlock, true))
293 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
295 string strHex = EncodeHexTx(tx);
300 UniValue result(UniValue::VOBJ);
301 result.push_back(Pair("hex", strHex));
302 TxToJSON(tx, hashBlock, result);
306 int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n)
308 int32_t i,m; uint8_t *ptr;
311 for (iter=0; iter<2; iter++)
316 CCoinsViewMemPool view(pcoinsTip,mempool);
317 if ( view.GetCoins(txid,coins) == 0 )
319 //fprintf(stderr,"cant get view\n");
322 mempool.pruneSpent(txid, coins); // TODO: this should be done by the CCoinsViewMemPool
324 else if ( pcoinsTip->GetCoins(txid,coins) == 0 )
326 //fprintf(stderr,"cant get pcoinsTip->GetCoins\n");
329 if ( n < 0 || (unsigned int)n >= coins.vout.size() || coins.vout[n].IsNull() )
331 fprintf(stderr,"iter.%d n.%d vs voutsize.%d\n",iter,n,(int32_t)coins.vout.size());
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];
342 if ( GetTransaction(txid,tx,hashBlock,true) == 0 )
344 else if ( n <= tx.vout.size() ) // vout.size() seems off by 1
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");
356 UniValue gettxoutproof(const UniValue& params, bool fHelp)
358 if (fHelp || (params.size() != 1 && params.size() != 2))
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"
368 "1. \"txids\" (string) A json array of txids to filter\n"
370 " \"txid\" (string) A transaction hash\n"
373 "2. \"block hash\" (string, optional) If specified, looks for txid in the block with this hash\n"
375 "\"data\" (string) A string that is a serialized, hex-encoded data for the proof.\n"
378 set<uint256> setTxids;
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);
394 CBlockIndex* pblockindex = NULL;
397 if (params.size() > 1)
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];
405 if (pcoinsTip->GetCoins(oneTxid, coins) && coins.nHeight > 0 && coins.nHeight <= chainActive.Height())
406 pblockindex = chainActive[coins.nHeight];
409 if (pblockindex == NULL)
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];
420 if(!ReadBlockFromDisk(block, pblockindex))
421 throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
423 unsigned int ntxFound = 0;
424 BOOST_FOREACH(const CTransaction&tx, block.vtx)
425 if (setTxids.count(tx.GetHash()))
427 if (ntxFound != setTxids.size())
428 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "(Not all) transactions not found in specified block");
430 CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION);
431 CMerkleBlock mb(block, setTxids);
433 std::string strHex = HexStr(ssMB.begin(), ssMB.end());
437 UniValue verifytxoutproof(const UniValue& params, bool fHelp)
439 if (fHelp || params.size() != 1)
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"
445 "1. \"proof\" (string, required) The hex-encoded proof generated by gettxoutproof\n"
447 "[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof is invalid\n"
450 CDataStream ssMB(ParseHexV(params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION);
451 CMerkleBlock merkleBlock;
454 UniValue res(UniValue::VARR);
456 vector<uint256> vMatch;
457 if (merkleBlock.txn.ExtractMatches(vMatch) != merkleBlock.header.hashMerkleRoot)
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");
465 BOOST_FOREACH(const uint256& hash, vMatch)
466 res.push_back(hash.GetHex());
470 UniValue createrawtransaction(const UniValue& params, bool fHelp)
472 if (fHelp || params.size() != 2)
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"
481 "1. \"transactions\" (string, required) A json array of json objects\n"
484 " \"txid\":\"id\", (string, required) The transaction id\n"
485 " \"vout\":n (numeric, required) The output number\n"
489 "2. \"addresses\" (string, required) a json object with addresses as keys and amounts as values\n"
491 " \"address\": x.xxx (numeric, required) The key is the Zcash address, the value is the " + CURRENCY_UNIT + " amount\n"
496 "\"transaction\" (string) hex string of the transaction\n"
499 + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"{\\\"address\\\":0.01}\"")
500 + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"address\\\":0.01}\"")
504 RPCTypeCheck(params, boost::assign::list_of(UniValue::VARR)(UniValue::VOBJ));
506 UniValue inputs = params[0].get_array();
507 UniValue sendTo = params[1].get_obj();
509 int nextBlockHeight = chainActive.Height() + 1;
510 CMutableTransaction rawTx = CreateNewContextualCMutableTransaction(
511 Params().GetConsensus(), nextBlockHeight);
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.");
520 for (size_t idx = 0; idx < inputs.size(); idx++) {
521 const UniValue& input = inputs[idx];
522 const UniValue& o = input.get_obj();
524 uint256 txid = ParseHashO(o, "txid");
526 const UniValue& vout_v = find_value(o, "vout");
528 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
529 int nOutput = vout_v.get_int();
531 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
533 CTxIn in(COutPoint(txid, nOutput));
534 rawTx.vin.push_back(in);
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_);
544 if (setAddress.count(address))
545 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_);
546 setAddress.insert(address);
548 CScript scriptPubKey = GetScriptForDestination(address.Get());
549 CAmount nAmount = AmountFromValue(sendTo[name_]);
551 CTxOut out(nAmount, scriptPubKey);
552 rawTx.vout.push_back(out);
555 return EncodeHexTx(rawTx);
558 UniValue decoderawtransaction(const UniValue& params, bool fHelp)
560 if (fHelp || params.size() != 1)
562 "decoderawtransaction \"hexstring\"\n"
563 "\nReturn a JSON object representing the serialized, hex-encoded transaction.\n"
566 "1. \"hex\" (string, required) The transaction hex string\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"
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"
584 " \"sequence\": n (numeric) The script sequence number\n"
588 " \"vout\" : [ (array of json objects)\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"
605 " \"vjoinsplit\" : [ (array of json objects, only for version >= 2)\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"
614 " \"commitments\" : [ (json array of string)\n"
615 " \"hex\" (string) output note commitment\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"
624 " \"proof\" : \"hex\", (string) the zero-knowledge proof\n"
625 " \"ciphertexts\" : [ (json array of string)\n"
626 " \"hex\" (string) output note ciphertext\n"
635 + HelpExampleCli("decoderawtransaction", "\"hexstring\"")
636 + HelpExampleRpc("decoderawtransaction", "\"hexstring\"")
640 RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
644 if (!DecodeHexTx(tx, params[0].get_str()))
645 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
647 UniValue result(UniValue::VOBJ);
648 TxToJSON(tx, uint256(), result);
653 UniValue decodescript(const UniValue& params, bool fHelp)
655 if (fHelp || params.size() != 1)
657 "decodescript \"hex\"\n"
658 "\nDecode a hex-encoded script.\n"
660 "1. \"hex\" (string) the hex encoded script\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"
671 " \"p2sh\",\"address\" (string) script address\n"
674 + HelpExampleCli("decodescript", "\"hexstring\"")
675 + HelpExampleRpc("decodescript", "\"hexstring\"")
679 RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
681 UniValue r(UniValue::VOBJ);
683 if (params[0].get_str().size() > 0){
684 vector<unsigned char> scriptData(ParseHexV(params[0], "argument"));
685 script = CScript(scriptData.begin(), scriptData.end());
687 // Empty scripts are valid
689 ScriptPubKeyToJSON(script, r, false);
691 r.push_back(Pair("p2sh", CBitcoinAddress(CScriptID(script)).ToString()));
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)
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);
707 UniValue signrawtransaction(const UniValue& params, bool fHelp)
709 if (fHelp || params.size() < 1 || params.size() > 4)
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"
718 + HelpRequiringPassphrase() + "\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"
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"
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"
739 "4. \"sighashtype\" (string, optional, default=ALL) The signature hash type. Must be one of\n"
743 " \"ALL|ANYONECANPAY\"\n"
744 " \"NONE|ANYONECANPAY\"\n"
745 " \"SINGLE|ANYONECANPAY\"\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"
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"
764 + HelpExampleCli("signrawtransaction", "\"myhex\"")
765 + HelpExampleRpc("signrawtransaction", "\"myhex\"")
769 LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
773 RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VARR)(UniValue::VARR)(UniValue::VSTR), true);
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()) {
780 CMutableTransaction tx;
782 txVariants.push_back(tx);
784 catch (const std::exception&) {
785 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
789 if (txVariants.empty())
790 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transaction");
792 // mergedTx will end up with all the signatures; it
793 // starts as a clone of the rawtx:
794 CMutableTransaction mergedTx(txVariants[0]);
796 // Fetch previous transactions (inputs):
797 CCoinsView viewDummy;
798 CCoinsViewCache view(&viewDummy);
801 CCoinsViewCache &viewChain = *pcoinsTip;
802 CCoinsViewMemPool viewMempool(&viewChain, mempool);
803 view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
805 BOOST_FOREACH(const CTxIn& txin, mergedTx.vin) {
806 const uint256& prevHash = txin.prevout.hash;
808 view.AccessCoins(prevHash); // this is certainly allowed to fail
811 view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
814 bool fGivenKeys = false;
815 CBasicKeyStore tempKeystore;
816 if (params.size() > 2 && !params[2].isNull()) {
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());
824 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
825 CKey key = vchSecret.GetKey();
827 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
828 tempKeystore.AddKey(key);
832 else if (pwalletMain)
833 EnsureWalletIsUnlocked();
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];
842 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
844 UniValue prevOut = p.get_obj();
846 RPCTypeCheckObj(prevOut, boost::assign::map_list_of("txid", UniValue::VSTR)("vout", UniValue::VNUM)("scriptPubKey", UniValue::VSTR));
848 uint256 txid = ParseHashO(prevOut, "txid");
850 int nOut = find_value(prevOut, "vout").get_int();
852 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
854 vector<unsigned char> pkData(ParseHexO(prevOut, "scriptPubKey"));
855 CScript scriptPubKey(pkData.begin(), pkData.end());
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);
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"));
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");
880 vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
881 CScript redeemScript(rsData.begin(), rsData.end());
882 tempKeystore.AddCScript(redeemScript);
889 const CKeyStore& keystore = ((fGivenKeys || !pwalletMain) ? tempKeystore : *pwalletMain);
891 const CKeyStore& keystore = tempKeystore;
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))
905 string strHashType = params[3].get_str();
906 if (mapSigHashValues.count(strHashType))
907 nHashType = mapSigHashValues[strHashType];
909 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param");
912 bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
914 // Grab the current consensus branch ID
915 auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
917 // Script verification errors
918 UniValue vErrors(UniValue::VARR);
920 // Use CTransaction for the constant parts of the
921 // transaction to avoid rehashing.
922 const CTransaction txConst(mergedTx);
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");
931 const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
932 const CAmount& amount = coins->vout[txin.prevout.n].nValue;
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);
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);
944 UpdateTransaction(mergedTx, i, sigdata);
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));
951 bool fComplete = vErrors.empty();
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));
963 UniValue sendrawtransaction(const UniValue& params, bool fHelp)
965 if (fHelp || params.size() < 1 || params.size() > 2)
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"
971 "1. \"hexstring\" (string, required) The hex string of the raw transaction)\n"
972 "2. allowhighfees (boolean, optional, default=false) Allow high fees\n"
974 "\"hex\" (string) The transaction hash in hex\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\"")
987 RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL));
989 // parse hex string from parameter
991 if (!DecodeHexTx(tx, params[0].get_str()))
992 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
993 uint256 hashTx = tx.GetHash();
995 bool fOverrideFees = false;
996 if (params.size() > 1)
997 fOverrideFees = params[1].get_bool();
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()));
1011 if (fMissingInputs) {
1012 throw JSONRPCError(RPC_TRANSACTION_ERROR, "Missing inputs");
1014 throw JSONRPCError(RPC_TRANSACTION_ERROR, state.GetRejectReason());
1017 } else if (fHaveChain) {
1018 throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
1020 RelayTransaction(tx);
1022 return hashTx.GetHex();