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