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.
7 #include "bitcoinrpc.h"
8 #include "txdb-leveldb.h"
15 using namespace boost;
16 using namespace json_spirit;
18 void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex)
21 vector<CTxDestination> addresses;
24 out.push_back(Pair("asm", scriptPubKey.ToString()));
27 out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
29 if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired))
31 out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD)));
35 if (type != TX_NULL_DATA)
37 out.push_back(Pair("reqSigs", nRequired));
38 out.push_back(Pair("type", GetTxnOutputType(type)));
40 if (type == TX_PUBKEY_DROP)
42 vector<valtype> vSolutions;
43 Solver(scriptPubKey, type, vSolutions);
44 out.push_back(Pair("keyVariant", HexStr(vSolutions[0])));
45 out.push_back(Pair("R", HexStr(vSolutions[1])));
47 CMalleableKeyView view;
48 if (pwalletMain->CheckOwnership(CPubKey(vSolutions[0]), CPubKey(vSolutions[1]), view))
49 out.push_back(Pair("pubkeyPair", CBitcoinAddress(view.GetMalleablePubKey()).ToString()));
54 for (const CTxDestination& addr : addresses)
55 a.push_back(CBitcoinAddress(addr).ToString());
56 out.push_back(Pair("addresses", a));
61 out.push_back(Pair("type", GetTxnOutputType(type)));
65 void TxToJSON(const CTransaction& tx, const uint256& hashBlock, Object& entry)
67 entry.push_back(Pair("txid", tx.GetHash().GetHex()));
68 entry.push_back(Pair("version", tx.nVersion));
69 entry.push_back(Pair("time", (int64_t)tx.nTime));
70 entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
72 for (const CTxIn& txin : tx.vin)
76 in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
79 in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
80 in.push_back(Pair("vout", (int64_t)txin.prevout.n));
82 o.push_back(Pair("asm", txin.scriptSig.ToString()));
83 o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
84 in.push_back(Pair("scriptSig", o));
86 in.push_back(Pair("sequence", (int64_t)txin.nSequence));
89 entry.push_back(Pair("vin", vin));
91 for (unsigned int i = 0; i < tx.vout.size(); i++)
93 const CTxOut& txout = tx.vout[i];
95 out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
96 out.push_back(Pair("n", (int64_t)i));
98 ScriptPubKeyToJSON(txout.scriptPubKey, o, true);
99 out.push_back(Pair("scriptPubKey", o));
102 entry.push_back(Pair("vout", vout));
106 entry.push_back(Pair("blockhash", hashBlock.GetHex()));
107 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
108 if (mi != mapBlockIndex.end() && (*mi).second)
110 CBlockIndex* pindex = (*mi).second;
111 if (pindex->IsInMainChain())
113 entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight));
114 entry.push_back(Pair("time", (int64_t)pindex->nTime));
115 entry.push_back(Pair("blocktime", (int64_t)pindex->nTime));
118 entry.push_back(Pair("confirmations", 0));
123 Value getrawtransaction(const Array& params, bool fHelp)
125 if (fHelp || params.size() < 1 || params.size() > 2)
127 "getrawtransaction <txid> [verbose=0]\n"
128 "If verbose=0, returns a string that is\n"
129 "serialized, hex-encoded data for <txid>.\n"
130 "If verbose is non-zero, returns an Object\n"
131 "with information about <txid>.");
134 hash.SetHex(params[0].get_str());
136 bool fVerbose = false;
137 if (params.size() > 1)
138 fVerbose = (params[1].get_int() != 0);
141 uint256 hashBlock = 0;
142 if (!GetTransaction(hash, tx, hashBlock))
143 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
145 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
147 string strHex = HexStr(ssTx.begin(), ssTx.end());
153 result.push_back(Pair("hex", strHex));
154 TxToJSON(tx, hashBlock, result);
158 Value listunspent(const Array& params, bool fHelp)
160 if (fHelp || params.size() > 3)
162 "listunspent [minconf=1] [maxconf=9999999] [\"address\",...]\n"
163 "Returns array of unspent transaction outputs\n"
164 "with between minconf and maxconf (inclusive) confirmations.\n"
165 "Optionally filtered to only include txouts paid to specified addresses.\n"
166 "Results are an array of Objects, each of which has:\n"
167 "{txid, vout, scriptPubKey, amount, confirmations}");
169 RPCTypeCheck(params, {int_type, int_type, array_type});
172 if (params.size() > 0)
173 nMinDepth = params[0].get_int();
175 int nMaxDepth = 9999999;
176 if (params.size() > 1)
177 nMaxDepth = params[1].get_int();
179 set<CBitcoinAddress> setAddress;
180 if (params.size() > 2)
182 Array inputs = params[2].get_array();
183 for (Value& input : inputs)
185 CBitcoinAddress address(input.get_str());
186 if (!address.IsValid())
187 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid NovaCoin address: ")+input.get_str());
188 if (setAddress.count(address))
189 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str());
190 setAddress.insert(address);
195 vector<COutput> vecOutputs;
196 pwalletMain->AvailableCoins(vecOutputs, false);
197 for (const COutput& out : vecOutputs)
199 if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
202 if(setAddress.size())
204 CTxDestination address;
205 if(!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
208 if (!setAddress.count(address))
212 int64_t nValue = out.tx->vout[out.i].nValue;
213 const CScript& pk = out.tx->vout[out.i].scriptPubKey;
215 entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
216 entry.push_back(Pair("vout", out.i));
217 CTxDestination address;
218 if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
220 entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
221 if (pwalletMain->mapAddressBook.count(address))
222 entry.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
224 entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end())));
225 if (pk.IsPayToScriptHash())
227 CTxDestination address;
228 if (ExtractDestination(pk, address))
230 const CScriptID& hash = boost::get<CScriptID>(address);
231 CScript redeemScript;
232 if (pwalletMain->GetCScript(hash, redeemScript))
233 entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
236 entry.push_back(Pair("amount",ValueFromAmount(nValue)));
237 entry.push_back(Pair("confirmations",out.nDepth));
238 entry.push_back(Pair("spendable", out.fSpendable));
239 results.push_back(entry);
245 Value createrawtransaction(const Array& params, bool fHelp)
247 if (fHelp || params.size() > 3 || params.size() < 2)
249 "createrawtransaction <'[{\"txid\":txid,\"vout\":n},...]'> <'{address:amount,...}'> [hex data]\n"
250 "Create a transaction spending given inputs\n"
251 "(array of objects containing transaction id and output number),\n"
252 "sending to given address(es),\n"
253 "optional data to add into data-carrying output.\n"
254 "Returns hex-encoded raw transaction.\n"
255 "Note that the transaction's inputs are not signed, and\n"
256 "it is not stored in the wallet or transmitted to the network.");
258 RPCTypeCheck(params, {array_type, obj_type});
260 Array inputs = params[0].get_array();
261 Object sendTo = params[1].get_obj();
265 for (Value& input : inputs)
267 const Object& o = input.get_obj();
269 const Value& txid_v = find_value(o, "txid");
270 if (txid_v.type() != str_type)
271 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing txid key");
272 string txid = txid_v.get_str();
274 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
276 const Value& vout_v = find_value(o, "vout");
277 if (vout_v.type() != int_type)
278 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
279 int nOutput = vout_v.get_int();
281 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
283 CTxIn in(COutPoint(uint256(txid), nOutput));
284 rawTx.vin.push_back(in);
287 set<CBitcoinAddress> setAddress;
288 for (const Pair& s : sendTo)
290 // Create output destination script
291 CScript scriptPubKey;
292 CBitcoinAddress address(s.name_);
294 if (address.IsValid())
296 scriptPubKey.SetAddress(address);
298 // Don't perform duplication checking for pubkey-pair addresses
299 if (!address.IsPair())
301 if (setAddress.count(address))
302 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
303 setAddress.insert(address);
307 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid output destination: ")+s.name_);
309 int64_t nAmount = AmountFromValue(s.value_);
311 CTxOut out(nAmount, scriptPubKey);
312 rawTx.vout.push_back(out);
315 if (params.size() == 3)
317 // Data carrying output
318 CScript scriptPubKey;
319 scriptPubKey << OP_RETURN << ParseHex(params[2].get_str());
320 CTxOut out(0, scriptPubKey);
321 rawTx.vout.push_back(out);
324 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
326 return HexStr(ss.begin(), ss.end());
329 Value decoderawtransaction(const Array& params, bool fHelp)
331 if (fHelp || params.size() != 1)
333 "decoderawtransaction <hex string>\n"
334 "Return a JSON object representing the serialized, hex-encoded transaction.");
336 RPCTypeCheck(params, {str_type});
338 vector<unsigned char> txData(ParseHex(params[0].get_str()));
339 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
344 catch (const std::exception&) {
345 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
349 TxToJSON(tx, 0, result);
354 Value decodescript(const Array& params, bool fHelp)
356 if (fHelp || params.size() != 1)
358 "decodescript <hex string>\n"
359 "Decode a hex-encoded script.");
361 RPCTypeCheck(params, {str_type});
365 if (params[0].get_str().size() > 0){
366 vector<unsigned char> scriptData(ParseHexV(params[0], "argument"));
367 script = CScript(scriptData.begin(), scriptData.end());
369 // Empty scripts are valid
371 ScriptPubKeyToJSON(script, r, false);
373 r.push_back(Pair("p2sh", CBitcoinAddress(script.GetID()).ToString()));
377 Value signrawtransaction(const Array& params, bool fHelp)
379 if (fHelp || params.size() < 1 || params.size() > 4)
381 "signrawtransaction <hex string> '[{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex,\"redeemScript\":hex},...]' '[<privatekey1>,...]' [sighashtype=\"ALL\"]\n"
382 "Sign inputs for raw transaction (serialized, hex-encoded).\n"
383 "Second optional argument (may be null) is an array of previous transaction outputs that\n"
384 "this transaction depends on but may not yet be in the blockchain.\n"
385 "Third optional argument (may be null) is an array of base58-encoded private\n"
386 "keys that, if given, will be the only keys used to sign the transaction.\n"
387 "Fourth optional argument is a string that is one of six values; ALL, NONE, SINGLE or\n"
388 "ALL|ANYONECANPAY, NONE|ANYONECANPAY, SINGLE|ANYONECANPAY.\n"
389 "Returns json object with keys:\n"
390 " hex : raw transaction with signature(s) (hex-encoded string)\n"
391 " complete : 1 if transaction has a complete set of signature (0 if not)"
392 + HelpRequiringPassphrase());
394 RPCTypeCheck(params, {str_type, array_type, array_type, str_type}, true);
396 vector<unsigned char> txData(ParseHex(params[0].get_str()));
397 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
398 vector<CTransaction> txVariants;
399 while (!ssData.empty())
404 txVariants.push_back(tx);
406 catch (const std::exception&) {
407 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
411 if (txVariants.empty())
412 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transaction");
414 // mergedTx will end up with all the signatures; it
415 // starts as a clone of the rawtx:
416 CTransaction mergedTx(txVariants[0]);
417 bool fComplete = true;
419 // Fetch previous transactions (inputs):
420 map<COutPoint, CScript> mapPrevOut;
421 for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
426 map<uint256, CTxIndex> unused;
429 // FetchInputs aborts on failure, so we go one at a time.
430 tempTx.vin.push_back(mergedTx.vin[i]);
431 tempTx.FetchInputs(txdb, unused, false, false, mapPrevTx, fInvalid);
433 // Copy results into mapPrevOut:
434 for (const CTxIn& txin : tempTx.vin)
436 const uint256& prevHash = txin.prevout.hash;
437 if (mapPrevTx.count(prevHash) && mapPrevTx[prevHash].second.vout.size()>txin.prevout.n)
438 mapPrevOut[txin.prevout] = mapPrevTx[prevHash].second.vout[txin.prevout.n].scriptPubKey;
442 bool fGivenKeys = false;
443 CBasicKeyStore tempKeystore;
444 if (params.size() > 2 && params[2].type() != null_type)
447 Array keys = params[2].get_array();
450 CBitcoinSecret vchSecret;
451 bool fGood = vchSecret.SetString(k.get_str());
453 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
456 CSecret secret = vchSecret.GetSecret(fCompressed);
457 key.SetSecret(secret, fCompressed);
458 tempKeystore.AddKey(key);
462 EnsureWalletIsUnlocked();
464 // Add previous txouts given in the RPC call:
465 if (params.size() > 1 && params[1].type() != null_type)
467 Array prevTxs = params[1].get_array();
468 for (Value& p : prevTxs)
470 if (p.type() != obj_type)
471 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
473 Object prevOut = p.get_obj();
475 RPCTypeCheck(prevOut, {{"txid", str_type}, {"vout", int_type}, {"scriptPubKey", str_type}});
477 string txidHex = find_value(prevOut, "txid").get_str();
479 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "txid must be hexadecimal");
481 txid.SetHex(txidHex);
483 int nOut = find_value(prevOut, "vout").get_int();
485 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
487 string pkHex = find_value(prevOut, "scriptPubKey").get_str();
489 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "scriptPubKey must be hexadecimal");
490 vector<unsigned char> pkData(ParseHex(pkHex));
491 CScript scriptPubKey(pkData.begin(), pkData.end());
493 COutPoint outpoint(txid, nOut);
494 if (mapPrevOut.count(outpoint))
496 // Complain if scriptPubKey doesn't match
497 if (mapPrevOut[outpoint] != scriptPubKey)
499 string err("Previous output scriptPubKey mismatch:\n");
500 err = err + mapPrevOut[outpoint].ToString() + "\nvs:\n"+
501 scriptPubKey.ToString();
502 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
506 mapPrevOut[outpoint] = scriptPubKey;
508 // if redeemScript given and not using the local wallet (private keys
509 // given), add redeemScript to the tempKeystore so it can be signed:
510 Value v = find_value(prevOut, "redeemScript");
511 if (fGivenKeys && scriptPubKey.IsPayToScriptHash())
513 RPCTypeCheck(prevOut, {{"txid", str_type}, {"vout", int_type}, {"scriptPubKey", str_type}, {"redeemScript",str_type}});
514 Value v = find_value(prevOut, "redeemScript");
515 if (!(v == Value::null))
517 vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
518 CScript redeemScript(rsData.begin(), rsData.end());
519 tempKeystore.AddCScript(redeemScript);
525 const CKeyStore& keystore = (fGivenKeys ? tempKeystore : *pwalletMain);
527 int nHashType = SIGHASH_ALL;
528 if (params.size() > 3 && params[3].type() != null_type)
530 static map<string, int> mapSigHashValues =
532 {"ALL", SIGHASH_ALL},
533 {"ALL|ANYONECANPAY", SIGHASH_ALL|SIGHASH_ANYONECANPAY},
534 {"NONE", SIGHASH_NONE},
535 {"NONE|ANYONECANPAY", SIGHASH_NONE|SIGHASH_ANYONECANPAY},
536 {"SINGLE", SIGHASH_SINGLE},
537 {"SINGLE|ANYONECANPAY", SIGHASH_SINGLE|SIGHASH_ANYONECANPAY}
539 string strHashType = params[3].get_str();
540 if (mapSigHashValues.count(strHashType))
541 nHashType = mapSigHashValues[strHashType];
543 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param");
546 bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
549 for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
551 CTxIn& txin = mergedTx.vin[i];
552 if (mapPrevOut.count(txin.prevout) == 0)
557 const CScript& prevPubKey = mapPrevOut[txin.prevout];
559 txin.scriptSig.clear();
560 // Only sign SIGHASH_SINGLE if there's a corresponding output:
561 if (!fHashSingle || (i < mergedTx.vout.size()))
562 SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
564 // ... and merge in other signatures:
565 for (const CTransaction& txv : txVariants)
567 txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
569 if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, STRICT_FLAGS, 0))
574 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
576 result.push_back(Pair("hex", HexStr(ssTx.begin(), ssTx.end())));
577 result.push_back(Pair("complete", fComplete));
582 Value sendrawtransaction(const Array& params, bool fHelp)
584 if (fHelp || params.size() < 1 || params.size() > 1)
586 "sendrawtransaction <hex string>\n"
587 "Submits raw transaction (serialized, hex-encoded) to local node and network.");
589 RPCTypeCheck(params, {str_type});
591 // parse hex string from parameter
592 vector<unsigned char> txData(ParseHex(params[0].get_str()));
593 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
596 // deserialize binary data stream
600 catch (const std::exception&) {
601 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
603 uint256 hashTx = tx.GetHash();
605 // See if the transaction is already in a block
606 // or in the memory pool:
607 CTransaction existingTx;
608 uint256 hashBlock = 0;
609 if (GetTransaction(hashTx, existingTx, hashBlock))
612 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("transaction already in block ")+hashBlock.GetHex());
613 // Not in block, but already in the memory pool; will drop
614 // through to re-relay it.
618 // push to local node
620 if (!tx.AcceptToMemoryPool(txdb))
621 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected");
623 SyncWithWallets(tx, NULL, true);
625 RelayTransaction(tx, hashTx);
627 return hashTx.GetHex();
630 Value createmultisig(const Array& params, bool fHelp)
632 if (fHelp || params.size() < 2 || params.size() > 3)
634 string msg = "createmultisig <nrequired> <'[\"key\",\"key\"]'>\n"
635 "\nCreates a multi-signature address with n signature of m keys required.\n"
636 "It returns a json object with the address and redeemScript.";
637 throw runtime_error(msg);
640 int nRequired = params[0].get_int();
641 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<CPubKey> 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.IsFullyValid())
671 throw runtime_error(" Invalid public key: "+ks);
672 pubkeys[i] = vchPubKey;
675 // Case 2: hex public key
678 CPubKey vchPubKey(ParseHex(ks));
679 if (!vchPubKey.IsFullyValid())
680 throw runtime_error(" Invalid public key: "+ks);
681 pubkeys[i] = vchPubKey;
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())));