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