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