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"
14 using namespace json_spirit;
16 void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex)
19 std::vector<CTxDestination> addresses;
22 out.push_back(Pair("asm", scriptPubKey.ToString()));
25 out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
27 if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired))
29 out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD)));
33 if (type != TX_NULL_DATA)
35 out.push_back(Pair("reqSigs", nRequired));
36 out.push_back(Pair("type", GetTxnOutputType(type)));
38 if (type == TX_PUBKEY_DROP)
40 std::vector<valtype> vSolutions;
41 Solver(scriptPubKey, type, vSolutions);
42 out.push_back(Pair("keyVariant", HexStr(vSolutions[0])));
43 out.push_back(Pair("R", HexStr(vSolutions[1])));
45 CMalleableKeyView view;
46 if (pwalletMain->CheckOwnership(CPubKey(vSolutions[0]), CPubKey(vSolutions[1]), view))
47 out.push_back(Pair("pubkeyPair", CBitcoinAddress(view.GetMalleablePubKey()).ToString()));
52 for (const CTxDestination& addr : addresses)
53 a.push_back(CBitcoinAddress(addr).ToString());
54 out.push_back(Pair("addresses", a));
59 out.push_back(Pair("type", GetTxnOutputType(type)));
63 void TxToJSON(const CTransaction& tx, const uint256& hashBlock, Object& entry)
65 entry.push_back(Pair("txid", tx.GetHash().GetHex()));
66 entry.push_back(Pair("version", tx.nVersion));
67 entry.push_back(Pair("time", (int64_t)tx.nTime));
68 entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
70 for (const CTxIn& txin : tx.vin)
74 in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
77 in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
78 in.push_back(Pair("vout", (int64_t)txin.prevout.n));
80 o.push_back(Pair("asm", txin.scriptSig.ToString()));
81 o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
82 in.push_back(Pair("scriptSig", o));
84 in.push_back(Pair("sequence", (int64_t)txin.nSequence));
87 entry.push_back(Pair("vin", vin));
89 for (unsigned int i = 0; i < tx.vout.size(); i++)
91 const CTxOut& txout = tx.vout[i];
93 out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
94 out.push_back(Pair("n", (int64_t)i));
96 ScriptPubKeyToJSON(txout.scriptPubKey, o, true);
97 out.push_back(Pair("scriptPubKey", o));
100 entry.push_back(Pair("vout", vout));
104 entry.push_back(Pair("blockhash", hashBlock.GetHex()));
105 std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
106 if (mi != mapBlockIndex.end() && (*mi).second)
108 CBlockIndex* pindex = (*mi).second;
109 if (pindex->IsInMainChain())
111 entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight));
112 entry.push_back(Pair("time", (int64_t)pindex->nTime));
113 entry.push_back(Pair("blocktime", (int64_t)pindex->nTime));
116 entry.push_back(Pair("confirmations", 0));
121 Value getrawtransaction(const Array& params, bool fHelp)
123 if (fHelp || params.size() < 1 || params.size() > 2)
124 throw std::runtime_error(
125 "getrawtransaction <txid> [verbose=0]\n"
126 "If verbose=0, returns a string that is\n"
127 "serialized, hex-encoded data for <txid>.\n"
128 "If verbose is non-zero, returns an Object\n"
129 "with information about <txid>.");
132 hash.SetHex(params[0].get_str());
134 bool fVerbose = false;
135 if (params.size() > 1)
136 fVerbose = (params[1].get_int() != 0);
139 uint256 hashBlock = 0;
140 if (!GetTransaction(hash, tx, hashBlock))
141 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
143 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
145 std::string strHex = HexStr(ssTx.begin(), ssTx.end());
151 result.push_back(Pair("hex", strHex));
152 TxToJSON(tx, hashBlock, result);
156 Value listunspent(const Array& params, bool fHelp)
158 if (fHelp || params.size() > 3)
159 throw std::runtime_error(
160 "listunspent [minconf=1] [maxconf=9999999] [\"address\",...]\n"
161 "Returns array of unspent transaction outputs\n"
162 "with between minconf and maxconf (inclusive) confirmations.\n"
163 "Optionally filtered to only include txouts paid to specified addresses.\n"
164 "Results are an array of Objects, each of which has:\n"
165 "{txid, vout, scriptPubKey, amount, confirmations}");
167 RPCTypeCheck(params, {int_type, int_type, array_type});
170 if (params.size() > 0)
171 nMinDepth = params[0].get_int();
173 int nMaxDepth = 9999999;
174 if (params.size() > 1)
175 nMaxDepth = params[1].get_int();
177 std::set<CBitcoinAddress> setAddress;
178 if (params.size() > 2)
180 Array inputs = params[2].get_array();
181 for (Value& input : inputs)
183 CBitcoinAddress address(input.get_str());
184 if (!address.IsValid())
185 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid NovaCoin address: ")+input.get_str());
186 if (setAddress.count(address))
187 throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ")+input.get_str());
188 setAddress.insert(address);
193 std::vector<COutput> vecOutputs;
194 pwalletMain->AvailableCoins(vecOutputs, false);
195 for (const COutput& out : vecOutputs)
197 if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
200 if(setAddress.size())
202 CTxDestination address;
203 if(!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
206 if (!setAddress.count(address))
210 int64_t nValue = out.tx->vout[out.i].nValue;
211 const CScript& pk = out.tx->vout[out.i].scriptPubKey;
213 entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
214 entry.push_back(Pair("vout", out.i));
215 CTxDestination address;
216 if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
218 entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
219 if (pwalletMain->mapAddressBook.count(address))
220 entry.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
222 entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end())));
223 if (pk.IsPayToScriptHash())
225 CTxDestination address;
226 if (ExtractDestination(pk, address))
228 const CScriptID& hash = std::get<CScriptID>(address);
229 CScript redeemScript;
230 if (pwalletMain->GetCScript(hash, redeemScript))
231 entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
234 entry.push_back(Pair("amount",ValueFromAmount(nValue)));
235 entry.push_back(Pair("confirmations",out.nDepth));
236 entry.push_back(Pair("spendable", out.fSpendable));
237 results.push_back(entry);
243 Value createrawtransaction(const Array& params, bool fHelp)
245 if (fHelp || params.size() > 3 || params.size() < 2)
246 throw std::runtime_error(
247 "createrawtransaction <'[{\"txid\":txid,\"vout\":n},...]'> <'{address:amount,...}'> [hex data]\n"
248 "Create a transaction spending given inputs\n"
249 "(array of objects containing transaction id and output number),\n"
250 "sending to given address(es),\n"
251 "optional data to add into data-carrying output.\n"
252 "Returns hex-encoded raw transaction.\n"
253 "Note that the transaction's inputs are not signed, and\n"
254 "it is not stored in the wallet or transmitted to the network.");
256 RPCTypeCheck(params, {array_type, obj_type});
258 Array inputs = params[0].get_array();
259 Object sendTo = params[1].get_obj();
263 for (Value& input : inputs)
265 const Object& o = input.get_obj();
267 const Value& txid_v = find_value(o, "txid");
268 if (txid_v.type() != str_type)
269 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing txid key");
270 std::string txid = txid_v.get_str();
272 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
274 const Value& vout_v = find_value(o, "vout");
275 if (vout_v.type() != int_type)
276 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
277 int nOutput = vout_v.get_int();
279 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
281 CTxIn in(COutPoint(uint256(txid), nOutput));
282 rawTx.vin.push_back(in);
285 std::set<CBitcoinAddress> setAddress;
286 for (const Pair& s : sendTo)
288 // Create output destination script
289 CScript scriptPubKey;
290 CBitcoinAddress address(s.name_);
292 if (address.IsValid())
294 scriptPubKey.SetAddress(address);
296 // Don't perform duplication checking for pubkey-pair addresses
297 if (!address.IsPair())
299 if (setAddress.count(address))
300 throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ")+s.name_);
301 setAddress.insert(address);
305 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid output destination: ")+s.name_);
307 int64_t nAmount = AmountFromValue(s.value_);
309 CTxOut out(nAmount, scriptPubKey);
310 rawTx.vout.push_back(out);
313 if (params.size() == 3)
315 // Data carrying output
316 CScript scriptPubKey;
317 scriptPubKey << OP_RETURN << ParseHex(params[2].get_str());
318 CTxOut out(0, scriptPubKey);
319 rawTx.vout.push_back(out);
322 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
324 return HexStr(ss.begin(), ss.end());
327 Value decoderawtransaction(const Array& params, bool fHelp)
329 if (fHelp || params.size() != 1)
330 throw std::runtime_error(
331 "decoderawtransaction <hex string>\n"
332 "Return a JSON object representing the serialized, hex-encoded transaction.");
334 RPCTypeCheck(params, {str_type});
336 std::vector<unsigned char> txData(ParseHex(params[0].get_str()));
337 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
342 catch (const std::exception&) {
343 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
347 TxToJSON(tx, 0, result);
352 Value decodescript(const Array& params, bool fHelp)
354 if (fHelp || params.size() != 1)
355 throw std::runtime_error(
356 "decodescript <hex string>\n"
357 "Decode a hex-encoded script.");
359 RPCTypeCheck(params, {str_type});
363 if (params[0].get_str().size() > 0){
364 std::vector<unsigned char> scriptData(ParseHexV(params[0], "argument"));
365 script = CScript(scriptData.begin(), scriptData.end());
367 // Empty scripts are valid
369 ScriptPubKeyToJSON(script, r, false);
371 r.push_back(Pair("p2sh", CBitcoinAddress(script.GetID()).ToString()));
375 Value signrawtransaction(const Array& params, bool fHelp)
377 if (fHelp || params.size() < 1 || params.size() > 4)
378 throw std::runtime_error(
379 "signrawtransaction <hex string> '[{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex,\"redeemScript\":hex},...]' '[<privatekey1>,...]' [sighashtype=\"ALL\"]\n"
380 "Sign inputs for raw transaction (serialized, hex-encoded).\n"
381 "Second optional argument (may be null) is an array of previous transaction outputs that\n"
382 "this transaction depends on but may not yet be in the blockchain.\n"
383 "Third optional argument (may be null) is an array of base58-encoded private\n"
384 "keys that, if given, will be the only keys used to sign the transaction.\n"
385 "Fourth optional argument is a string that is one of six values; ALL, NONE, SINGLE or\n"
386 "ALL|ANYONECANPAY, NONE|ANYONECANPAY, SINGLE|ANYONECANPAY.\n"
387 "Returns json object with keys:\n"
388 " hex : raw transaction with signature(s) (hex-encoded string)\n"
389 " complete : 1 if transaction has a complete set of signature (0 if not)"
390 + HelpRequiringPassphrase());
392 RPCTypeCheck(params, {str_type, array_type, array_type, str_type}, true);
394 std::vector<unsigned char> txData(ParseHex(params[0].get_str()));
395 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
396 std::vector<CTransaction> txVariants;
397 while (!ssData.empty())
402 txVariants.push_back(tx);
404 catch (const std::exception&) {
405 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
409 if (txVariants.empty())
410 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transaction");
412 // mergedTx will end up with all the signatures; it
413 // starts as a clone of the rawtx:
414 CTransaction mergedTx(txVariants[0]);
415 bool fComplete = true;
417 // Fetch previous transactions (inputs):
418 std::map<COutPoint, CScript> mapPrevOut;
419 for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
424 std::map<uint256, CTxIndex> unused;
427 // FetchInputs aborts on failure, so we go one at a time.
428 tempTx.vin.push_back(mergedTx.vin[i]);
429 tempTx.FetchInputs(txdb, unused, false, false, mapPrevTx, fInvalid);
431 // Copy results into mapPrevOut:
432 for (const CTxIn& txin : tempTx.vin)
434 const uint256& prevHash = txin.prevout.hash;
435 if (mapPrevTx.count(prevHash) && mapPrevTx[prevHash].second.vout.size()>txin.prevout.n)
436 mapPrevOut[txin.prevout] = mapPrevTx[prevHash].second.vout[txin.prevout.n].scriptPubKey;
440 bool fGivenKeys = false;
441 CBasicKeyStore tempKeystore;
442 if (params.size() > 2 && params[2].type() != null_type)
445 Array keys = params[2].get_array();
448 CBitcoinSecret vchSecret;
449 bool fGood = vchSecret.SetString(k.get_str());
451 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
454 CSecret secret = vchSecret.GetSecret(fCompressed);
455 key.SetSecret(secret, fCompressed);
456 tempKeystore.AddKey(key);
460 EnsureWalletIsUnlocked();
462 // Add previous txouts given in the RPC call:
463 if (params.size() > 1 && params[1].type() != null_type)
465 Array prevTxs = params[1].get_array();
466 for (Value& p : prevTxs)
468 if (p.type() != obj_type)
469 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
471 Object prevOut = p.get_obj();
473 RPCTypeCheck(prevOut, {{"txid", str_type}, {"vout", int_type}, {"scriptPubKey", str_type}});
475 std::string txidHex = find_value(prevOut, "txid").get_str();
477 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "txid must be hexadecimal");
479 txid.SetHex(txidHex);
481 int nOut = find_value(prevOut, "vout").get_int();
483 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
485 std::string pkHex = find_value(prevOut, "scriptPubKey").get_str();
487 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "scriptPubKey must be hexadecimal");
488 std::vector<unsigned char> pkData(ParseHex(pkHex));
489 CScript scriptPubKey(pkData.begin(), pkData.end());
491 COutPoint outpoint(txid, nOut);
492 if (mapPrevOut.count(outpoint))
494 // Complain if scriptPubKey doesn't match
495 if (mapPrevOut[outpoint] != scriptPubKey)
497 std::string err("Previous output scriptPubKey mismatch:\n");
498 err = err + mapPrevOut[outpoint].ToString() + "\nvs:\n"+
499 scriptPubKey.ToString();
500 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
504 mapPrevOut[outpoint] = scriptPubKey;
506 // if redeemScript given and not using the local wallet (private keys
507 // given), add redeemScript to the tempKeystore so it can be signed:
508 Value v = find_value(prevOut, "redeemScript");
509 if (fGivenKeys && scriptPubKey.IsPayToScriptHash())
511 RPCTypeCheck(prevOut, {{"txid", str_type}, {"vout", int_type}, {"scriptPubKey", str_type}, {"redeemScript",str_type}});
512 Value v = find_value(prevOut, "redeemScript");
513 if (!(v == Value::null))
515 std::vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
516 CScript redeemScript(rsData.begin(), rsData.end());
517 tempKeystore.AddCScript(redeemScript);
523 const CKeyStore& keystore = (fGivenKeys ? tempKeystore : *pwalletMain);
525 int nHashType = SIGHASH_ALL;
526 if (params.size() > 3 && params[3].type() != null_type)
528 static std::map<std::string, int> mapSigHashValues =
530 {"ALL", SIGHASH_ALL},
531 {"ALL|ANYONECANPAY", SIGHASH_ALL|SIGHASH_ANYONECANPAY},
532 {"NONE", SIGHASH_NONE},
533 {"NONE|ANYONECANPAY", SIGHASH_NONE|SIGHASH_ANYONECANPAY},
534 {"SINGLE", SIGHASH_SINGLE},
535 {"SINGLE|ANYONECANPAY", SIGHASH_SINGLE|SIGHASH_ANYONECANPAY}
537 std::string strHashType = params[3].get_str();
538 if (mapSigHashValues.count(strHashType))
539 nHashType = mapSigHashValues[strHashType];
541 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param");
544 bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
547 for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
549 CTxIn& txin = mergedTx.vin[i];
550 if (mapPrevOut.count(txin.prevout) == 0)
555 const CScript& prevPubKey = mapPrevOut[txin.prevout];
557 txin.scriptSig.clear();
558 // Only sign SIGHASH_SINGLE if there's a corresponding output:
559 if (!fHashSingle || (i < mergedTx.vout.size()))
560 SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
562 // ... and merge in other signatures:
563 for (const CTransaction& txv : txVariants)
565 txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
567 if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, STRICT_FLAGS, 0))
572 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
574 result.push_back(Pair("hex", HexStr(ssTx.begin(), ssTx.end())));
575 result.push_back(Pair("complete", fComplete));
580 Value sendrawtransaction(const Array& params, bool fHelp)
582 if (fHelp || params.size() < 1 || params.size() > 1)
583 throw std::runtime_error(
584 "sendrawtransaction <hex string>\n"
585 "Submits raw transaction (serialized, hex-encoded) to local node and network.");
587 RPCTypeCheck(params, {str_type});
589 // parse hex string from parameter
590 std::vector<unsigned char> txData(ParseHex(params[0].get_str()));
591 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
594 // deserialize binary data stream
598 catch (const std::exception&) {
599 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
601 uint256 hashTx = tx.GetHash();
603 // See if the transaction is already in a block
604 // or in the memory pool:
605 CTransaction existingTx;
606 uint256 hashBlock = 0;
607 if (GetTransaction(hashTx, existingTx, hashBlock))
610 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("transaction already in block ")+hashBlock.GetHex());
611 // Not in block, but already in the memory pool; will drop
612 // through to re-relay it.
616 // push to local node
618 if (!tx.AcceptToMemoryPool(txdb))
619 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected");
621 SyncWithWallets(tx, NULL, true);
623 RelayTransaction(tx, hashTx);
625 return hashTx.GetHex();
628 Value createmultisig(const Array& params, bool fHelp)
630 if (fHelp || params.size() < 2 || params.size() > 3)
632 std::string msg = "createmultisig <nrequired> <'[\"key\",\"key\"]'>\n"
633 "\nCreates a multi-signature address with n signature of m keys required.\n"
634 "It returns a json object with the address and redeemScript.";
635 throw std::runtime_error(msg);
638 int nRequired = params[0].get_int();
639 const Array& keys = params[1].get_array();
641 // Gather public keys
643 throw std::runtime_error("a multisignature address must require at least one key to redeem");
644 if ((int)keys.size() < nRequired)
645 throw std::runtime_error(
646 strprintf("not enough keys supplied "
647 "(got %" PRIszu " keys, but need at least %d to redeem)", keys.size(), nRequired));
648 if (keys.size() > 16)
649 throw std::runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
650 std::vector<CPubKey> pubkeys;
651 pubkeys.resize(keys.size());
652 for (unsigned int i = 0; i < keys.size(); i++)
654 const std::string& ks = keys[i].get_str();
656 // Case 1: Bitcoin address and we have full public key:
657 CBitcoinAddress address(ks);
658 if (address.IsValid())
661 if (!address.GetKeyID(keyID))
662 throw std::runtime_error(
663 strprintf("%s does not refer to a key",ks.c_str()));
665 if (!pwalletMain->GetPubKey(keyID, vchPubKey))
666 throw std::runtime_error(
667 strprintf("no full public key for address %s",ks.c_str()));
668 if (!vchPubKey.IsFullyValid())
669 throw std::runtime_error(" Invalid public key: "+ks);
670 pubkeys[i] = vchPubKey;
673 // Case 2: hex public key
676 CPubKey vchPubKey(ParseHex(ks));
677 if (!vchPubKey.IsFullyValid())
678 throw std::runtime_error(" Invalid public key: "+ks);
679 pubkeys[i] = vchPubKey;
683 throw std::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)
692 throw std::runtime_error(
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())));