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