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.
6 #include <boost/assign/list_of.hpp>
9 #include "bitcoinrpc.h"
17 using namespace boost;
18 using namespace boost::assign;
19 using namespace json_spirit;
21 void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex)
24 vector<CTxDestination> addresses;
27 out.push_back(Pair("asm", scriptPubKey.ToString()));
30 out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
32 if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired))
34 out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD)));
38 if (type != TX_NULL_DATA)
40 out.push_back(Pair("reqSigs", nRequired));
41 out.push_back(Pair("type", GetTxnOutputType(type)));
44 BOOST_FOREACH(const CTxDestination& addr, addresses)
45 a.push_back(CBitcoinAddress(addr).ToString());
46 out.push_back(Pair("addresses", a));
50 out.push_back(Pair("type", GetTxnOutputType(type)));
54 void TxToJSON(const CTransaction& tx, const uint256& hashBlock, Object& entry)
56 entry.push_back(Pair("txid", tx.GetHash().GetHex()));
57 entry.push_back(Pair("version", tx.nVersion));
58 entry.push_back(Pair("time", (int64_t)tx.nTime));
59 entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
61 BOOST_FOREACH(const CTxIn& txin, tx.vin)
65 in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
68 in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
69 in.push_back(Pair("vout", (int64_t)txin.prevout.n));
71 o.push_back(Pair("asm", txin.scriptSig.ToString()));
72 o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
73 in.push_back(Pair("scriptSig", o));
75 in.push_back(Pair("sequence", (int64_t)txin.nSequence));
78 entry.push_back(Pair("vin", vin));
80 for (unsigned int i = 0; i < tx.vout.size(); i++)
82 const CTxOut& txout = tx.vout[i];
84 out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
85 out.push_back(Pair("n", (int64_t)i));
87 ScriptPubKeyToJSON(txout.scriptPubKey, o, true);
88 out.push_back(Pair("scriptPubKey", o));
91 entry.push_back(Pair("vout", vout));
95 entry.push_back(Pair("blockhash", hashBlock.GetHex()));
96 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
97 if (mi != mapBlockIndex.end() && (*mi).second)
99 CBlockIndex* pindex = (*mi).second;
100 if (pindex->IsInMainChain())
102 entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight));
103 entry.push_back(Pair("time", (int64_t)pindex->nTime));
104 entry.push_back(Pair("blocktime", (int64_t)pindex->nTime));
107 entry.push_back(Pair("confirmations", 0));
112 Value getrawtransaction(const Array& params, bool fHelp)
114 if (fHelp || params.size() < 1 || params.size() > 2)
116 "getrawtransaction <txid> [verbose=0]\n"
117 "If verbose=0, returns a string that is\n"
118 "serialized, hex-encoded data for <txid>.\n"
119 "If verbose is non-zero, returns an Object\n"
120 "with information about <txid>.");
123 hash.SetHex(params[0].get_str());
125 bool fVerbose = false;
126 if (params.size() > 1)
127 fVerbose = (params[1].get_int() != 0);
130 uint256 hashBlock = 0;
131 if (!GetTransaction(hash, tx, hashBlock))
132 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
134 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
136 string strHex = HexStr(ssTx.begin(), ssTx.end());
142 result.push_back(Pair("hex", strHex));
143 TxToJSON(tx, hashBlock, result);
147 Value listunspent(const Array& params, bool fHelp)
149 if (fHelp || params.size() > 3)
151 "listunspent [minconf=1] [maxconf=9999999] [\"address\",...]\n"
152 "Returns array of unspent transaction outputs\n"
153 "with between minconf and maxconf (inclusive) confirmations.\n"
154 "Optionally filtered to only include txouts paid to specified addresses.\n"
155 "Results are an array of Objects, each of which has:\n"
156 "{txid, vout, scriptPubKey, amount, confirmations}");
158 RPCTypeCheck(params, list_of(int_type)(int_type)(array_type));
161 if (params.size() > 0)
162 nMinDepth = params[0].get_int();
164 int nMaxDepth = 9999999;
165 if (params.size() > 1)
166 nMaxDepth = params[1].get_int();
168 set<CBitcoinAddress> setAddress;
169 if (params.size() > 2)
171 Array inputs = params[2].get_array();
172 BOOST_FOREACH(Value& input, inputs)
174 CBitcoinAddress address(input.get_str());
175 if (!address.IsValid())
176 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid NovaCoin address: ")+input.get_str());
177 if (setAddress.count(address))
178 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str());
179 setAddress.insert(address);
184 vector<COutput> vecOutputs;
185 pwalletMain->AvailableCoins(vecOutputs, false);
186 BOOST_FOREACH(const COutput& out, vecOutputs)
188 if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
191 if(setAddress.size())
193 CTxDestination address;
194 if(!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
197 if (!setAddress.count(address))
201 int64_t nValue = out.tx->vout[out.i].nValue;
202 const CScript& pk = out.tx->vout[out.i].scriptPubKey;
204 entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
205 entry.push_back(Pair("vout", out.i));
206 CTxDestination address;
207 if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
209 entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
210 if (pwalletMain->mapAddressBook.count(address))
211 entry.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
213 entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end())));
214 if (pk.IsPayToScriptHash())
216 CTxDestination address;
217 if (ExtractDestination(pk, address))
219 const CScriptID& hash = boost::get<CScriptID>(address);
220 CScript redeemScript;
221 if (pwalletMain->GetCScript(hash, redeemScript))
222 entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
225 entry.push_back(Pair("amount",ValueFromAmount(nValue)));
226 entry.push_back(Pair("confirmations",out.nDepth));
227 entry.push_back(Pair("spendable", out.fSpendable));
228 results.push_back(entry);
234 Value createrawtransaction(const Array& params, bool fHelp)
236 if (fHelp || params.size() > 3 || params.size() < 2)
238 "createrawtransaction <'[{\"txid\":txid,\"vout\":n},...]'> <'{address:amount,...}'> [hex data]\n"
239 "Create a transaction spending given inputs\n"
240 "(array of objects containing transaction id and output number),\n"
241 "sending to given address(es),\n"
242 "optional data to add into data-carrying output.\n"
243 "Returns hex-encoded raw transaction.\n"
244 "Note that the transaction's inputs are not signed, and\n"
245 "it is not stored in the wallet or transmitted to the network.");
247 RPCTypeCheck(params, list_of(array_type)(obj_type));
249 Array inputs = params[0].get_array();
250 Object sendTo = params[1].get_obj();
254 BOOST_FOREACH(Value& input, inputs)
256 const Object& o = input.get_obj();
258 const Value& txid_v = find_value(o, "txid");
259 if (txid_v.type() != str_type)
260 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing txid key");
261 string txid = txid_v.get_str();
263 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
265 const Value& vout_v = find_value(o, "vout");
266 if (vout_v.type() != int_type)
267 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
268 int nOutput = vout_v.get_int();
270 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
272 CTxIn in(COutPoint(uint256(txid), nOutput));
273 rawTx.vin.push_back(in);
276 set<CBitcoinAddress> setAddress;
277 BOOST_FOREACH(const Pair& s, sendTo)
279 CBitcoinAddress address(s.name_);
280 if (!address.IsValid())
281 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid NovaCoin address: ")+s.name_);
283 if (setAddress.count(address))
284 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
285 setAddress.insert(address);
287 CScript scriptPubKey;
288 scriptPubKey.SetDestination(address.Get());
289 int64_t nAmount = AmountFromValue(s.value_);
291 CTxOut out(nAmount, scriptPubKey);
292 rawTx.vout.push_back(out);
295 if (params.size() == 3)
297 // Data carrying output
298 CScript scriptPubKey;
299 scriptPubKey << OP_RETURN << ParseHex(params[2].get_str());
300 CTxOut out(0, scriptPubKey);
301 rawTx.vout.push_back(out);
304 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
306 return HexStr(ss.begin(), ss.end());
309 Value decoderawtransaction(const Array& params, bool fHelp)
311 if (fHelp || params.size() != 1)
313 "decoderawtransaction <hex string>\n"
314 "Return a JSON object representing the serialized, hex-encoded transaction.");
316 RPCTypeCheck(params, list_of(str_type));
318 vector<unsigned char> txData(ParseHex(params[0].get_str()));
319 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
324 catch (const std::exception&) {
325 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
329 TxToJSON(tx, 0, result);
334 Value decodescript(const Array& params, bool fHelp)
336 if (fHelp || params.size() != 1)
338 "decodescript <hex string>\n"
339 "Decode a hex-encoded script.");
341 RPCTypeCheck(params, list_of(str_type));
345 if (params[0].get_str().size() > 0){
346 vector<unsigned char> scriptData(ParseHexV(params[0], "argument"));
347 script = CScript(scriptData.begin(), scriptData.end());
349 // Empty scripts are valid
351 ScriptPubKeyToJSON(script, r, false);
353 r.push_back(Pair("p2sh", CBitcoinAddress(script.GetID()).ToString()));
357 Value signrawtransaction(const Array& params, bool fHelp)
359 if (fHelp || params.size() < 1 || params.size() > 4)
361 "signrawtransaction <hex string> '[{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex,\"redeemScript\":hex},...]' '[<privatekey1>,...]' [sighashtype=\"ALL\"]\n"
362 "Sign inputs for raw transaction (serialized, hex-encoded).\n"
363 "Second optional argument (may be null) is an array of previous transaction outputs that\n"
364 "this transaction depends on but may not yet be in the blockchain.\n"
365 "Third optional argument (may be null) is an array of base58-encoded private\n"
366 "keys that, if given, will be the only keys used to sign the transaction.\n"
367 "Fourth optional argument is a string that is one of six values; ALL, NONE, SINGLE or\n"
368 "ALL|ANYONECANPAY, NONE|ANYONECANPAY, SINGLE|ANYONECANPAY.\n"
369 "Returns json object with keys:\n"
370 " hex : raw transaction with signature(s) (hex-encoded string)\n"
371 " complete : 1 if transaction has a complete set of signature (0 if not)"
372 + HelpRequiringPassphrase());
374 RPCTypeCheck(params, list_of(str_type)(array_type)(array_type)(str_type), true);
376 vector<unsigned char> txData(ParseHex(params[0].get_str()));
377 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
378 vector<CTransaction> txVariants;
379 while (!ssData.empty())
384 txVariants.push_back(tx);
386 catch (const std::exception&) {
387 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
391 if (txVariants.empty())
392 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transaction");
394 // mergedTx will end up with all the signatures; it
395 // starts as a clone of the rawtx:
396 CTransaction mergedTx(txVariants[0]);
397 bool fComplete = true;
399 // Fetch previous transactions (inputs):
400 map<COutPoint, CScript> mapPrevOut;
401 for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
406 map<uint256, CTxIndex> unused;
409 // FetchInputs aborts on failure, so we go one at a time.
410 tempTx.vin.push_back(mergedTx.vin[i]);
411 tempTx.FetchInputs(txdb, unused, false, false, mapPrevTx, fInvalid);
413 // Copy results into mapPrevOut:
414 BOOST_FOREACH(const CTxIn& txin, tempTx.vin)
416 const uint256& prevHash = txin.prevout.hash;
417 if (mapPrevTx.count(prevHash) && mapPrevTx[prevHash].second.vout.size()>txin.prevout.n)
418 mapPrevOut[txin.prevout] = mapPrevTx[prevHash].second.vout[txin.prevout.n].scriptPubKey;
422 bool fGivenKeys = false;
423 CBasicKeyStore tempKeystore;
424 if (params.size() > 2 && params[2].type() != null_type)
427 Array keys = params[2].get_array();
428 BOOST_FOREACH(Value k, keys)
430 CBitcoinSecret vchSecret;
431 bool fGood = vchSecret.SetString(k.get_str());
433 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
436 CSecret secret = vchSecret.GetSecret(fCompressed);
437 key.SetSecret(secret, fCompressed);
438 tempKeystore.AddKey(key);
442 EnsureWalletIsUnlocked();
444 // Add previous txouts given in the RPC call:
445 if (params.size() > 1 && params[1].type() != null_type)
447 Array prevTxs = params[1].get_array();
448 BOOST_FOREACH(Value& p, prevTxs)
450 if (p.type() != obj_type)
451 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
453 Object prevOut = p.get_obj();
455 RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type));
457 string txidHex = find_value(prevOut, "txid").get_str();
459 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "txid must be hexadecimal");
461 txid.SetHex(txidHex);
463 int nOut = find_value(prevOut, "vout").get_int();
465 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
467 string pkHex = find_value(prevOut, "scriptPubKey").get_str();
469 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "scriptPubKey must be hexadecimal");
470 vector<unsigned char> pkData(ParseHex(pkHex));
471 CScript scriptPubKey(pkData.begin(), pkData.end());
473 COutPoint outpoint(txid, nOut);
474 if (mapPrevOut.count(outpoint))
476 // Complain if scriptPubKey doesn't match
477 if (mapPrevOut[outpoint] != scriptPubKey)
479 string err("Previous output scriptPubKey mismatch:\n");
480 err = err + mapPrevOut[outpoint].ToString() + "\nvs:\n"+
481 scriptPubKey.ToString();
482 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
486 mapPrevOut[outpoint] = scriptPubKey;
488 // if redeemScript given and not using the local wallet (private keys
489 // given), add redeemScript to the tempKeystore so it can be signed:
490 Value v = find_value(prevOut, "redeemScript");
491 if (fGivenKeys && scriptPubKey.IsPayToScriptHash())
493 RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type)("redeemScript",str_type));
494 Value v = find_value(prevOut, "redeemScript");
495 if (!(v == Value::null))
497 vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
498 CScript redeemScript(rsData.begin(), rsData.end());
499 tempKeystore.AddCScript(redeemScript);
505 const CKeyStore& keystore = (fGivenKeys ? tempKeystore : *pwalletMain);
507 int nHashType = SIGHASH_ALL;
508 if (params.size() > 3 && params[3].type() != null_type)
510 static map<string, int> mapSigHashValues =
511 boost::assign::map_list_of
512 (string("ALL"), int(SIGHASH_ALL))
513 (string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY))
514 (string("NONE"), int(SIGHASH_NONE))
515 (string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY))
516 (string("SINGLE"), int(SIGHASH_SINGLE))
517 (string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY))
519 string strHashType = params[3].get_str();
520 if (mapSigHashValues.count(strHashType))
521 nHashType = mapSigHashValues[strHashType];
523 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param");
526 bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
529 for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
531 CTxIn& txin = mergedTx.vin[i];
532 if (mapPrevOut.count(txin.prevout) == 0)
537 const CScript& prevPubKey = mapPrevOut[txin.prevout];
539 txin.scriptSig.clear();
540 // Only sign SIGHASH_SINGLE if there's a corresponding output:
541 if (!fHashSingle || (i < mergedTx.vout.size()))
542 SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
544 // ... and merge in other signatures:
545 BOOST_FOREACH(const CTransaction& txv, txVariants)
547 txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
549 if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, STRICT_FLAGS, 0))
554 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
556 result.push_back(Pair("hex", HexStr(ssTx.begin(), ssTx.end())));
557 result.push_back(Pair("complete", fComplete));
562 Value sendrawtransaction(const Array& params, bool fHelp)
564 if (fHelp || params.size() < 1 || params.size() > 1)
566 "sendrawtransaction <hex string>\n"
567 "Submits raw transaction (serialized, hex-encoded) to local node and network.");
569 RPCTypeCheck(params, list_of(str_type));
571 // parse hex string from parameter
572 vector<unsigned char> txData(ParseHex(params[0].get_str()));
573 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
576 // deserialize binary data stream
580 catch (const std::exception&) {
581 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
583 uint256 hashTx = tx.GetHash();
585 // See if the transaction is already in a block
586 // or in the memory pool:
587 CTransaction existingTx;
588 uint256 hashBlock = 0;
589 if (GetTransaction(hashTx, existingTx, hashBlock))
592 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("transaction already in block ")+hashBlock.GetHex());
593 // Not in block, but already in the memory pool; will drop
594 // through to re-relay it.
598 // push to local node
600 if (!tx.AcceptToMemoryPool(txdb))
601 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected");
603 SyncWithWallets(tx, NULL, true);
605 RelayTransaction(tx, hashTx);
607 return hashTx.GetHex();
610 Value createmultisig(const Array& params, bool fHelp)
612 if (fHelp || params.size() < 2 || params.size() > 3)
614 string msg = "createmultisig <nrequired> <'[\"key\",\"key\"]'>\n"
615 "\nCreates a multi-signature address with n signature of m keys required.\n"
616 "It returns a json object with the address and redeemScript.";
617 throw runtime_error(msg);
620 int nRequired = params[0].get_int();
621 const Array& keys = params[1].get_array();
624 // Gather public keys
626 throw runtime_error("a multisignature address must require at least one key to redeem");
627 if ((int)keys.size() < nRequired)
629 strprintf("not enough keys supplied "
630 "(got %" PRIszu " keys, but need at least %d to redeem)", keys.size(), nRequired));
631 if (keys.size() > 16)
632 throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
633 std::vector<CKey> pubkeys;
634 pubkeys.resize(keys.size());
635 for (unsigned int i = 0; i < keys.size(); i++)
637 const std::string& ks = keys[i].get_str();
639 // Case 1: Bitcoin address and we have full public key:
640 CBitcoinAddress address(ks);
641 if (address.IsValid())
644 if (!address.GetKeyID(keyID))
646 strprintf("%s does not refer to a key",ks.c_str()));
648 if (!pwalletMain->GetPubKey(keyID, vchPubKey))
650 strprintf("no full public key for address %s",ks.c_str()));
651 if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey))
652 throw runtime_error(" Invalid public key: "+ks);
655 // Case 2: hex public key
658 CPubKey vchPubKey(ParseHex(ks));
659 if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey))
660 throw runtime_error(" Invalid public key: "+ks);
664 throw runtime_error(" Invalid public key: "+ks);
668 // Construct using pay-to-script-hash:
670 inner.SetMultisig(nRequired, pubkeys);
672 if (inner.size() > MAX_SCRIPT_ELEMENT_SIZE)
674 strprintf("redeemScript exceeds size limit: %" PRIszu " > %d", inner.size(), MAX_SCRIPT_ELEMENT_SIZE));
676 CScriptID innerID = inner.GetID();
677 CBitcoinAddress address(innerID);
680 result.push_back(Pair("address", address.ToString()));
681 result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));