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)));
43 if (type == TX_PUBKEY_DROP)
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])));
52 BOOST_FOREACH(const CTxDestination& addr, addresses)
53 a.push_back(CBitcoinAddress(addr).ToString());
54 out.push_back(Pair("addresses", a));
58 out.push_back(Pair("type", GetTxnOutputType(type)));
62 void TxToJSON(const CTransaction& tx, const uint256& hashBlock, Object& entry)
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));
69 BOOST_FOREACH(const CTxIn& txin, tx.vin)
73 in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
76 in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
77 in.push_back(Pair("vout", (int64_t)txin.prevout.n));
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));
83 in.push_back(Pair("sequence", (int64_t)txin.nSequence));
86 entry.push_back(Pair("vin", vin));
88 for (unsigned int i = 0; i < tx.vout.size(); i++)
90 const CTxOut& txout = tx.vout[i];
92 out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
93 out.push_back(Pair("n", (int64_t)i));
95 ScriptPubKeyToJSON(txout.scriptPubKey, o, true);
96 out.push_back(Pair("scriptPubKey", o));
99 entry.push_back(Pair("vout", vout));
103 entry.push_back(Pair("blockhash", hashBlock.GetHex()));
104 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
105 if (mi != mapBlockIndex.end() && (*mi).second)
107 CBlockIndex* pindex = (*mi).second;
108 if (pindex->IsInMainChain())
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));
115 entry.push_back(Pair("confirmations", 0));
120 Value getrawtransaction(const Array& params, bool fHelp)
122 if (fHelp || params.size() < 1 || params.size() > 2)
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>.");
131 hash.SetHex(params[0].get_str());
133 bool fVerbose = false;
134 if (params.size() > 1)
135 fVerbose = (params[1].get_int() != 0);
138 uint256 hashBlock = 0;
139 if (!GetTransaction(hash, tx, hashBlock))
140 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
142 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
144 string strHex = HexStr(ssTx.begin(), ssTx.end());
150 result.push_back(Pair("hex", strHex));
151 TxToJSON(tx, hashBlock, result);
155 Value listunspent(const Array& params, bool fHelp)
157 if (fHelp || params.size() > 3)
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}");
166 RPCTypeCheck(params, list_of(int_type)(int_type)(array_type));
169 if (params.size() > 0)
170 nMinDepth = params[0].get_int();
172 int nMaxDepth = 9999999;
173 if (params.size() > 1)
174 nMaxDepth = params[1].get_int();
176 set<CBitcoinAddress> setAddress;
177 if (params.size() > 2)
179 Array inputs = params[2].get_array();
180 BOOST_FOREACH(Value& input, inputs)
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);
192 vector<COutput> vecOutputs;
193 pwalletMain->AvailableCoins(vecOutputs, false);
194 BOOST_FOREACH(const COutput& out, vecOutputs)
196 if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
199 if(setAddress.size())
201 CTxDestination address;
202 if(!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
205 if (!setAddress.count(address))
209 int64_t nValue = out.tx->vout[out.i].nValue;
210 const CScript& pk = out.tx->vout[out.i].scriptPubKey;
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))
217 entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
218 if (pwalletMain->mapAddressBook.count(address))
219 entry.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
221 entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end())));
222 if (pk.IsPayToScriptHash())
224 CTxDestination address;
225 if (ExtractDestination(pk, address))
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())));
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);
242 Value createrawtransaction(const Array& params, bool fHelp)
244 if (fHelp || params.size() > 3 || params.size() < 2)
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.");
255 RPCTypeCheck(params, list_of(array_type)(obj_type));
257 Array inputs = params[0].get_array();
258 Object sendTo = params[1].get_obj();
262 BOOST_FOREACH(Value& input, inputs)
264 const Object& o = input.get_obj();
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();
271 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
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();
278 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
280 CTxIn in(COutPoint(uint256(txid), nOutput));
281 rawTx.vin.push_back(in);
284 set<CBitcoinAddress> setAddress;
285 BOOST_FOREACH(const Pair& s, sendTo)
287 // Create output destination script
288 CScript scriptPubKey;
289 CBitcoinAddress address(s.name_);
290 if (!address.IsValid())
292 CMalleablePubKey mpk(s.name_);
294 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid output destination: ")+s.name_);
296 CPubKey keyVariant, R;
297 mpk.GetVariant(R, keyVariant);
298 scriptPubKey.SetDestination(R, keyVariant);
302 scriptPubKey.SetDestination(address.Get());
303 if (setAddress.count(address))
304 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
305 setAddress.insert(address);
308 int64_t nAmount = AmountFromValue(s.value_);
310 CTxOut out(nAmount, scriptPubKey);
311 rawTx.vout.push_back(out);
314 if (params.size() == 3)
316 // Data carrying output
317 CScript scriptPubKey;
318 scriptPubKey << OP_RETURN << ParseHex(params[2].get_str());
319 CTxOut out(0, scriptPubKey);
320 rawTx.vout.push_back(out);
323 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
325 return HexStr(ss.begin(), ss.end());
328 Value decoderawtransaction(const Array& params, bool fHelp)
330 if (fHelp || params.size() != 1)
332 "decoderawtransaction <hex string>\n"
333 "Return a JSON object representing the serialized, hex-encoded transaction.");
335 RPCTypeCheck(params, list_of(str_type));
337 vector<unsigned char> txData(ParseHex(params[0].get_str()));
338 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
343 catch (const std::exception&) {
344 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
348 TxToJSON(tx, 0, result);
353 Value decodescript(const Array& params, bool fHelp)
355 if (fHelp || params.size() != 1)
357 "decodescript <hex string>\n"
358 "Decode a hex-encoded script.");
360 RPCTypeCheck(params, list_of(str_type));
364 if (params[0].get_str().size() > 0){
365 vector<unsigned char> scriptData(ParseHexV(params[0], "argument"));
366 script = CScript(scriptData.begin(), scriptData.end());
368 // Empty scripts are valid
370 ScriptPubKeyToJSON(script, r, false);
372 r.push_back(Pair("p2sh", CBitcoinAddress(script.GetID()).ToString()));
376 Value signrawtransaction(const Array& params, bool fHelp)
378 if (fHelp || params.size() < 1 || params.size() > 4)
380 "signrawtransaction <hex string> '[{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex,\"redeemScript\":hex},...]' '[<privatekey1>,...]' [sighashtype=\"ALL\"]\n"
381 "Sign inputs for raw transaction (serialized, hex-encoded).\n"
382 "Second optional argument (may be null) is an array of previous transaction outputs that\n"
383 "this transaction depends on but may not yet be in the blockchain.\n"
384 "Third optional argument (may be null) is an array of base58-encoded private\n"
385 "keys that, if given, will be the only keys used to sign the transaction.\n"
386 "Fourth optional argument is a string that is one of six values; ALL, NONE, SINGLE or\n"
387 "ALL|ANYONECANPAY, NONE|ANYONECANPAY, SINGLE|ANYONECANPAY.\n"
388 "Returns json object with keys:\n"
389 " hex : raw transaction with signature(s) (hex-encoded string)\n"
390 " complete : 1 if transaction has a complete set of signature (0 if not)"
391 + HelpRequiringPassphrase());
393 RPCTypeCheck(params, list_of(str_type)(array_type)(array_type)(str_type), true);
395 vector<unsigned char> txData(ParseHex(params[0].get_str()));
396 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
397 vector<CTransaction> txVariants;
398 while (!ssData.empty())
403 txVariants.push_back(tx);
405 catch (const std::exception&) {
406 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
410 if (txVariants.empty())
411 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transaction");
413 // mergedTx will end up with all the signatures; it
414 // starts as a clone of the rawtx:
415 CTransaction mergedTx(txVariants[0]);
416 bool fComplete = true;
418 // Fetch previous transactions (inputs):
419 map<COutPoint, CScript> mapPrevOut;
420 for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
425 map<uint256, CTxIndex> unused;
428 // FetchInputs aborts on failure, so we go one at a time.
429 tempTx.vin.push_back(mergedTx.vin[i]);
430 tempTx.FetchInputs(txdb, unused, false, false, mapPrevTx, fInvalid);
432 // Copy results into mapPrevOut:
433 BOOST_FOREACH(const CTxIn& txin, tempTx.vin)
435 const uint256& prevHash = txin.prevout.hash;
436 if (mapPrevTx.count(prevHash) && mapPrevTx[prevHash].second.vout.size()>txin.prevout.n)
437 mapPrevOut[txin.prevout] = mapPrevTx[prevHash].second.vout[txin.prevout.n].scriptPubKey;
441 bool fGivenKeys = false;
442 CBasicKeyStore tempKeystore;
443 if (params.size() > 2 && params[2].type() != null_type)
446 Array keys = params[2].get_array();
447 BOOST_FOREACH(Value k, keys)
449 CBitcoinSecret vchSecret;
450 bool fGood = vchSecret.SetString(k.get_str());
452 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
455 CSecret secret = vchSecret.GetSecret(fCompressed);
456 key.SetSecret(secret, fCompressed);
457 tempKeystore.AddKey(key);
461 EnsureWalletIsUnlocked();
463 // Add previous txouts given in the RPC call:
464 if (params.size() > 1 && params[1].type() != null_type)
466 Array prevTxs = params[1].get_array();
467 BOOST_FOREACH(Value& p, prevTxs)
469 if (p.type() != obj_type)
470 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
472 Object prevOut = p.get_obj();
474 RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type));
476 string txidHex = find_value(prevOut, "txid").get_str();
478 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "txid must be hexadecimal");
480 txid.SetHex(txidHex);
482 int nOut = find_value(prevOut, "vout").get_int();
484 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
486 string pkHex = find_value(prevOut, "scriptPubKey").get_str();
488 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "scriptPubKey must be hexadecimal");
489 vector<unsigned char> pkData(ParseHex(pkHex));
490 CScript scriptPubKey(pkData.begin(), pkData.end());
492 COutPoint outpoint(txid, nOut);
493 if (mapPrevOut.count(outpoint))
495 // Complain if scriptPubKey doesn't match
496 if (mapPrevOut[outpoint] != scriptPubKey)
498 string err("Previous output scriptPubKey mismatch:\n");
499 err = err + mapPrevOut[outpoint].ToString() + "\nvs:\n"+
500 scriptPubKey.ToString();
501 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
505 mapPrevOut[outpoint] = scriptPubKey;
507 // if redeemScript given and not using the local wallet (private keys
508 // given), add redeemScript to the tempKeystore so it can be signed:
509 Value v = find_value(prevOut, "redeemScript");
510 if (fGivenKeys && scriptPubKey.IsPayToScriptHash())
512 RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type)("redeemScript",str_type));
513 Value v = find_value(prevOut, "redeemScript");
514 if (!(v == Value::null))
516 vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
517 CScript redeemScript(rsData.begin(), rsData.end());
518 tempKeystore.AddCScript(redeemScript);
524 const CKeyStore& keystore = (fGivenKeys ? tempKeystore : *pwalletMain);
526 int nHashType = SIGHASH_ALL;
527 if (params.size() > 3 && params[3].type() != null_type)
529 static map<string, int> mapSigHashValues =
530 boost::assign::map_list_of
531 (string("ALL"), int(SIGHASH_ALL))
532 (string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY))
533 (string("NONE"), int(SIGHASH_NONE))
534 (string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY))
535 (string("SINGLE"), int(SIGHASH_SINGLE))
536 (string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY))
538 string strHashType = params[3].get_str();
539 if (mapSigHashValues.count(strHashType))
540 nHashType = mapSigHashValues[strHashType];
542 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param");
545 bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
548 for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
550 CTxIn& txin = mergedTx.vin[i];
551 if (mapPrevOut.count(txin.prevout) == 0)
556 const CScript& prevPubKey = mapPrevOut[txin.prevout];
558 txin.scriptSig.clear();
559 // Only sign SIGHASH_SINGLE if there's a corresponding output:
560 if (!fHashSingle || (i < mergedTx.vout.size()))
561 SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
563 // ... and merge in other signatures:
564 BOOST_FOREACH(const CTransaction& txv, txVariants)
566 txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
568 if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, STRICT_FLAGS, 0))
573 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
575 result.push_back(Pair("hex", HexStr(ssTx.begin(), ssTx.end())));
576 result.push_back(Pair("complete", fComplete));
581 Value sendrawtransaction(const Array& params, bool fHelp)
583 if (fHelp || params.size() < 1 || params.size() > 1)
585 "sendrawtransaction <hex string>\n"
586 "Submits raw transaction (serialized, hex-encoded) to local node and network.");
588 RPCTypeCheck(params, list_of(str_type));
590 // parse hex string from parameter
591 vector<unsigned char> txData(ParseHex(params[0].get_str()));
592 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
595 // deserialize binary data stream
599 catch (const std::exception&) {
600 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
602 uint256 hashTx = tx.GetHash();
604 // See if the transaction is already in a block
605 // or in the memory pool:
606 CTransaction existingTx;
607 uint256 hashBlock = 0;
608 if (GetTransaction(hashTx, existingTx, hashBlock))
611 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("transaction already in block ")+hashBlock.GetHex());
612 // Not in block, but already in the memory pool; will drop
613 // through to re-relay it.
617 // push to local node
619 if (!tx.AcceptToMemoryPool(txdb))
620 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected");
622 SyncWithWallets(tx, NULL, true);
624 RelayTransaction(tx, hashTx);
626 return hashTx.GetHex();
629 Value createmultisig(const Array& params, bool fHelp)
631 if (fHelp || params.size() < 2 || params.size() > 3)
633 string msg = "createmultisig <nrequired> <'[\"key\",\"key\"]'>\n"
634 "\nCreates a multi-signature address with n signature of m keys required.\n"
635 "It returns a json object with the address and redeemScript.";
636 throw runtime_error(msg);
639 int nRequired = params[0].get_int();
640 const Array& keys = params[1].get_array();
643 // Gather public keys
645 throw runtime_error("a multisignature address must require at least one key to redeem");
646 if ((int)keys.size() < nRequired)
648 strprintf("not enough keys supplied "
649 "(got %" PRIszu " keys, but need at least %d to redeem)", keys.size(), nRequired));
650 if (keys.size() > 16)
651 throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
652 std::vector<CKey> pubkeys;
653 pubkeys.resize(keys.size());
654 for (unsigned int i = 0; i < keys.size(); i++)
656 const std::string& ks = keys[i].get_str();
658 // Case 1: Bitcoin address and we have full public key:
659 CBitcoinAddress address(ks);
660 if (address.IsValid())
663 if (!address.GetKeyID(keyID))
665 strprintf("%s does not refer to a key",ks.c_str()));
667 if (!pwalletMain->GetPubKey(keyID, vchPubKey))
669 strprintf("no full public key for address %s",ks.c_str()));
670 if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey))
671 throw runtime_error(" Invalid public key: "+ks);
674 // Case 2: hex public key
677 CPubKey vchPubKey(ParseHex(ks));
678 if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey))
679 throw runtime_error(" Invalid public key: "+ks);
683 throw runtime_error(" Invalid public key: "+ks);
687 // Construct using pay-to-script-hash:
689 inner.SetMultisig(nRequired, pubkeys);
691 if (inner.size() > MAX_SCRIPT_ELEMENT_SIZE)
693 strprintf("redeemScript exceeds size limit: %" PRIszu " > %d", inner.size(), MAX_SCRIPT_ELEMENT_SIZE));
695 CScriptID innerID = inner.GetID();
696 CBitcoinAddress address(innerID);
699 result.push_back(Pair("address", address.ToString()));
700 result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));