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