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