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