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 CBitcoinAddress address(s.name_);
288 if (!address.IsValid())
289 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid NovaCoin address: ")+s.name_);
291 if (setAddress.count(address))
292 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
293 setAddress.insert(address);
295 CScript scriptPubKey;
296 scriptPubKey.SetDestination(address.Get());
297 int64_t nAmount = AmountFromValue(s.value_);
299 CTxOut out(nAmount, scriptPubKey);
300 rawTx.vout.push_back(out);
303 if (params.size() == 3)
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);
312 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
314 return HexStr(ss.begin(), ss.end());
317 Value decoderawtransaction(const Array& params, bool fHelp)
319 if (fHelp || params.size() != 1)
321 "decoderawtransaction <hex string>\n"
322 "Return a JSON object representing the serialized, hex-encoded transaction.");
324 RPCTypeCheck(params, list_of(str_type));
326 vector<unsigned char> txData(ParseHex(params[0].get_str()));
327 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
332 catch (const std::exception&) {
333 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
337 TxToJSON(tx, 0, result);
342 Value decodescript(const Array& params, bool fHelp)
344 if (fHelp || params.size() != 1)
346 "decodescript <hex string>\n"
347 "Decode a hex-encoded script.");
349 RPCTypeCheck(params, list_of(str_type));
353 if (params[0].get_str().size() > 0){
354 vector<unsigned char> scriptData(ParseHexV(params[0], "argument"));
355 script = CScript(scriptData.begin(), scriptData.end());
357 // Empty scripts are valid
359 ScriptPubKeyToJSON(script, r, false);
361 r.push_back(Pair("p2sh", CBitcoinAddress(script.GetID()).ToString()));
365 Value signrawtransaction(const Array& params, bool fHelp)
367 if (fHelp || params.size() < 1 || params.size() > 4)
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());
382 RPCTypeCheck(params, list_of(str_type)(array_type)(array_type)(str_type), true);
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())
392 txVariants.push_back(tx);
394 catch (const std::exception&) {
395 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
399 if (txVariants.empty())
400 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transaction");
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;
407 // Fetch previous transactions (inputs):
408 map<COutPoint, CScript> mapPrevOut;
409 for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
414 map<uint256, CTxIndex> unused;
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);
421 // Copy results into mapPrevOut:
422 BOOST_FOREACH(const CTxIn& txin, tempTx.vin)
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;
430 bool fGivenKeys = false;
431 CBasicKeyStore tempKeystore;
432 if (params.size() > 2 && params[2].type() != null_type)
435 Array keys = params[2].get_array();
436 BOOST_FOREACH(Value k, keys)
438 CBitcoinSecret vchSecret;
439 bool fGood = vchSecret.SetString(k.get_str());
441 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
444 CSecret secret = vchSecret.GetSecret(fCompressed);
445 key.SetSecret(secret, fCompressed);
446 tempKeystore.AddKey(key);
450 EnsureWalletIsUnlocked();
452 // Add previous txouts given in the RPC call:
453 if (params.size() > 1 && params[1].type() != null_type)
455 Array prevTxs = params[1].get_array();
456 BOOST_FOREACH(Value& p, prevTxs)
458 if (p.type() != obj_type)
459 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
461 Object prevOut = p.get_obj();
463 RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type));
465 string txidHex = find_value(prevOut, "txid").get_str();
467 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "txid must be hexadecimal");
469 txid.SetHex(txidHex);
471 int nOut = find_value(prevOut, "vout").get_int();
473 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
475 string pkHex = find_value(prevOut, "scriptPubKey").get_str();
477 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "scriptPubKey must be hexadecimal");
478 vector<unsigned char> pkData(ParseHex(pkHex));
479 CScript scriptPubKey(pkData.begin(), pkData.end());
481 COutPoint outpoint(txid, nOut);
482 if (mapPrevOut.count(outpoint))
484 // Complain if scriptPubKey doesn't match
485 if (mapPrevOut[outpoint] != scriptPubKey)
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);
494 mapPrevOut[outpoint] = scriptPubKey;
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())
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))
505 vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
506 CScript redeemScript(rsData.begin(), rsData.end());
507 tempKeystore.AddCScript(redeemScript);
513 const CKeyStore& keystore = (fGivenKeys ? tempKeystore : *pwalletMain);
515 int nHashType = SIGHASH_ALL;
516 if (params.size() > 3 && params[3].type() != null_type)
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))
527 string strHashType = params[3].get_str();
528 if (mapSigHashValues.count(strHashType))
529 nHashType = mapSigHashValues[strHashType];
531 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param");
534 bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
537 for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
539 CTxIn& txin = mergedTx.vin[i];
540 if (mapPrevOut.count(txin.prevout) == 0)
545 const CScript& prevPubKey = mapPrevOut[txin.prevout];
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);
552 // ... and merge in other signatures:
553 BOOST_FOREACH(const CTransaction& txv, txVariants)
555 txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
557 if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, STRICT_FLAGS, 0))
562 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
564 result.push_back(Pair("hex", HexStr(ssTx.begin(), ssTx.end())));
565 result.push_back(Pair("complete", fComplete));
570 Value sendrawtransaction(const Array& params, bool fHelp)
572 if (fHelp || params.size() < 1 || params.size() > 1)
574 "sendrawtransaction <hex string>\n"
575 "Submits raw transaction (serialized, hex-encoded) to local node and network.");
577 RPCTypeCheck(params, list_of(str_type));
579 // parse hex string from parameter
580 vector<unsigned char> txData(ParseHex(params[0].get_str()));
581 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
584 // deserialize binary data stream
588 catch (const std::exception&) {
589 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
591 uint256 hashTx = tx.GetHash();
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))
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.
606 // push to local node
608 if (!tx.AcceptToMemoryPool(txdb))
609 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected");
611 SyncWithWallets(tx, NULL, true);
613 RelayTransaction(tx, hashTx);
615 return hashTx.GetHex();
618 Value createmultisig(const Array& params, bool fHelp)
620 if (fHelp || params.size() < 2 || params.size() > 3)
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);
628 int nRequired = params[0].get_int();
629 const Array& keys = params[1].get_array();
632 // Gather public keys
634 throw runtime_error("a multisignature address must require at least one key to redeem");
635 if ((int)keys.size() < nRequired)
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++)
645 const std::string& ks = keys[i].get_str();
647 // Case 1: Bitcoin address and we have full public key:
648 CBitcoinAddress address(ks);
649 if (address.IsValid())
652 if (!address.GetKeyID(keyID))
654 strprintf("%s does not refer to a key",ks.c_str()));
656 if (!pwalletMain->GetPubKey(keyID, vchPubKey))
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);
663 // Case 2: hex public key
666 CPubKey vchPubKey(ParseHex(ks));
667 if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey))
668 throw runtime_error(" Invalid public key: "+ks);
672 throw runtime_error(" Invalid public key: "+ks);
676 // Construct using pay-to-script-hash:
678 inner.SetMultisig(nRequired, pubkeys);
680 if (inner.size() > MAX_SCRIPT_ELEMENT_SIZE)
682 strprintf("redeemScript exceeds size limit: %" PRIszu " > %d", inner.size(), MAX_SCRIPT_ELEMENT_SIZE));
684 CScriptID innerID = inner.GetID();
685 CBitcoinAddress address(innerID);
688 result.push_back(Pair("address", address.ToString()));
689 result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));