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"
19 using namespace boost;
20 using namespace boost::assign;
21 using namespace json_spirit;
23 void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex)
26 vector<CTxDestination> addresses;
29 out.push_back(Pair("asm", scriptPubKey.ToString()));
32 out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
34 if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired))
36 out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD)));
40 if (type != TX_NULL_DATA)
42 out.push_back(Pair("reqSigs", nRequired));
43 out.push_back(Pair("type", GetTxnOutputType(type)));
46 BOOST_FOREACH(const CTxDestination& addr, addresses)
47 a.push_back(CBitcoinAddress(addr).ToString());
48 out.push_back(Pair("addresses", a));
52 out.push_back(Pair("type", GetTxnOutputType(type)));
56 void TxToJSON(const CTransaction& tx, const uint256& hashBlock, Object& entry)
58 entry.push_back(Pair("txid", tx.GetHash().GetHex()));
59 entry.push_back(Pair("version", tx.nVersion));
60 entry.push_back(Pair("time", (int64_t)tx.nTime));
61 entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
63 BOOST_FOREACH(const CTxIn& txin, tx.vin)
67 in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
70 in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
71 in.push_back(Pair("vout", (int64_t)txin.prevout.n));
73 o.push_back(Pair("asm", txin.scriptSig.ToString()));
74 o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
75 in.push_back(Pair("scriptSig", o));
77 in.push_back(Pair("sequence", (int64_t)txin.nSequence));
80 entry.push_back(Pair("vin", vin));
82 for (unsigned int i = 0; i < tx.vout.size(); i++)
84 const CTxOut& txout = tx.vout[i];
86 out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
87 out.push_back(Pair("n", (int64_t)i));
89 ScriptPubKeyToJSON(txout.scriptPubKey, o, true);
90 out.push_back(Pair("scriptPubKey", o));
93 entry.push_back(Pair("vout", vout));
97 entry.push_back(Pair("blockhash", hashBlock.GetHex()));
98 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
99 if (mi != mapBlockIndex.end() && (*mi).second)
101 CBlockIndex* pindex = (*mi).second;
102 if (pindex->IsInMainChain())
104 entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight));
105 entry.push_back(Pair("time", (int64_t)pindex->nTime));
106 entry.push_back(Pair("blocktime", (int64_t)pindex->nTime));
109 entry.push_back(Pair("confirmations", 0));
114 Value getrawtransaction(const Array& params, bool fHelp)
116 if (fHelp || params.size() < 1 || params.size() > 2)
118 "getrawtransaction <txid> [verbose=0]\n"
119 "If verbose=0, returns a string that is\n"
120 "serialized, hex-encoded data for <txid>.\n"
121 "If verbose is non-zero, returns an Object\n"
122 "with information about <txid>.");
125 hash.SetHex(params[0].get_str());
127 bool fVerbose = false;
128 if (params.size() > 1)
129 fVerbose = (params[1].get_int() != 0);
132 uint256 hashBlock = 0;
133 if (!GetTransaction(hash, tx, hashBlock))
134 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
136 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
138 string strHex = HexStr(ssTx.begin(), ssTx.end());
144 result.push_back(Pair("hex", strHex));
145 TxToJSON(tx, hashBlock, result);
149 Value listunspent(const Array& params, bool fHelp)
151 if (fHelp || params.size() > 3)
153 "listunspent [minconf=1] [maxconf=9999999] [\"address\",...]\n"
154 "Returns array of unspent transaction outputs\n"
155 "with between minconf and maxconf (inclusive) confirmations.\n"
156 "Optionally filtered to only include txouts paid to specified addresses.\n"
157 "Results are an array of Objects, each of which has:\n"
158 "{txid, vout, scriptPubKey, amount, confirmations}");
160 RPCTypeCheck(params, list_of(int_type)(int_type)(array_type));
163 if (params.size() > 0)
164 nMinDepth = params[0].get_int();
166 int nMaxDepth = 9999999;
167 if (params.size() > 1)
168 nMaxDepth = params[1].get_int();
170 set<CBitcoinAddress> setAddress;
171 if (params.size() > 2)
173 Array inputs = params[2].get_array();
174 BOOST_FOREACH(Value& input, inputs)
176 CBitcoinAddress address(input.get_str());
177 if (!address.IsValid())
178 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid NovaCoin address: ")+input.get_str());
179 if (setAddress.count(address))
180 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str());
181 setAddress.insert(address);
186 vector<COutput> vecOutputs;
187 pwalletMain->AvailableCoins(vecOutputs, false);
188 BOOST_FOREACH(const COutput& out, vecOutputs)
190 if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
193 if(setAddress.size())
195 CTxDestination address;
196 if(!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
199 if (!setAddress.count(address))
203 int64_t nValue = out.tx->vout[out.i].nValue;
204 const CScript& pk = out.tx->vout[out.i].scriptPubKey;
206 entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
207 entry.push_back(Pair("vout", out.i));
208 CTxDestination address;
209 if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
211 entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
212 if (pwalletMain->mapAddressBook.count(address))
213 entry.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
215 entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end())));
216 if (pk.IsPayToScriptHash())
218 CTxDestination address;
219 if (ExtractDestination(pk, address))
221 const CScriptID& hash = boost::get<CScriptID>(address);
222 CScript redeemScript;
223 if (pwalletMain->GetCScript(hash, redeemScript))
224 entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
227 entry.push_back(Pair("amount",ValueFromAmount(nValue)));
228 entry.push_back(Pair("confirmations",out.nDepth));
229 entry.push_back(Pair("spendable", out.fSpendable));
230 results.push_back(entry);
236 Value createrawtransaction(const Array& params, bool fHelp)
238 if (fHelp || params.size() > 3 || params.size() < 2)
240 "createrawtransaction <'[{\"txid\":txid,\"vout\":n},...]'> <'{address:amount,...}'> [hex data]\n"
241 "Create a transaction spending given inputs\n"
242 "(array of objects containing transaction id and output number),\n"
243 "sending to given address(es),\n"
244 "optional data to add into data-carrying output.\n"
245 "Returns hex-encoded raw transaction.\n"
246 "Note that the transaction's inputs are not signed, and\n"
247 "it is not stored in the wallet or transmitted to the network.");
249 RPCTypeCheck(params, list_of(array_type)(obj_type));
251 Array inputs = params[0].get_array();
252 Object sendTo = params[1].get_obj();
256 BOOST_FOREACH(Value& input, inputs)
258 const Object& o = input.get_obj();
260 const Value& txid_v = find_value(o, "txid");
261 if (txid_v.type() != str_type)
262 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing txid key");
263 string txid = txid_v.get_str();
265 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
267 const Value& vout_v = find_value(o, "vout");
268 if (vout_v.type() != int_type)
269 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
270 int nOutput = vout_v.get_int();
272 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
274 CTxIn in(COutPoint(uint256(txid), nOutput));
275 rawTx.vin.push_back(in);
278 set<CBitcoinAddress> setAddress;
279 BOOST_FOREACH(const Pair& s, sendTo)
281 CBitcoinAddress address(s.name_);
282 if (!address.IsValid())
283 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid NovaCoin address: ")+s.name_);
285 if (setAddress.count(address))
286 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
287 setAddress.insert(address);
289 CScript scriptPubKey;
290 scriptPubKey.SetDestination(address.Get());
291 int64_t nAmount = AmountFromValue(s.value_);
293 CTxOut out(nAmount, scriptPubKey);
294 rawTx.vout.push_back(out);
297 if (params.size() == 3)
299 // Data carrying output
300 CScript scriptPubKey;
301 scriptPubKey << OP_RETURN << ParseHex(params[2].get_str());
302 CTxOut out(0, scriptPubKey);
303 rawTx.vout.push_back(out);
306 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
308 return HexStr(ss.begin(), ss.end());
311 Value decoderawtransaction(const Array& params, bool fHelp)
313 if (fHelp || params.size() != 1)
315 "decoderawtransaction <hex string>\n"
316 "Return a JSON object representing the serialized, hex-encoded transaction.");
318 RPCTypeCheck(params, list_of(str_type));
320 vector<unsigned char> txData(ParseHex(params[0].get_str()));
321 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
326 catch (const std::exception&) {
327 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
331 TxToJSON(tx, 0, result);
336 Value decodescript(const Array& params, bool fHelp)
338 if (fHelp || params.size() != 1)
340 "decodescript <hex string>\n"
341 "Decode a hex-encoded script.");
343 RPCTypeCheck(params, list_of(str_type));
347 if (params[0].get_str().size() > 0){
348 vector<unsigned char> scriptData(ParseHexV(params[0], "argument"));
349 script = CScript(scriptData.begin(), scriptData.end());
351 // Empty scripts are valid
353 ScriptPubKeyToJSON(script, r, false);
355 r.push_back(Pair("p2sh", CBitcoinAddress(script.GetID()).ToString()));
359 Value signrawtransaction(const Array& params, bool fHelp)
361 if (fHelp || params.size() < 1 || params.size() > 4)
363 "signrawtransaction <hex string> '[{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex,\"redeemScript\":hex},...]' '[<privatekey1>,...]' [sighashtype=\"ALL\"]\n"
364 "Sign inputs for raw transaction (serialized, hex-encoded).\n"
365 "Second optional argument (may be null) is an array of previous transaction outputs that\n"
366 "this transaction depends on but may not yet be in the blockchain.\n"
367 "Third optional argument (may be null) is an array of base58-encoded private\n"
368 "keys that, if given, will be the only keys used to sign the transaction.\n"
369 "Fourth optional argument is a string that is one of six values; ALL, NONE, SINGLE or\n"
370 "ALL|ANYONECANPAY, NONE|ANYONECANPAY, SINGLE|ANYONECANPAY.\n"
371 "Returns json object with keys:\n"
372 " hex : raw transaction with signature(s) (hex-encoded string)\n"
373 " complete : 1 if transaction has a complete set of signature (0 if not)"
374 + HelpRequiringPassphrase());
376 RPCTypeCheck(params, list_of(str_type)(array_type)(array_type)(str_type), true);
378 vector<unsigned char> txData(ParseHex(params[0].get_str()));
379 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
380 vector<CTransaction> txVariants;
381 while (!ssData.empty())
386 txVariants.push_back(tx);
388 catch (const std::exception&) {
389 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
393 if (txVariants.empty())
394 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transaction");
396 // mergedTx will end up with all the signatures; it
397 // starts as a clone of the rawtx:
398 CTransaction mergedTx(txVariants[0]);
399 bool fComplete = true;
401 // Fetch previous transactions (inputs):
402 map<COutPoint, CScript> mapPrevOut;
403 for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
408 map<uint256, CTxIndex> unused;
411 // FetchInputs aborts on failure, so we go one at a time.
412 tempTx.vin.push_back(mergedTx.vin[i]);
413 tempTx.FetchInputs(txdb, unused, false, false, mapPrevTx, fInvalid);
415 // Copy results into mapPrevOut:
416 BOOST_FOREACH(const CTxIn& txin, tempTx.vin)
418 const uint256& prevHash = txin.prevout.hash;
419 if (mapPrevTx.count(prevHash) && mapPrevTx[prevHash].second.vout.size()>txin.prevout.n)
420 mapPrevOut[txin.prevout] = mapPrevTx[prevHash].second.vout[txin.prevout.n].scriptPubKey;
424 bool fGivenKeys = false;
425 CBasicKeyStore tempKeystore;
426 if (params.size() > 2 && params[2].type() != null_type)
429 Array keys = params[2].get_array();
430 BOOST_FOREACH(Value k, keys)
432 CBitcoinSecret vchSecret;
433 bool fGood = vchSecret.SetString(k.get_str());
435 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
438 CSecret secret = vchSecret.GetSecret(fCompressed);
439 key.SetSecret(secret, fCompressed);
440 tempKeystore.AddKey(key);
444 EnsureWalletIsUnlocked();
446 // Add previous txouts given in the RPC call:
447 if (params.size() > 1 && params[1].type() != null_type)
449 Array prevTxs = params[1].get_array();
450 BOOST_FOREACH(Value& p, prevTxs)
452 if (p.type() != obj_type)
453 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
455 Object prevOut = p.get_obj();
457 RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type));
459 string txidHex = find_value(prevOut, "txid").get_str();
461 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "txid must be hexadecimal");
463 txid.SetHex(txidHex);
465 int nOut = find_value(prevOut, "vout").get_int();
467 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
469 string pkHex = find_value(prevOut, "scriptPubKey").get_str();
471 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "scriptPubKey must be hexadecimal");
472 vector<unsigned char> pkData(ParseHex(pkHex));
473 CScript scriptPubKey(pkData.begin(), pkData.end());
475 COutPoint outpoint(txid, nOut);
476 if (mapPrevOut.count(outpoint))
478 // Complain if scriptPubKey doesn't match
479 if (mapPrevOut[outpoint] != scriptPubKey)
481 string err("Previous output scriptPubKey mismatch:\n");
482 err = err + mapPrevOut[outpoint].ToString() + "\nvs:\n"+
483 scriptPubKey.ToString();
484 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
488 mapPrevOut[outpoint] = scriptPubKey;
490 // if redeemScript given and not using the local wallet (private keys
491 // given), add redeemScript to the tempKeystore so it can be signed:
492 Value v = find_value(prevOut, "redeemScript");
493 if (fGivenKeys && scriptPubKey.IsPayToScriptHash())
495 RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type)("redeemScript",str_type));
496 Value v = find_value(prevOut, "redeemScript");
497 if (!(v == Value::null))
499 vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
500 CScript redeemScript(rsData.begin(), rsData.end());
501 tempKeystore.AddCScript(redeemScript);
507 const CKeyStore& keystore = (fGivenKeys ? tempKeystore : *pwalletMain);
509 int nHashType = SIGHASH_ALL;
510 if (params.size() > 3 && params[3].type() != null_type)
512 static map<string, int> mapSigHashValues =
513 boost::assign::map_list_of
514 (string("ALL"), int(SIGHASH_ALL))
515 (string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY))
516 (string("NONE"), int(SIGHASH_NONE))
517 (string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY))
518 (string("SINGLE"), int(SIGHASH_SINGLE))
519 (string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY))
521 string strHashType = params[3].get_str();
522 if (mapSigHashValues.count(strHashType))
523 nHashType = mapSigHashValues[strHashType];
525 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param");
528 bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
531 for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
533 CTxIn& txin = mergedTx.vin[i];
534 if (mapPrevOut.count(txin.prevout) == 0)
539 const CScript& prevPubKey = mapPrevOut[txin.prevout];
541 txin.scriptSig.clear();
542 // Only sign SIGHASH_SINGLE if there's a corresponding output:
543 if (!fHashSingle || (i < mergedTx.vout.size()))
544 SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
546 // ... and merge in other signatures:
547 BOOST_FOREACH(const CTransaction& txv, txVariants)
549 txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
551 if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, STRICT_FLAGS, 0))
556 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
558 result.push_back(Pair("hex", HexStr(ssTx.begin(), ssTx.end())));
559 result.push_back(Pair("complete", fComplete));
564 Value sendrawtransaction(const Array& params, bool fHelp)
566 if (fHelp || params.size() < 1 || params.size() > 1)
568 "sendrawtransaction <hex string>\n"
569 "Submits raw transaction (serialized, hex-encoded) to local node and network.");
571 RPCTypeCheck(params, list_of(str_type));
573 // parse hex string from parameter
574 vector<unsigned char> txData(ParseHex(params[0].get_str()));
575 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
578 // deserialize binary data stream
582 catch (const std::exception&) {
583 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
585 uint256 hashTx = tx.GetHash();
587 // See if the transaction is already in a block
588 // or in the memory pool:
589 CTransaction existingTx;
590 uint256 hashBlock = 0;
591 if (GetTransaction(hashTx, existingTx, hashBlock))
594 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("transaction already in block ")+hashBlock.GetHex());
595 // Not in block, but already in the memory pool; will drop
596 // through to re-relay it.
600 // push to local node
602 if (!tx.AcceptToMemoryPool(txdb))
603 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected");
605 SyncWithWallets(tx, NULL, true);
607 RelayTransaction(tx, hashTx);
609 return hashTx.GetHex();
612 Value createmultisig(const Array& params, bool fHelp)
614 if (fHelp || params.size() < 2 || params.size() > 3)
616 string msg = "createmultisig <nrequired> <'[\"key\",\"key\"]'>\n"
617 "\nCreates a multi-signature address with n signature of m keys required.\n"
618 "It returns a json object with the address and redeemScript.";
619 throw runtime_error(msg);
622 int nRequired = params[0].get_int();
623 const Array& keys = params[1].get_array();
626 // Gather public keys
628 throw runtime_error("a multisignature address must require at least one key to redeem");
629 if ((int)keys.size() < nRequired)
631 strprintf("not enough keys supplied "
632 "(got %" PRIszu " keys, but need at least %d to redeem)", keys.size(), nRequired));
633 if (keys.size() > 16)
634 throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
635 std::vector<CKey> pubkeys;
636 pubkeys.resize(keys.size());
637 for (unsigned int i = 0; i < keys.size(); i++)
639 const std::string& ks = keys[i].get_str();
641 // Case 1: Bitcoin address and we have full public key:
642 CBitcoinAddress address(ks);
643 if (address.IsValid())
646 if (!address.GetKeyID(keyID))
648 strprintf("%s does not refer to a key",ks.c_str()));
650 if (!pwalletMain->GetPubKey(keyID, vchPubKey))
652 strprintf("no full public key for address %s",ks.c_str()));
653 if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey))
654 throw runtime_error(" Invalid public key: "+ks);
657 // Case 2: hex public key
660 CPubKey vchPubKey(ParseHex(ks));
661 if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey))
662 throw runtime_error(" Invalid public key: "+ks);
666 throw runtime_error(" Invalid public key: "+ks);
670 // Construct using pay-to-script-hash:
672 inner.SetMultisig(nRequired, pubkeys);
674 if (inner.size() > MAX_SCRIPT_ELEMENT_SIZE)
676 strprintf("redeemScript exceeds size limit: %" PRIszu " > %d", inner.size(), MAX_SCRIPT_ELEMENT_SIZE));
678 CScriptID innerID = inner.GetID();
679 CBitcoinAddress address(innerID);
682 result.push_back(Pair("address", address.ToString()));
683 result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));