]>
Commit | Line | Data |
---|---|---|
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 | 31 | using namespace std; |
a2709fad | 32 | |
d014114d | 33 | void 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 |
58 | UniValue 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 | 113 | void 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 | 168 | UniValue 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 | 285 | UniValue 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 | 366 | UniValue 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 | 399 | UniValue 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 | 478 | UniValue 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 | 570 | UniValue 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 | 613 | static 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 | 624 | UniValue 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 | 866 | UniValue 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 | } |