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 if (!Solver(scriptPubKey, type, vSolutions))
48 out.push_back(Pair("keyVariant", HexStr(vSolutions[0])));
49 out.push_back(Pair("R", HexStr(vSolutions[1])));
54 BOOST_FOREACH(const CTxDestination& addr, addresses)
55 a.push_back(CBitcoinAddress(addr).ToString());
56 out.push_back(Pair("addresses", a));
60 out.push_back(Pair("type", GetTxnOutputType(type)));
64 void TxToJSON(const CTransaction& tx, const uint256& hashBlock, Object& entry)
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));
71 BOOST_FOREACH(const CTxIn& txin, tx.vin)
75 in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
78 in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
79 in.push_back(Pair("vout", (int64_t)txin.prevout.n));
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));
85 in.push_back(Pair("sequence", (int64_t)txin.nSequence));
88 entry.push_back(Pair("vin", vin));
90 for (unsigned int i = 0; i < tx.vout.size(); i++)
92 const CTxOut& txout = tx.vout[i];
94 out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
95 out.push_back(Pair("n", (int64_t)i));
97 ScriptPubKeyToJSON(txout.scriptPubKey, o, true);
98 out.push_back(Pair("scriptPubKey", o));
101 entry.push_back(Pair("vout", vout));
105 entry.push_back(Pair("blockhash", hashBlock.GetHex()));
106 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
107 if (mi != mapBlockIndex.end() && (*mi).second)
109 CBlockIndex* pindex = (*mi).second;
110 if (pindex->IsInMainChain())
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));
117 entry.push_back(Pair("confirmations", 0));
122 Value getrawtransaction(const Array& params, bool fHelp)
124 if (fHelp || params.size() < 1 || params.size() > 2)
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>.");
133 hash.SetHex(params[0].get_str());
135 bool fVerbose = false;
136 if (params.size() > 1)
137 fVerbose = (params[1].get_int() != 0);
140 uint256 hashBlock = 0;
141 if (!GetTransaction(hash, tx, hashBlock))
142 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
144 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
146 string strHex = HexStr(ssTx.begin(), ssTx.end());
152 result.push_back(Pair("hex", strHex));
153 TxToJSON(tx, hashBlock, result);
157 Value listunspent(const Array& params, bool fHelp)
159 if (fHelp || params.size() > 3)
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}");
168 RPCTypeCheck(params, list_of(int_type)(int_type)(array_type));
171 if (params.size() > 0)
172 nMinDepth = params[0].get_int();
174 int nMaxDepth = 9999999;
175 if (params.size() > 1)
176 nMaxDepth = params[1].get_int();
178 set<CBitcoinAddress> setAddress;
179 if (params.size() > 2)
181 Array inputs = params[2].get_array();
182 BOOST_FOREACH(Value& input, inputs)
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);
194 vector<COutput> vecOutputs;
195 pwalletMain->AvailableCoins(vecOutputs, false);
196 BOOST_FOREACH(const COutput& out, vecOutputs)
198 if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
201 if(setAddress.size())
203 CTxDestination address;
204 if(!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
207 if (!setAddress.count(address))
211 int64_t nValue = out.tx->vout[out.i].nValue;
212 const CScript& pk = out.tx->vout[out.i].scriptPubKey;
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))
219 entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
220 if (pwalletMain->mapAddressBook.count(address))
221 entry.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
223 entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end())));
224 if (pk.IsPayToScriptHash())
226 CTxDestination address;
227 if (ExtractDestination(pk, address))
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())));
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);
244 Value createrawtransaction(const Array& params, bool fHelp)
246 if (fHelp || params.size() > 3 || params.size() < 2)
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.");
257 RPCTypeCheck(params, list_of(array_type)(obj_type));
259 Array inputs = params[0].get_array();
260 Object sendTo = params[1].get_obj();
264 BOOST_FOREACH(Value& input, inputs)
266 const Object& o = input.get_obj();
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();
273 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
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();
280 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
282 CTxIn in(COutPoint(uint256(txid), nOutput));
283 rawTx.vin.push_back(in);
286 set<CBitcoinAddress> setAddress;
287 BOOST_FOREACH(const Pair& s, sendTo)
289 // Create output destination script
290 CScript scriptPubKey;
291 CBitcoinAddress address(s.name_);
292 if (!address.IsValid())
294 CMalleablePubKey mpk(s.name_);
296 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid output destination: ")+s.name_);
298 CPubKey keyVariant, R;
299 mpk.GetVariant(R, keyVariant);
300 scriptPubKey.SetDestination(R, keyVariant);
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);
310 int64_t nAmount = AmountFromValue(s.value_);
312 CTxOut out(nAmount, scriptPubKey);
313 rawTx.vout.push_back(out);
316 if (params.size() == 3)
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);
325 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
327 return HexStr(ss.begin(), ss.end());
330 Value decoderawtransaction(const Array& params, bool fHelp)
332 if (fHelp || params.size() != 1)
334 "decoderawtransaction <hex string>\n"
335 "Return a JSON object representing the serialized, hex-encoded transaction.");
337 RPCTypeCheck(params, list_of(str_type));
339 vector<unsigned char> txData(ParseHex(params[0].get_str()));
340 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
345 catch (const std::exception&) {
346 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
350 TxToJSON(tx, 0, result);
355 Value decodescript(const Array& params, bool fHelp)
357 if (fHelp || params.size() != 1)
359 "decodescript <hex string>\n"
360 "Decode a hex-encoded script.");
362 RPCTypeCheck(params, list_of(str_type));
366 if (params[0].get_str().size() > 0){
367 vector<unsigned char> scriptData(ParseHexV(params[0], "argument"));
368 script = CScript(scriptData.begin(), scriptData.end());
370 // Empty scripts are valid
372 ScriptPubKeyToJSON(script, r, false);
374 r.push_back(Pair("p2sh", CBitcoinAddress(script.GetID()).ToString()));
378 Value signrawtransaction(const Array& params, bool fHelp)
380 if (fHelp || params.size() < 1 || params.size() > 4)
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());
395 RPCTypeCheck(params, list_of(str_type)(array_type)(array_type)(str_type), true);
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())
405 txVariants.push_back(tx);
407 catch (const std::exception&) {
408 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
412 if (txVariants.empty())
413 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transaction");
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;
420 // Fetch previous transactions (inputs):
421 map<COutPoint, CScript> mapPrevOut;
422 for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
427 map<uint256, CTxIndex> unused;
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);
434 // Copy results into mapPrevOut:
435 BOOST_FOREACH(const CTxIn& txin, tempTx.vin)
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;
443 bool fGivenKeys = false;
444 CBasicKeyStore tempKeystore;
445 if (params.size() > 2 && params[2].type() != null_type)
448 Array keys = params[2].get_array();
449 BOOST_FOREACH(Value k, keys)
451 CBitcoinSecret vchSecret;
452 bool fGood = vchSecret.SetString(k.get_str());
454 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
457 CSecret secret = vchSecret.GetSecret(fCompressed);
458 key.SetSecret(secret, fCompressed);
459 tempKeystore.AddKey(key);
463 EnsureWalletIsUnlocked();
465 // Add previous txouts given in the RPC call:
466 if (params.size() > 1 && params[1].type() != null_type)
468 Array prevTxs = params[1].get_array();
469 BOOST_FOREACH(Value& p, prevTxs)
471 if (p.type() != obj_type)
472 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
474 Object prevOut = p.get_obj();
476 RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type));
478 string txidHex = find_value(prevOut, "txid").get_str();
480 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "txid must be hexadecimal");
482 txid.SetHex(txidHex);
484 int nOut = find_value(prevOut, "vout").get_int();
486 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
488 string pkHex = find_value(prevOut, "scriptPubKey").get_str();
490 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "scriptPubKey must be hexadecimal");
491 vector<unsigned char> pkData(ParseHex(pkHex));
492 CScript scriptPubKey(pkData.begin(), pkData.end());
494 COutPoint outpoint(txid, nOut);
495 if (mapPrevOut.count(outpoint))
497 // Complain if scriptPubKey doesn't match
498 if (mapPrevOut[outpoint] != scriptPubKey)
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);
507 mapPrevOut[outpoint] = scriptPubKey;
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())
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))
518 vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
519 CScript redeemScript(rsData.begin(), rsData.end());
520 tempKeystore.AddCScript(redeemScript);
526 const CKeyStore& keystore = (fGivenKeys ? tempKeystore : *pwalletMain);
528 int nHashType = SIGHASH_ALL;
529 if (params.size() > 3 && params[3].type() != null_type)
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))
540 string strHashType = params[3].get_str();
541 if (mapSigHashValues.count(strHashType))
542 nHashType = mapSigHashValues[strHashType];
544 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param");
547 bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
550 for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
552 CTxIn& txin = mergedTx.vin[i];
553 if (mapPrevOut.count(txin.prevout) == 0)
558 const CScript& prevPubKey = mapPrevOut[txin.prevout];
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);
565 // ... and merge in other signatures:
566 BOOST_FOREACH(const CTransaction& txv, txVariants)
568 txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
570 if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, STRICT_FLAGS, 0))
575 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
577 result.push_back(Pair("hex", HexStr(ssTx.begin(), ssTx.end())));
578 result.push_back(Pair("complete", fComplete));
583 Value sendrawtransaction(const Array& params, bool fHelp)
585 if (fHelp || params.size() < 1 || params.size() > 1)
587 "sendrawtransaction <hex string>\n"
588 "Submits raw transaction (serialized, hex-encoded) to local node and network.");
590 RPCTypeCheck(params, list_of(str_type));
592 // parse hex string from parameter
593 vector<unsigned char> txData(ParseHex(params[0].get_str()));
594 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
597 // deserialize binary data stream
601 catch (const std::exception&) {
602 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
604 uint256 hashTx = tx.GetHash();
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))
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.
619 // push to local node
621 if (!tx.AcceptToMemoryPool(txdb))
622 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected");
624 SyncWithWallets(tx, NULL, true);
626 RelayTransaction(tx, hashTx);
628 return hashTx.GetHex();
631 Value createmultisig(const Array& params, bool fHelp)
633 if (fHelp || params.size() < 2 || params.size() > 3)
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);
641 int nRequired = params[0].get_int();
642 const Array& keys = params[1].get_array();
645 // Gather public keys
647 throw runtime_error("a multisignature address must require at least one key to redeem");
648 if ((int)keys.size() < nRequired)
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++)
658 const std::string& ks = keys[i].get_str();
660 // Case 1: Bitcoin address and we have full public key:
661 CBitcoinAddress address(ks);
662 if (address.IsValid())
665 if (!address.GetKeyID(keyID))
667 strprintf("%s does not refer to a key",ks.c_str()));
669 if (!pwalletMain->GetPubKey(keyID, vchPubKey))
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);
676 // Case 2: hex public key
679 CPubKey vchPubKey(ParseHex(ks));
680 if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey))
681 throw runtime_error(" Invalid public key: "+ks);
685 throw runtime_error(" Invalid public key: "+ks);
689 // Construct using pay-to-script-hash:
691 inner.SetMultisig(nRequired, pubkeys);
693 if (inner.size() > MAX_SCRIPT_ELEMENT_SIZE)
695 strprintf("redeemScript exceeds size limit: %" PRIszu " > %d", inner.size(), MAX_SCRIPT_ELEMENT_SIZE));
697 CScriptID innerID = inner.GetID();
698 CBitcoinAddress address(innerID);
701 result.push_back(Pair("address", address.ToString()));
702 result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));