Move signature verification functions to CPubKey.
[novacoin.git] / src / rpcrawtransaction.cpp
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include <boost/assign/list_of.hpp>
7
8 #include "base58.h"
9 #include "bitcoinrpc.h"
10 #include "txdb.h"
11 #include "init.h"
12 #include "main.h"
13 #include "net.h"
14 #include "wallet.h"
15
16 using namespace std;
17 using namespace boost;
18 using namespace boost::assign;
19 using namespace json_spirit;
20
21 void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex)
22 {
23     txnouttype type;
24     vector<CTxDestination> addresses;
25     int nRequired;
26
27     out.push_back(Pair("asm", scriptPubKey.ToString()));
28
29     if (fIncludeHex)
30         out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
31
32     if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired))
33     {
34         out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD)));
35         return;
36     }
37
38     if (type != TX_NULL_DATA)
39     {
40         out.push_back(Pair("reqSigs", nRequired));
41         out.push_back(Pair("type", GetTxnOutputType(type)));
42
43         if (type == TX_PUBKEY_DROP)
44         {
45             vector<valtype> vSolutions;
46             Solver(scriptPubKey, type, vSolutions);
47             out.push_back(Pair("keyVariant", HexStr(vSolutions[0])));
48             out.push_back(Pair("R", HexStr(vSolutions[1])));
49
50             CMalleableKeyView view;
51             if (pwalletMain->CheckOwnership(CPubKey(vSolutions[0]), CPubKey(vSolutions[1]), view))
52                 out.push_back(Pair("pubkeyPair", CBitcoinAddress(view.GetMalleablePubKey()).ToString()));
53         }
54         else
55         {
56             Array a;
57             BOOST_FOREACH(const CTxDestination& addr, addresses)
58                 a.push_back(CBitcoinAddress(addr).ToString());
59             out.push_back(Pair("addresses", a));
60         }
61     }
62     else
63     {
64         out.push_back(Pair("type", GetTxnOutputType(type)));
65     }
66 }
67
68 void TxToJSON(const CTransaction& tx, const uint256& hashBlock, Object& entry)
69 {
70     entry.push_back(Pair("txid", tx.GetHash().GetHex()));
71     entry.push_back(Pair("version", tx.nVersion));
72     entry.push_back(Pair("time", (int64_t)tx.nTime));
73     entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
74     Array vin;
75     BOOST_FOREACH(const CTxIn& txin, tx.vin)
76     {
77         Object in;
78         if (tx.IsCoinBase())
79             in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
80         else
81         {
82             in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
83             in.push_back(Pair("vout", (int64_t)txin.prevout.n));
84             Object o;
85             o.push_back(Pair("asm", txin.scriptSig.ToString()));
86             o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
87             in.push_back(Pair("scriptSig", o));
88         }
89         in.push_back(Pair("sequence", (int64_t)txin.nSequence));
90         vin.push_back(in);
91     }
92     entry.push_back(Pair("vin", vin));
93     Array vout;
94     for (unsigned int i = 0; i < tx.vout.size(); i++)
95     {
96         const CTxOut& txout = tx.vout[i];
97         Object out;
98         out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
99         out.push_back(Pair("n", (int64_t)i));
100         Object o;
101         ScriptPubKeyToJSON(txout.scriptPubKey, o, true);
102         out.push_back(Pair("scriptPubKey", o));
103         vout.push_back(out);
104     }
105     entry.push_back(Pair("vout", vout));
106
107     if (hashBlock != 0)
108     {
109         entry.push_back(Pair("blockhash", hashBlock.GetHex()));
110         map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
111         if (mi != mapBlockIndex.end() && (*mi).second)
112         {
113             CBlockIndex* pindex = (*mi).second;
114             if (pindex->IsInMainChain())
115             {
116                 entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight));
117                 entry.push_back(Pair("time", (int64_t)pindex->nTime));
118                 entry.push_back(Pair("blocktime", (int64_t)pindex->nTime));
119             }
120             else
121                 entry.push_back(Pair("confirmations", 0));
122         }
123     }
124 }
125
126 Value getrawtransaction(const Array& params, bool fHelp)
127 {
128     if (fHelp || params.size() < 1 || params.size() > 2)
129         throw runtime_error(
130             "getrawtransaction <txid> [verbose=0]\n"
131             "If verbose=0, returns a string that is\n"
132             "serialized, hex-encoded data for <txid>.\n"
133             "If verbose is non-zero, returns an Object\n"
134             "with information about <txid>.");
135
136     uint256 hash;
137     hash.SetHex(params[0].get_str());
138
139     bool fVerbose = false;
140     if (params.size() > 1)
141         fVerbose = (params[1].get_int() != 0);
142
143     CTransaction tx;
144     uint256 hashBlock = 0;
145     if (!GetTransaction(hash, tx, hashBlock))
146         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
147
148     CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
149     ssTx << tx;
150     string strHex = HexStr(ssTx.begin(), ssTx.end());
151
152     if (!fVerbose)
153         return strHex;
154
155     Object result;
156     result.push_back(Pair("hex", strHex));
157     TxToJSON(tx, hashBlock, result);
158     return result;
159 }
160
161 Value listunspent(const Array& params, bool fHelp)
162 {
163     if (fHelp || params.size() > 3)
164         throw runtime_error(
165             "listunspent [minconf=1] [maxconf=9999999]  [\"address\",...]\n"
166             "Returns array of unspent transaction outputs\n"
167             "with between minconf and maxconf (inclusive) confirmations.\n"
168             "Optionally filtered to only include txouts paid to specified addresses.\n"
169             "Results are an array of Objects, each of which has:\n"
170             "{txid, vout, scriptPubKey, amount, confirmations}");
171
172     RPCTypeCheck(params, list_of(int_type)(int_type)(array_type));
173
174     int nMinDepth = 1;
175     if (params.size() > 0)
176         nMinDepth = params[0].get_int();
177
178     int nMaxDepth = 9999999;
179     if (params.size() > 1)
180         nMaxDepth = params[1].get_int();
181
182     set<CBitcoinAddress> setAddress;
183     if (params.size() > 2)
184     {
185         Array inputs = params[2].get_array();
186         BOOST_FOREACH(Value& input, inputs)
187         {
188             CBitcoinAddress address(input.get_str());
189             if (!address.IsValid())
190                 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid NovaCoin address: ")+input.get_str());
191             if (setAddress.count(address))
192                 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str());
193            setAddress.insert(address);
194         }
195     }
196
197     Array results;
198     vector<COutput> vecOutputs;
199     pwalletMain->AvailableCoins(vecOutputs, false);
200     BOOST_FOREACH(const COutput& out, vecOutputs)
201     {
202         if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
203             continue;
204
205         if(setAddress.size())
206         {
207             CTxDestination address;
208             if(!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
209                 continue;
210
211             if (!setAddress.count(address))
212                 continue;
213         }
214
215         int64_t nValue = out.tx->vout[out.i].nValue;
216         const CScript& pk = out.tx->vout[out.i].scriptPubKey;
217         Object entry;
218         entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
219         entry.push_back(Pair("vout", out.i));
220         CTxDestination address;
221         if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
222         {
223             entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
224             if (pwalletMain->mapAddressBook.count(address))
225                 entry.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
226         }
227         entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end())));
228         if (pk.IsPayToScriptHash())
229         {
230             CTxDestination address;
231             if (ExtractDestination(pk, address))
232             {
233                 const CScriptID& hash = boost::get<CScriptID>(address);
234                 CScript redeemScript;
235                 if (pwalletMain->GetCScript(hash, redeemScript))
236                     entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
237             }
238         }
239         entry.push_back(Pair("amount",ValueFromAmount(nValue)));
240         entry.push_back(Pair("confirmations",out.nDepth));
241         entry.push_back(Pair("spendable", out.fSpendable));
242         results.push_back(entry);
243     }
244
245     return results;
246 }
247
248 Value createrawtransaction(const Array& params, bool fHelp)
249 {
250     if (fHelp || params.size() > 3 || params.size() < 2)
251         throw runtime_error(
252             "createrawtransaction <'[{\"txid\":txid,\"vout\":n},...]'> <'{address:amount,...}'> [hex data]\n"
253             "Create a transaction spending given inputs\n"
254             "(array of objects containing transaction id and output number),\n"
255             "sending to given address(es),\n"
256             "optional data to add into data-carrying output.\n"
257             "Returns hex-encoded raw transaction.\n"
258             "Note that the transaction's inputs are not signed, and\n"
259             "it is not stored in the wallet or transmitted to the network.");
260
261     RPCTypeCheck(params, list_of(array_type)(obj_type));
262
263     Array inputs = params[0].get_array();
264     Object sendTo = params[1].get_obj();
265
266     CTransaction rawTx;
267
268     BOOST_FOREACH(Value& input, inputs)
269     {
270         const Object& o = input.get_obj();
271
272         const Value& txid_v = find_value(o, "txid");
273         if (txid_v.type() != str_type)
274             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing txid key");
275         string txid = txid_v.get_str();
276         if (!IsHex(txid))
277             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
278
279         const Value& vout_v = find_value(o, "vout");
280         if (vout_v.type() != int_type)
281             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
282         int nOutput = vout_v.get_int();
283         if (nOutput < 0)
284             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
285
286         CTxIn in(COutPoint(uint256(txid), nOutput));
287         rawTx.vin.push_back(in);
288     }
289
290     set<CBitcoinAddress> setAddress;
291     BOOST_FOREACH(const Pair& s, sendTo)
292     {
293         // Create output destination script
294         CScript scriptPubKey;
295         CBitcoinAddress address(s.name_);
296
297         if (address.IsValid())
298         {
299             scriptPubKey.SetAddress(address);
300
301             // Don't perform duplication checking for pubkey-pair addresses
302             if (!address.IsPair())
303             {
304                 if (setAddress.count(address))
305                     throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
306                 setAddress.insert(address);
307             }
308         }
309         else
310             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid output destination: ")+s.name_);
311
312         int64_t nAmount = AmountFromValue(s.value_);
313
314         CTxOut out(nAmount, scriptPubKey);
315         rawTx.vout.push_back(out);
316     }
317
318     if (params.size() == 3)
319     {
320         // Data carrying output
321         CScript scriptPubKey;
322         scriptPubKey << OP_RETURN << ParseHex(params[2].get_str());
323         CTxOut out(0, scriptPubKey);
324         rawTx.vout.push_back(out);
325     }
326
327     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
328     ss << rawTx;
329     return HexStr(ss.begin(), ss.end());
330 }
331
332 Value decoderawtransaction(const Array& params, bool fHelp)
333 {
334     if (fHelp || params.size() != 1)
335         throw runtime_error(
336             "decoderawtransaction <hex string>\n"
337             "Return a JSON object representing the serialized, hex-encoded transaction.");
338
339     RPCTypeCheck(params, list_of(str_type));
340
341     vector<unsigned char> txData(ParseHex(params[0].get_str()));
342     CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
343     CTransaction tx;
344     try {
345         ssData >> tx;
346     }
347     catch (const std::exception&) {
348         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
349     }
350
351     Object result;
352     TxToJSON(tx, 0, result);
353
354     return result;
355 }
356
357 Value decodescript(const Array& params, bool fHelp)
358 {
359     if (fHelp || params.size() != 1)
360         throw runtime_error(
361             "decodescript <hex string>\n"
362             "Decode a hex-encoded script.");
363
364     RPCTypeCheck(params, list_of(str_type));
365
366     Object r;
367     CScript script;
368     if (params[0].get_str().size() > 0){
369         vector<unsigned char> scriptData(ParseHexV(params[0], "argument"));
370         script = CScript(scriptData.begin(), scriptData.end());
371     } else {
372         // Empty scripts are valid
373     }
374     ScriptPubKeyToJSON(script, r, false);
375
376     r.push_back(Pair("p2sh", CBitcoinAddress(script.GetID()).ToString()));
377     return r;
378 }
379
380 Value signrawtransaction(const Array& params, bool fHelp)
381 {
382     if (fHelp || params.size() < 1 || params.size() > 4)
383         throw runtime_error(
384             "signrawtransaction <hex string> '[{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex,\"redeemScript\":hex},...]' '[<privatekey1>,...]' [sighashtype=\"ALL\"]\n"
385             "Sign inputs for raw transaction (serialized, hex-encoded).\n"
386             "Second optional argument (may be null) is an array of previous transaction outputs that\n"
387             "this transaction depends on but may not yet be in the blockchain.\n"
388             "Third optional argument (may be null) is an array of base58-encoded private\n"
389             "keys that, if given, will be the only keys used to sign the transaction.\n"
390             "Fourth optional argument is a string that is one of six values; ALL, NONE, SINGLE or\n"
391             "ALL|ANYONECANPAY, NONE|ANYONECANPAY, SINGLE|ANYONECANPAY.\n"
392             "Returns json object with keys:\n"
393             "  hex : raw transaction with signature(s) (hex-encoded string)\n"
394             "  complete : 1 if transaction has a complete set of signature (0 if not)"
395             + HelpRequiringPassphrase());
396
397     RPCTypeCheck(params, list_of(str_type)(array_type)(array_type)(str_type), true);
398
399     vector<unsigned char> txData(ParseHex(params[0].get_str()));
400     CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
401     vector<CTransaction> txVariants;
402     while (!ssData.empty())
403     {
404         try {
405             CTransaction tx;
406             ssData >> tx;
407             txVariants.push_back(tx);
408         }
409         catch (const std::exception&) {
410             throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
411         }
412     }
413
414     if (txVariants.empty())
415         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transaction");
416
417     // mergedTx will end up with all the signatures; it
418     // starts as a clone of the rawtx:
419     CTransaction mergedTx(txVariants[0]);
420     bool fComplete = true;
421
422     // Fetch previous transactions (inputs):
423     map<COutPoint, CScript> mapPrevOut;
424     for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
425     {
426         CTransaction tempTx;
427         MapPrevTx mapPrevTx;
428         CTxDB txdb("r");
429         map<uint256, CTxIndex> unused;
430         bool fInvalid;
431
432         // FetchInputs aborts on failure, so we go one at a time.
433         tempTx.vin.push_back(mergedTx.vin[i]);
434         tempTx.FetchInputs(txdb, unused, false, false, mapPrevTx, fInvalid);
435
436         // Copy results into mapPrevOut:
437         BOOST_FOREACH(const CTxIn& txin, tempTx.vin)
438         {
439             const uint256& prevHash = txin.prevout.hash;
440             if (mapPrevTx.count(prevHash) && mapPrevTx[prevHash].second.vout.size()>txin.prevout.n)
441                 mapPrevOut[txin.prevout] = mapPrevTx[prevHash].second.vout[txin.prevout.n].scriptPubKey;
442         }
443     }
444
445     bool fGivenKeys = false;
446     CBasicKeyStore tempKeystore;
447     if (params.size() > 2 && params[2].type() != null_type)
448     {
449         fGivenKeys = true;
450         Array keys = params[2].get_array();
451         BOOST_FOREACH(Value k, keys)
452         {
453             CBitcoinSecret vchSecret;
454             bool fGood = vchSecret.SetString(k.get_str());
455             if (!fGood)
456                 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
457             CKey key;
458             bool fCompressed;
459             CSecret secret = vchSecret.GetSecret(fCompressed);
460             key.SetSecret(secret, fCompressed);
461             tempKeystore.AddKey(key);
462         }
463     }
464     else
465         EnsureWalletIsUnlocked();
466
467     // Add previous txouts given in the RPC call:
468     if (params.size() > 1 && params[1].type() != null_type)
469     {
470         Array prevTxs = params[1].get_array();
471         BOOST_FOREACH(Value& p, prevTxs)
472         {
473             if (p.type() != obj_type)
474                 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
475
476             Object prevOut = p.get_obj();
477
478             RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type));
479
480             string txidHex = find_value(prevOut, "txid").get_str();
481             if (!IsHex(txidHex))
482                 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "txid must be hexadecimal");
483             uint256 txid;
484             txid.SetHex(txidHex);
485
486             int nOut = find_value(prevOut, "vout").get_int();
487             if (nOut < 0)
488                 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
489
490             string pkHex = find_value(prevOut, "scriptPubKey").get_str();
491             if (!IsHex(pkHex))
492                 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "scriptPubKey must be hexadecimal");
493             vector<unsigned char> pkData(ParseHex(pkHex));
494             CScript scriptPubKey(pkData.begin(), pkData.end());
495
496             COutPoint outpoint(txid, nOut);
497             if (mapPrevOut.count(outpoint))
498             {
499                 // Complain if scriptPubKey doesn't match
500                 if (mapPrevOut[outpoint] != scriptPubKey)
501                 {
502                     string err("Previous output scriptPubKey mismatch:\n");
503                     err = err + mapPrevOut[outpoint].ToString() + "\nvs:\n"+
504                         scriptPubKey.ToString();
505                     throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
506                 }
507             }
508             else
509                 mapPrevOut[outpoint] = scriptPubKey;
510
511             // if redeemScript given and not using the local wallet (private keys
512             // given), add redeemScript to the tempKeystore so it can be signed:
513             Value v = find_value(prevOut, "redeemScript");
514             if (fGivenKeys && scriptPubKey.IsPayToScriptHash())
515             {
516                 RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type)("redeemScript",str_type));
517                 Value v = find_value(prevOut, "redeemScript");
518                 if (!(v == Value::null))
519                 {
520                     vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
521                     CScript redeemScript(rsData.begin(), rsData.end());
522                     tempKeystore.AddCScript(redeemScript);
523                 }
524             }
525         }
526     }
527
528     const CKeyStore& keystore = (fGivenKeys ? tempKeystore : *pwalletMain);
529
530     int nHashType = SIGHASH_ALL;
531     if (params.size() > 3 && params[3].type() != null_type)
532     {
533         static map<string, int> mapSigHashValues =
534             boost::assign::map_list_of
535             (string("ALL"), int(SIGHASH_ALL))
536             (string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY))
537             (string("NONE"), int(SIGHASH_NONE))
538             (string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY))
539             (string("SINGLE"), int(SIGHASH_SINGLE))
540             (string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY))
541             ;
542         string strHashType = params[3].get_str();
543         if (mapSigHashValues.count(strHashType))
544             nHashType = mapSigHashValues[strHashType];
545         else
546             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param");
547     }
548
549     bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
550
551     // Sign what we can:
552     for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
553     {
554         CTxIn& txin = mergedTx.vin[i];
555         if (mapPrevOut.count(txin.prevout) == 0)
556         {
557             fComplete = false;
558             continue;
559         }
560         const CScript& prevPubKey = mapPrevOut[txin.prevout];
561
562         txin.scriptSig.clear();
563         // Only sign SIGHASH_SINGLE if there's a corresponding output:
564         if (!fHashSingle || (i < mergedTx.vout.size()))
565             SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
566
567         // ... and merge in other signatures:
568         BOOST_FOREACH(const CTransaction& txv, txVariants)
569         {
570             txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
571         }
572         if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, STRICT_FLAGS, 0))
573             fComplete = false;
574     }
575
576     Object result;
577     CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
578     ssTx << mergedTx;
579     result.push_back(Pair("hex", HexStr(ssTx.begin(), ssTx.end())));
580     result.push_back(Pair("complete", fComplete));
581
582     return result;
583 }
584
585 Value sendrawtransaction(const Array& params, bool fHelp)
586 {
587     if (fHelp || params.size() < 1 || params.size() > 1)
588         throw runtime_error(
589             "sendrawtransaction <hex string>\n"
590             "Submits raw transaction (serialized, hex-encoded) to local node and network.");
591
592     RPCTypeCheck(params, list_of(str_type));
593
594     // parse hex string from parameter
595     vector<unsigned char> txData(ParseHex(params[0].get_str()));
596     CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
597     CTransaction tx;
598
599     // deserialize binary data stream
600     try {
601         ssData >> tx;
602     }
603     catch (const std::exception&) {
604         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
605     }
606     uint256 hashTx = tx.GetHash();
607
608     // See if the transaction is already in a block
609     // or in the memory pool:
610     CTransaction existingTx;
611     uint256 hashBlock = 0;
612     if (GetTransaction(hashTx, existingTx, hashBlock))
613     {
614         if (hashBlock != 0)
615             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("transaction already in block ")+hashBlock.GetHex());
616         // Not in block, but already in the memory pool; will drop
617         // through to re-relay it.
618     }
619     else
620     {
621         // push to local node
622         CTxDB txdb("r");
623         if (!tx.AcceptToMemoryPool(txdb))
624             throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected");
625
626         SyncWithWallets(tx, NULL, true);
627     }
628     RelayTransaction(tx, hashTx);
629
630     return hashTx.GetHex();
631 }
632
633 Value createmultisig(const Array& params, bool fHelp)
634 {
635     if (fHelp || params.size() < 2 || params.size() > 3)
636     {
637         string msg = "createmultisig <nrequired> <'[\"key\",\"key\"]'>\n"
638             "\nCreates a multi-signature address with n signature of m keys required.\n"
639             "It returns a json object with the address and redeemScript.";
640         throw runtime_error(msg);
641     }
642
643     int nRequired = params[0].get_int();
644     const Array& keys = params[1].get_array();
645
646     // Gather public keys
647     if (nRequired < 1)
648         throw runtime_error("a multisignature address must require at least one key to redeem");
649     if ((int)keys.size() < nRequired)
650         throw runtime_error(
651             strprintf("not enough keys supplied "
652                       "(got %" PRIszu " keys, but need at least %d to redeem)", keys.size(), nRequired));
653     if (keys.size() > 16)
654         throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
655     std::vector<CPubKey> pubkeys;
656     pubkeys.resize(keys.size());
657     for (unsigned int i = 0; i < keys.size(); i++)
658     {
659         const std::string& ks = keys[i].get_str();
660
661         // Case 1: Bitcoin address and we have full public key:
662         CBitcoinAddress address(ks);
663         if (address.IsValid())
664         {
665             CKeyID keyID;
666             if (!address.GetKeyID(keyID))
667                 throw runtime_error(
668                     strprintf("%s does not refer to a key",ks.c_str()));
669             CPubKey vchPubKey;
670             if (!pwalletMain->GetPubKey(keyID, vchPubKey))
671                 throw runtime_error(
672                     strprintf("no full public key for address %s",ks.c_str()));
673             if (!vchPubKey.IsFullyValid())
674                 throw runtime_error(" Invalid public key: "+ks);
675             pubkeys[i] = vchPubKey;
676         }
677
678         // Case 2: hex public key
679         else if (IsHex(ks))
680         {
681             CPubKey vchPubKey(ParseHex(ks));
682             if (!vchPubKey.IsFullyValid())
683                 throw runtime_error(" Invalid public key: "+ks);
684             pubkeys[i] = vchPubKey;
685         }
686         else
687         {
688             throw runtime_error(" Invalid public key: "+ks);
689         }
690     }
691
692     // Construct using pay-to-script-hash:
693     CScript inner;
694     inner.SetMultisig(nRequired, pubkeys);
695
696     if (inner.size() > MAX_SCRIPT_ELEMENT_SIZE)
697         throw runtime_error(
698             strprintf("redeemScript exceeds size limit: %" PRIszu " > %d", inner.size(), MAX_SCRIPT_ELEMENT_SIZE));
699
700     CScriptID innerID = inner.GetID();
701     CBitcoinAddress address(innerID);
702
703     Object result;
704     result.push_back(Pair("address", address.ToString()));
705     result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
706
707     return result;
708 }