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