]> Git Repo - VerusCoin.git/blame - src/rpcrawtransaction.cpp
Merge pull request #4982
[VerusCoin.git] / src / rpcrawtransaction.cpp
CommitLineData
a2709fad 1// Copyright (c) 2010 Satoshi Nakamoto
57702541 2// Copyright (c) 2009-2014 The Bitcoin developers
a2709fad
GA
3// Distributed under the MIT/X11 software license, see the accompanying
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
a2709fad 6#include "base58.h"
c037531d 7#include "core.h"
ae775b5b 8#include "core_io.h"
a2709fad 9#include "init.h"
c037531d
PK
10#include "keystore.h"
11#include "main.h"
771ffb5e 12#include "net.h"
c037531d 13#include "rpcserver.h"
c4408a6c 14#include "script/script.h"
e088d65a 15#include "script/sign.h"
611116d4 16#include "script/standard.h"
51ed9ec9 17#include "uint256.h"
48ba56cd 18#ifdef ENABLE_WALLET
a2709fad 19#include "wallet.h"
48ba56cd 20#endif
a2709fad 21
51ed9ec9
BD
22#include <stdint.h>
23
24#include <boost/assign/list_of.hpp>
25#include "json/json_spirit_utils.h"
26#include "json/json_spirit_value.h"
27
a2709fad
GA
28using namespace boost;
29using namespace boost::assign;
30using namespace json_spirit;
611116d4 31using namespace std;
a2709fad 32
be066fad 33void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex)
a2709fad
GA
34{
35 txnouttype type;
36 vector<CTxDestination> addresses;
37 int nRequired;
38
39 out.push_back(Pair("asm", scriptPubKey.ToString()));
be066fad
PT
40 if (fIncludeHex)
41 out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
a2709fad 42
3ce7e669 43 if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) {
22de68df 44 out.push_back(Pair("type", GetTxnOutputType(type)));
a2709fad
GA
45 return;
46 }
47
48 out.push_back(Pair("reqSigs", nRequired));
49 out.push_back(Pair("type", GetTxnOutputType(type)));
50
51 Array a;
52 BOOST_FOREACH(const CTxDestination& addr, addresses)
53 a.push_back(CBitcoinAddress(addr).ToString());
54 out.push_back(Pair("addresses", a));
55}
56
bdab0cf5 57void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
a2709fad
GA
58{
59 entry.push_back(Pair("txid", tx.GetHash().GetHex()));
60 entry.push_back(Pair("version", tx.nVersion));
4b61a6a4 61 entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
a2709fad 62 Array vin;
3ce7e669 63 BOOST_FOREACH(const CTxIn& txin, tx.vin) {
a2709fad
GA
64 Object in;
65 if (tx.IsCoinBase())
66 in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
3ce7e669 67 else {
a2709fad 68 in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
4b61a6a4 69 in.push_back(Pair("vout", (int64_t)txin.prevout.n));
a2709fad
GA
70 Object o;
71 o.push_back(Pair("asm", txin.scriptSig.ToString()));
72 o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
73 in.push_back(Pair("scriptSig", o));
74 }
4b61a6a4 75 in.push_back(Pair("sequence", (int64_t)txin.nSequence));
a2709fad
GA
76 vin.push_back(in);
77 }
78 entry.push_back(Pair("vin", vin));
79 Array vout;
3ce7e669 80 for (unsigned int i = 0; i < tx.vout.size(); i++) {
a2709fad
GA
81 const CTxOut& txout = tx.vout[i];
82 Object out;
83 out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
4b61a6a4 84 out.push_back(Pair("n", (int64_t)i));
a2709fad 85 Object o;
a702a0b6 86 ScriptPubKeyToJSON(txout.scriptPubKey, o, true);
a2709fad
GA
87 out.push_back(Pair("scriptPubKey", o));
88 vout.push_back(out);
89 }
90 entry.push_back(Pair("vout", vout));
91
3ce7e669 92 if (hashBlock != 0) {
a2709fad 93 entry.push_back(Pair("blockhash", hashBlock.GetHex()));
145d5be8 94 BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
3ce7e669 95 if (mi != mapBlockIndex.end() && (*mi).second) {
a2709fad 96 CBlockIndex* pindex = (*mi).second;
3ce7e669 97 if (chainActive.Contains(pindex)) {
4c6d41b8 98 entry.push_back(Pair("confirmations", 1 + chainActive.Height() - pindex->nHeight));
209377a7 99 entry.push_back(Pair("time", pindex->GetBlockTime()));
100 entry.push_back(Pair("blocktime", pindex->GetBlockTime()));
a2709fad
GA
101 }
102 else
103 entry.push_back(Pair("confirmations", 0));
104 }
105 }
106}
107
108Value getrawtransaction(const Array& params, bool fHelp)
109{
110 if (fHelp || params.size() < 1 || params.size() > 2)
111 throw runtime_error(
a6099ef3 112 "getrawtransaction \"txid\" ( verbose )\n"
113 "\nReturn the raw transaction data.\n"
114 "\nIf verbose=0, returns a string that is serialized, hex-encoded data for 'txid'.\n"
115 "If verbose is non-zero, returns an Object with information about 'txid'.\n"
116
117 "\nArguments:\n"
118 "1. \"txid\" (string, required) The transaction id\n"
119 "2. verbose (numeric, optional, default=0) If 0, return a string, other return a json object\n"
120
121 "\nResult (if verbose is not set or set to 0):\n"
122 "\"data\" (string) The serialized, hex-encoded data for 'txid'\n"
123
124 "\nResult (if verbose > 0):\n"
125 "{\n"
126 " \"hex\" : \"data\", (string) The serialized, hex-encoded data for 'txid'\n"
127 " \"txid\" : \"id\", (string) The transaction id (same as provided)\n"
128 " \"version\" : n, (numeric) The version\n"
129 " \"locktime\" : ttt, (numeric) The lock time\n"
130 " \"vin\" : [ (array of json objects)\n"
131 " {\n"
132 " \"txid\": \"id\", (string) The transaction id\n"
133 " \"vout\": n, (numeric) \n"
134 " \"scriptSig\": { (json object) The script\n"
135 " \"asm\": \"asm\", (string) asm\n"
136 " \"hex\": \"hex\" (string) hex\n"
137 " },\n"
138 " \"sequence\": n (numeric) The script sequence number\n"
139 " }\n"
140 " ,...\n"
141 " ],\n"
142 " \"vout\" : [ (array of json objects)\n"
143 " {\n"
144 " \"value\" : x.xxx, (numeric) The value in btc\n"
145 " \"n\" : n, (numeric) index\n"
146 " \"scriptPubKey\" : { (json object)\n"
147 " \"asm\" : \"asm\", (string) the asm\n"
148 " \"hex\" : \"hex\", (string) the hex\n"
149 " \"reqSigs\" : n, (numeric) The required sigs\n"
150 " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
151 " \"addresses\" : [ (json array of string)\n"
152 " \"bitcoinaddress\" (string) bitcoin address\n"
153 " ,...\n"
154 " ]\n"
155 " }\n"
156 " }\n"
157 " ,...\n"
158 " ],\n"
159 " \"blockhash\" : \"hash\", (string) the block hash\n"
160 " \"confirmations\" : n, (numeric) The confirmations\n"
161 " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT)\n"
162 " \"blocktime\" : ttt (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
163 "}\n"
164
165 "\nExamples:\n"
166 + HelpExampleCli("getrawtransaction", "\"mytxid\"")
167 + HelpExampleCli("getrawtransaction", "\"mytxid\" 1")
168 + HelpExampleRpc("getrawtransaction", "\"mytxid\", 1")
169 );
a2709fad 170
2d43f88e 171 uint256 hash = ParseHashV(params[0], "parameter 1");
a2709fad
GA
172
173 bool fVerbose = false;
174 if (params.size() > 1)
175 fVerbose = (params[1].get_int() != 0);
176
177 CTransaction tx;
178 uint256 hashBlock = 0;
450cbb09 179 if (!GetTransaction(hash, tx, hashBlock, true))
738835d7 180 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
a2709fad 181
ae775b5b 182 string strHex = EncodeHexTx(tx);
a2709fad
GA
183
184 if (!fVerbose)
185 return strHex;
186
187 Object result;
188 result.push_back(Pair("hex", strHex));
189 TxToJSON(tx, hashBlock, result);
190 return result;
191}
192
48ba56cd 193#ifdef ENABLE_WALLET
a2709fad
GA
194Value listunspent(const Array& params, bool fHelp)
195{
92735bca 196 if (fHelp || params.size() > 3)
a2709fad 197 throw runtime_error(
a6099ef3 198 "listunspent ( minconf maxconf [\"address\",...] )\n"
199 "\nReturns array of unspent transaction outputs\n"
a2709fad 200 "with between minconf and maxconf (inclusive) confirmations.\n"
a6099ef3 201 "Optionally filter to only include txouts paid to specified addresses.\n"
a2709fad 202 "Results are an array of Objects, each of which has:\n"
a6099ef3 203 "{txid, vout, scriptPubKey, amount, confirmations}\n"
204 "\nArguments:\n"
205 "1. minconf (numeric, optional, default=1) The minimum confirmationsi to filter\n"
206 "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n"
207 "3. \"addresses\" (string) A json array of bitcoin addresses to filter\n"
208 " [\n"
209 " \"address\" (string) bitcoin address\n"
210 " ,...\n"
211 " ]\n"
212 "\nResult\n"
213 "[ (array of json object)\n"
214 " {\n"
215 " \"txid\" : \"txid\", (string) the transaction id \n"
216 " \"vout\" : n, (numeric) the vout value\n"
217 " \"address\" : \"address\", (string) the bitcoin address\n"
218 " \"account\" : \"account\", (string) The associated account, or \"\" for the default account\n"
219 " \"scriptPubKey\" : \"key\", (string) the script key\n"
220 " \"amount\" : x.xxx, (numeric) the transaction amount in btc\n"
221 " \"confirmations\" : n (numeric) The number of confirmations\n"
222 " }\n"
223 " ,...\n"
224 "]\n"
225
226 "\nExamples\n"
227 + HelpExampleCli("listunspent", "")
228 + HelpExampleCli("listunspent", "6 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
229 + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
230 );
a2709fad 231
92735bca 232 RPCTypeCheck(params, list_of(int_type)(int_type)(array_type));
a2709fad
GA
233
234 int nMinDepth = 1;
235 if (params.size() > 0)
236 nMinDepth = params[0].get_int();
237
92735bca 238 int nMaxDepth = 9999999;
a2709fad
GA
239 if (params.size() > 1)
240 nMaxDepth = params[1].get_int();
241
92735bca 242 set<CBitcoinAddress> setAddress;
3ce7e669 243 if (params.size() > 2) {
92735bca 244 Array inputs = params[2].get_array();
3ce7e669 245 BOOST_FOREACH(Value& input, inputs) {
92735bca
GM
246 CBitcoinAddress address(input.get_str());
247 if (!address.IsValid())
738835d7 248 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+input.get_str());
92735bca 249 if (setAddress.count(address))
738835d7 250 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str());
92735bca
GM
251 setAddress.insert(address);
252 }
253 }
254
a2709fad
GA
255 Array results;
256 vector<COutput> vecOutputs;
b0730874 257 assert(pwalletMain != NULL);
a2709fad 258 pwalletMain->AvailableCoins(vecOutputs, false);
3ce7e669 259 BOOST_FOREACH(const COutput& out, vecOutputs) {
a2709fad
GA
260 if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
261 continue;
262
3ce7e669 263 if (setAddress.size()) {
b1093efa 264 CTxDestination address;
2d43f88e 265 if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
b1093efa
GM
266 continue;
267
268 if (!setAddress.count(address))
269 continue;
270 }
92735bca 271
a372168e 272 CAmount nValue = out.tx->vout[out.i].nValue;
a2709fad
GA
273 const CScript& pk = out.tx->vout[out.i].scriptPubKey;
274 Object entry;
275 entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
276 entry.push_back(Pair("vout", out.i));
550479b0 277 CTxDestination address;
3ce7e669 278 if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
550479b0 279 entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
280 if (pwalletMain->mapAddressBook.count(address))
61885513 281 entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name));
550479b0 282 }
a2709fad 283 entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end())));
3ce7e669 284 if (pk.IsPayToScriptHash()) {
03346a61 285 CTxDestination address;
3ce7e669 286 if (ExtractDestination(pk, address)) {
03346a61
GA
287 const CScriptID& hash = boost::get<const CScriptID&>(address);
288 CScript redeemScript;
289 if (pwalletMain->GetCScript(hash, redeemScript))
290 entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
291 }
292 }
a2709fad
GA
293 entry.push_back(Pair("amount",ValueFromAmount(nValue)));
294 entry.push_back(Pair("confirmations",out.nDepth));
c8988460 295 entry.push_back(Pair("spendable", out.fSpendable));
a2709fad
GA
296 results.push_back(entry);
297 }
298
299 return results;
300}
48ba56cd 301#endif
a2709fad
GA
302
303Value createrawtransaction(const Array& params, bool fHelp)
304{
305 if (fHelp || params.size() != 2)
306 throw runtime_error(
a6099ef3 307 "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,...}\n"
308 "\nCreate a transaction spending the given inputs and sending to the given addresses.\n"
a2709fad
GA
309 "Returns hex-encoded raw transaction.\n"
310 "Note that the transaction's inputs are not signed, and\n"
a6099ef3 311 "it is not stored in the wallet or transmitted to the network.\n"
312
313 "\nArguments:\n"
314 "1. \"transactions\" (string, required) A json array of json objects\n"
315 " [\n"
316 " {\n"
317 " \"txid\":\"id\", (string, required) The transaction id\n"
318 " \"vout\":n (numeric, required) The output number\n"
319 " }\n"
320 " ,...\n"
321 " ]\n"
322 "2. \"addresses\" (string, required) a json object with addresses as keys and amounts as values\n"
323 " {\n"
324 " \"address\": x.xxx (numeric, required) The key is the bitcoin address, the value is the btc amount\n"
325 " ,...\n"
326 " }\n"
327
328 "\nResult:\n"
329 "\"transaction\" (string) hex string of the transaction\n"
330
331 "\nExamples\n"
332 + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"{\\\"address\\\":0.01}\"")
333 + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"address\\\":0.01}\"")
334 );
a2709fad
GA
335
336 RPCTypeCheck(params, list_of(array_type)(obj_type));
337
338 Array inputs = params[0].get_array();
339 Object sendTo = params[1].get_obj();
340
4949004d 341 CMutableTransaction rawTx;
a2709fad 342
3ce7e669 343 BOOST_FOREACH(const Value& input, inputs) {
a2709fad
GA
344 const Object& o = input.get_obj();
345
2d43f88e 346 uint256 txid = ParseHashO(o, "txid");
a2709fad
GA
347
348 const Value& vout_v = find_value(o, "vout");
349 if (vout_v.type() != int_type)
738835d7 350 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
a2709fad
GA
351 int nOutput = vout_v.get_int();
352 if (nOutput < 0)
738835d7 353 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
a2709fad 354
2d43f88e 355 CTxIn in(COutPoint(txid, nOutput));
a2709fad
GA
356 rawTx.vin.push_back(in);
357 }
358
359 set<CBitcoinAddress> setAddress;
3ce7e669 360 BOOST_FOREACH(const Pair& s, sendTo) {
a2709fad
GA
361 CBitcoinAddress address(s.name_);
362 if (!address.IsValid())
738835d7 363 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
a2709fad
GA
364
365 if (setAddress.count(address))
738835d7 366 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
a2709fad
GA
367 setAddress.insert(address);
368
0be990ba 369 CScript scriptPubKey = GetScriptForDestination(address.Get());
a372168e 370 CAmount nAmount = AmountFromValue(s.value_);
a2709fad
GA
371
372 CTxOut out(nAmount, scriptPubKey);
373 rawTx.vout.push_back(out);
374 }
375
ae775b5b 376 return EncodeHexTx(rawTx);
a2709fad
GA
377}
378
379Value decoderawtransaction(const Array& params, bool fHelp)
380{
381 if (fHelp || params.size() != 1)
382 throw runtime_error(
a6099ef3 383 "decoderawtransaction \"hexstring\"\n"
384 "\nReturn a JSON object representing the serialized, hex-encoded transaction.\n"
385
386 "\nArguments:\n"
e0c06d2c 387 "1. \"hex\" (string, required) The transaction hex string\n"
a6099ef3 388
389 "\nResult:\n"
390 "{\n"
e0c06d2c 391 " \"txid\" : \"id\", (string) The transaction id\n"
a6099ef3 392 " \"version\" : n, (numeric) The version\n"
393 " \"locktime\" : ttt, (numeric) The lock time\n"
394 " \"vin\" : [ (array of json objects)\n"
395 " {\n"
396 " \"txid\": \"id\", (string) The transaction id\n"
397 " \"vout\": n, (numeric) The output number\n"
398 " \"scriptSig\": { (json object) The script\n"
399 " \"asm\": \"asm\", (string) asm\n"
400 " \"hex\": \"hex\" (string) hex\n"
401 " },\n"
402 " \"sequence\": n (numeric) The script sequence number\n"
403 " }\n"
404 " ,...\n"
405 " ],\n"
406 " \"vout\" : [ (array of json objects)\n"
407 " {\n"
408 " \"value\" : x.xxx, (numeric) The value in btc\n"
409 " \"n\" : n, (numeric) index\n"
410 " \"scriptPubKey\" : { (json object)\n"
411 " \"asm\" : \"asm\", (string) the asm\n"
412 " \"hex\" : \"hex\", (string) the hex\n"
413 " \"reqSigs\" : n, (numeric) The required sigs\n"
414 " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
415 " \"addresses\" : [ (json array of string)\n"
416 " \"12tvKAXCxZjSmdNbao16dKXC8tRWfcF5oc\" (string) bitcoin address\n"
417 " ,...\n"
418 " ]\n"
419 " }\n"
420 " }\n"
421 " ,...\n"
422 " ],\n"
a6099ef3 423 "}\n"
424
425 "\nExamples:\n"
426 + HelpExampleCli("decoderawtransaction", "\"hexstring\"")
427 + HelpExampleRpc("decoderawtransaction", "\"hexstring\"")
428 );
a2709fad 429
ae775b5b
JG
430 RPCTypeCheck(params, list_of(str_type));
431
a2709fad 432 CTransaction tx;
ae775b5b
JG
433
434 if (!DecodeHexTx(tx, params[0].get_str()))
738835d7 435 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
a2709fad
GA
436
437 Object result;
438 TxToJSON(tx, 0, result);
439
440 return result;
441}
442
be066fad
PT
443Value decodescript(const Array& params, bool fHelp)
444{
445 if (fHelp || params.size() != 1)
446 throw runtime_error(
a6099ef3 447 "decodescript \"hex\"\n"
448 "\nDecode a hex-encoded script.\n"
449 "\nArguments:\n"
450 "1. \"hex\" (string) the hex encoded script\n"
451 "\nResult:\n"
452 "{\n"
453 " \"asm\":\"asm\", (string) Script public key\n"
454 " \"hex\":\"hex\", (string) hex encoded public key\n"
455 " \"type\":\"type\", (string) The output type\n"
456 " \"reqSigs\": n, (numeric) The required signatures\n"
457 " \"addresses\": [ (json array of string)\n"
458 " \"address\" (string) bitcoin address\n"
459 " ,...\n"
460 " ],\n"
461 " \"p2sh\",\"address\" (string) script address\n"
462 "}\n"
463 "\nExamples:\n"
464 + HelpExampleCli("decodescript", "\"hexstring\"")
465 + HelpExampleRpc("decodescript", "\"hexstring\"")
466 );
be066fad
PT
467
468 RPCTypeCheck(params, list_of(str_type));
469
470 Object r;
471 CScript script;
472 if (params[0].get_str().size() > 0){
473 vector<unsigned char> scriptData(ParseHexV(params[0], "argument"));
474 script = CScript(scriptData.begin(), scriptData.end());
475 } else {
476 // Empty scripts are valid
477 }
478 ScriptPubKeyToJSON(script, r, false);
479
480 r.push_back(Pair("p2sh", CBitcoinAddress(script.GetID()).ToString()));
481 return r;
482}
483
a2709fad
GA
484Value signrawtransaction(const Array& params, bool fHelp)
485{
3c3666d6 486 if (fHelp || params.size() < 1 || params.size() > 4)
a2709fad 487 throw runtime_error(
a6099ef3 488 "signrawtransaction \"hexstring\" ( [{\"txid\":\"id\",\"vout\":n,\"scriptPubKey\":\"hex\",\"redeemScript\":\"hex\"},...] [\"privatekey1\",...] sighashtype )\n"
489 "\nSign inputs for raw transaction (serialized, hex-encoded).\n"
490 "The second optional argument (may be null) is an array of previous transaction outputs that\n"
729b1806 491 "this transaction depends on but may not yet be in the block chain.\n"
a6099ef3 492 "The third optional argument (may be null) is an array of base58-encoded private\n"
a2709fad 493 "keys that, if given, will be the only keys used to sign the transaction.\n"
48ba56cd 494#ifdef ENABLE_WALLET
a6099ef3 495 + HelpRequiringPassphrase() + "\n"
48ba56cd 496#endif
a6099ef3 497
498 "\nArguments:\n"
499 "1. \"hexstring\" (string, required) The transaction hex string\n"
500 "2. \"prevtxs\" (string, optional) An json array of previous dependent transaction outputs\n"
041f71bb 501 " [ (json array of json objects, or 'null' if none provided)\n"
a6099ef3 502 " {\n"
503 " \"txid\":\"id\", (string, required) The transaction id\n"
504 " \"vout\":n, (numeric, required) The output number\n"
505 " \"scriptPubKey\": \"hex\", (string, required) script key\n"
6265ecc8 506 " \"redeemScript\": \"hex\" (string, required for P2SH) redeem script\n"
a6099ef3 507 " }\n"
508 " ,...\n"
509 " ]\n"
510 "3. \"privatekeys\" (string, optional) A json array of base58-encoded private keys for signing\n"
041f71bb 511 " [ (json array of strings, or 'null' if none provided)\n"
a6099ef3 512 " \"privatekey\" (string) private key in base58-encoding\n"
513 " ,...\n"
514 " ]\n"
ab643811 515 "4. \"sighashtype\" (string, optional, default=ALL) The signature hash type. Must be one of\n"
a6099ef3 516 " \"ALL\"\n"
517 " \"NONE\"\n"
518 " \"SINGLE\"\n"
519 " \"ALL|ANYONECANPAY\"\n"
520 " \"NONE|ANYONECANPAY\"\n"
521 " \"SINGLE|ANYONECANPAY\"\n"
522
523 "\nResult:\n"
524 "{\n"
525 " \"hex\": \"value\", (string) The raw transaction with signature(s) (hex-encoded string)\n"
526 " \"complete\": n (numeric) if transaction has a complete set of signature (0 if not)\n"
527 "}\n"
528
529 "\nExamples:\n"
530 + HelpExampleCli("signrawtransaction", "\"myhex\"")
531 + HelpExampleRpc("signrawtransaction", "\"myhex\"")
532 );
a2709fad 533
cc6dfd1f 534 RPCTypeCheck(params, list_of(str_type)(array_type)(array_type)(str_type), true);
a2709fad 535
2d43f88e 536 vector<unsigned char> txData(ParseHexV(params[0], "argument 1"));
a2709fad 537 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
4949004d 538 vector<CMutableTransaction> txVariants;
3ce7e669 539 while (!ssData.empty()) {
a2709fad 540 try {
4949004d 541 CMutableTransaction tx;
a2709fad
GA
542 ssData >> tx;
543 txVariants.push_back(tx);
544 }
ec91092d 545 catch (const std::exception &) {
738835d7 546 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
a2709fad
GA
547 }
548 }
549
550 if (txVariants.empty())
738835d7 551 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transaction");
a2709fad
GA
552
553 // mergedTx will end up with all the signatures; it
554 // starts as a clone of the rawtx:
4949004d 555 CMutableTransaction mergedTx(txVariants[0]);
a2709fad
GA
556 bool fComplete = true;
557
558 // Fetch previous transactions (inputs):
450cbb09
PW
559 CCoinsView viewDummy;
560 CCoinsViewCache view(viewDummy);
a2709fad 561 {
450cbb09 562 LOCK(mempool.cs);
ae8bfd12
PW
563 CCoinsViewCache &viewChain = *pcoinsTip;
564 CCoinsViewMemPool viewMempool(viewChain, mempool);
450cbb09
PW
565 view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
566
567 BOOST_FOREACH(const CTxIn& txin, mergedTx.vin) {
a2709fad 568 const uint256& prevHash = txin.prevout.hash;
450cbb09 569 CCoins coins;
629d75fa 570 view.AccessCoins(prevHash); // this is certainly allowed to fail
a2709fad 571 }
450cbb09 572
ae8bfd12 573 view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
a2709fad
GA
574 }
575
03346a61
GA
576 bool fGivenKeys = false;
577 CBasicKeyStore tempKeystore;
3ce7e669 578 if (params.size() > 2 && params[2].type() != null_type) {
03346a61
GA
579 fGivenKeys = true;
580 Array keys = params[2].get_array();
3ce7e669 581 BOOST_FOREACH(Value k, keys) {
03346a61
GA
582 CBitcoinSecret vchSecret;
583 bool fGood = vchSecret.SetString(k.get_str());
584 if (!fGood)
585 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
dfa23b94 586 CKey key = vchSecret.GetKey();
03346a61
GA
587 tempKeystore.AddKey(key);
588 }
589 }
48ba56cd 590#ifdef ENABLE_WALLET
03346a61
GA
591 else
592 EnsureWalletIsUnlocked();
48ba56cd 593#endif
03346a61 594
a2709fad 595 // Add previous txouts given in the RPC call:
3ce7e669 596 if (params.size() > 1 && params[1].type() != null_type) {
a2709fad 597 Array prevTxs = params[1].get_array();
3ce7e669 598 BOOST_FOREACH(Value& p, prevTxs) {
a2709fad 599 if (p.type() != obj_type)
738835d7 600 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
a2709fad
GA
601
602 Object prevOut = p.get_obj();
603
21c6d3ae 604 RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type));
a2709fad 605
2d43f88e 606 uint256 txid = ParseHashO(prevOut, "txid");
a2709fad
GA
607
608 int nOut = find_value(prevOut, "vout").get_int();
609 if (nOut < 0)
738835d7 610 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
a2709fad 611
2d43f88e 612 vector<unsigned char> pkData(ParseHexO(prevOut, "scriptPubKey"));
a2709fad
GA
613 CScript scriptPubKey(pkData.begin(), pkData.end());
614
450cbb09
PW
615 CCoins coins;
616 if (view.GetCoins(txid, coins)) {
617 if (coins.IsAvailable(nOut) && coins.vout[nOut].scriptPubKey != scriptPubKey) {
a2709fad 618 string err("Previous output scriptPubKey mismatch:\n");
450cbb09 619 err = err + coins.vout[nOut].scriptPubKey.ToString() + "\nvs:\n"+
a2709fad 620 scriptPubKey.ToString();
738835d7 621 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
a2709fad 622 }
450cbb09 623 // what todo if txid is known, but the actual output isn't?
a2709fad 624 }
03346a61
GA
625 if ((unsigned int)nOut >= coins.vout.size())
626 coins.vout.resize(nOut+1);
450cbb09
PW
627 coins.vout[nOut].scriptPubKey = scriptPubKey;
628 coins.vout[nOut].nValue = 0; // we don't know the actual output value
629 view.SetCoins(txid, coins);
a2709fad 630
03346a61
GA
631 // if redeemScript given and not using the local wallet (private keys
632 // given), add redeemScript to the tempKeystore so it can be signed:
3ce7e669 633 if (fGivenKeys && scriptPubKey.IsPayToScriptHash()) {
21c6d3ae
GM
634 RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type)("redeemScript",str_type));
635 Value v = find_value(prevOut, "redeemScript");
3ce7e669 636 if (!(v == Value::null)) {
21c6d3ae
GM
637 vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
638 CScript redeemScript(rsData.begin(), rsData.end());
639 tempKeystore.AddCScript(redeemScript);
640 }
03346a61 641 }
a2709fad
GA
642 }
643 }
cc6dfd1f 644
48ba56cd 645#ifdef ENABLE_WALLET
b0730874 646 const CKeyStore& keystore = ((fGivenKeys || !pwalletMain) ? tempKeystore : *pwalletMain);
48ba56cd
WL
647#else
648 const CKeyStore& keystore = tempKeystore;
649#endif
a2709fad 650
3c3666d6 651 int nHashType = SIGHASH_ALL;
3ce7e669 652 if (params.size() > 3 && params[3].type() != null_type) {
3c3666d6
GA
653 static map<string, int> mapSigHashValues =
654 boost::assign::map_list_of
655 (string("ALL"), int(SIGHASH_ALL))
656 (string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY))
657 (string("NONE"), int(SIGHASH_NONE))
658 (string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY))
659 (string("SINGLE"), int(SIGHASH_SINGLE))
660 (string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY))
661 ;
662 string strHashType = params[3].get_str();
663 if (mapSigHashValues.count(strHashType))
664 nHashType = mapSigHashValues[strHashType];
665 else
738835d7 666 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param");
3c3666d6
GA
667 }
668
d5e7b611
GA
669 bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
670
a2709fad 671 // Sign what we can:
3ce7e669 672 for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
a2709fad 673 CTxIn& txin = mergedTx.vin[i];
629d75fa
PW
674 const CCoins* coins = view.AccessCoins(txin.prevout.hash);
675 if (coins == NULL || !coins->IsAvailable(txin.prevout.n)) {
a2709fad
GA
676 fComplete = false;
677 continue;
678 }
629d75fa 679 const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
a2709fad
GA
680
681 txin.scriptSig.clear();
d5e7b611
GA
682 // Only sign SIGHASH_SINGLE if there's a corresponding output:
683 if (!fHashSingle || (i < mergedTx.vout.size()))
684 SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
a2709fad
GA
685
686 // ... and merge in other signatures:
3ce7e669 687 BOOST_FOREACH(const CMutableTransaction& txv, txVariants) {
a2709fad
GA
688 txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
689 }
2b23a875 690 if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, STANDARD_SCRIPT_VERIFY_FLAGS))
a2709fad
GA
691 fComplete = false;
692 }
693
694 Object result;
ae775b5b 695 result.push_back(Pair("hex", EncodeHexTx(mergedTx)));
a2709fad
GA
696 result.push_back(Pair("complete", fComplete));
697
698 return result;
699}
700
701Value sendrawtransaction(const Array& params, bool fHelp)
702{
9d14e689 703 if (fHelp || params.size() < 1 || params.size() > 2)
a2709fad 704 throw runtime_error(
a6099ef3 705 "sendrawtransaction \"hexstring\" ( allowhighfees )\n"
706 "\nSubmits raw transaction (serialized, hex-encoded) to local node and network.\n"
707 "\nAlso see createrawtransaction and signrawtransaction calls.\n"
708 "\nArguments:\n"
709 "1. \"hexstring\" (string, required) The hex string of the raw transaction)\n"
710 "2. allowhighfees (boolean, optional, default=false) Allow high fees\n"
711 "\nResult:\n"
712 "\"hex\" (string) The transaction hash in hex\n"
713 "\nExamples:\n"
714 "\nCreate a transaction\n"
715 + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") +
716 "Sign the transaction, and get back the hex\n"
717 + HelpExampleCli("signrawtransaction", "\"myhex\"") +
718 "\nSend the transaction (signed hex)\n"
719 + HelpExampleCli("sendrawtransaction", "\"signedhex\"") +
720 "\nAs a json rpc call\n"
721 + HelpExampleRpc("sendrawtransaction", "\"signedhex\"")
722 );
723
ae775b5b 724 RPCTypeCheck(params, list_of(str_type)(bool_type));
a2709fad 725
a2709fad 726 // parse hex string from parameter
a2709fad 727 CTransaction tx;
ae775b5b
JG
728 if (!DecodeHexTx(tx, params[0].get_str()))
729 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
730 uint256 hashTx = tx.GetHash();
a2709fad 731
9d14e689
GM
732 bool fOverrideFees = false;
733 if (params.size() > 1)
734 fOverrideFees = params[1].get_bool();
735
ae8bfd12 736 CCoinsViewCache &view = *pcoinsTip;
629d75fa 737 const CCoins* existingCoins = view.AccessCoins(hashTx);
1d46fe33 738 bool fHaveMempool = mempool.exists(hashTx);
629d75fa 739 bool fHaveChain = existingCoins && existingCoins->nHeight < 1000000000;
1d46fe33
WL
740 if (!fHaveMempool && !fHaveChain) {
741 // push to local node and sync with wallets
742 CValidationState state;
0d27dad8 743 if (!AcceptToMemoryPool(mempool, state, tx, false, NULL, !fOverrideFees)) {
1d46fe33
WL
744 if(state.IsInvalid())
745 throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
746 else
747 throw JSONRPCError(RPC_TRANSACTION_ERROR, state.GetRejectReason());
450cbb09 748 }
1d46fe33
WL
749 } else if (fHaveChain) {
750 throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
771ffb5e 751 }
d38da59b 752 RelayTransaction(tx);
a2709fad 753
771ffb5e 754 return hashTx.GetHex();
a2709fad 755}
This page took 0.232073 seconds and 4 git commands to generate.