1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 #include "clientversion.h"
12 #include "rpcserver.h"
16 #include "wallet/wallet.h"
17 #include "wallet/walletdb.h"
22 #include <boost/assign/list_of.hpp>
26 #include "zcash/Address.hpp"
31 * @note Do not add or change anything in the information returned by this
32 * method. `getinfo` exists for backwards-compatibility only. It combines
33 * information from wildly different sources in the program, which is a mess,
34 * and is thus planned to be deprecated eventually.
36 * Based on the source of the information, new information should be added to:
37 * - `getblockchaininfo`,
38 * - `getnetworkinfo` or
41 * Or alternatively, create a specific query method for the information.
44 int32_t Jumblr_depositaddradd(char *depositaddr);
45 int32_t Jumblr_secretaddradd(char *secretaddr);
46 uint64_t komodo_interestsum();
47 int32_t komodo_longestchain();
48 int32_t komodo_notarized_height(uint256 *hashp,uint256 *txidp);
49 int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp);
50 extern int32_t KOMODO_LASTMINED,JUMBLR_PAUSE;
51 extern char ASSETCHAINS_SYMBOL[];
52 int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp);
53 #define KOMODO_VERSION "0.1.1"
55 UniValue getinfo(const UniValue& params, bool fHelp)
57 uint256 notarized_hash,notarized_desttxid; int32_t notarized_height,longestchain,kmdnotarized_height,txid_height;
58 if (fHelp || params.size() != 0)
61 "Returns an object containing various state info.\n"
64 " \"version\": xxxxx, (numeric) the server version\n"
65 " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
66 " \"walletversion\": xxxxx, (numeric) the wallet version\n"
67 " \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n"
68 " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
69 " \"timeoffset\": xxxxx, (numeric) the time offset\n"
70 " \"connections\": xxxxx, (numeric) the number of connections\n"
71 " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n"
72 " \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
73 " \"testnet\": true|false, (boolean) if the server is using testnet or not\n"
74 " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
75 " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
76 " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
77 " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in btc/kb\n"
78 " \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n"
79 " \"errors\": \"...\" (string) any error messages\n"
82 + HelpExampleCli("getinfo", "")
83 + HelpExampleRpc("getinfo", "")
87 LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
93 GetProxy(NET_IPV4, proxy);
94 notarized_height = komodo_notarized_height(¬arized_hash,¬arized_desttxid);
96 UniValue obj(UniValue::VOBJ);
97 obj.push_back(Pair("version", CLIENT_VERSION));
98 obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
99 obj.push_back(Pair("KMDversion", KOMODO_VERSION));
100 obj.push_back(Pair("notarized", notarized_height));
101 obj.push_back(Pair("notarizedhash", notarized_hash.ToString()));
102 obj.push_back(Pair("notarizedtxid", notarized_desttxid.ToString()));
103 txid_height = notarizedtxid_height(ASSETCHAINS_SYMBOL[0] != 0 ? (char *)"KMD" : (char *)"BTC",(char *)notarized_desttxid.ToString().c_str(),&kmdnotarized_height);
104 if ( txid_height > 0 )
105 obj.push_back(Pair("notarizedtxid_height", txid_height));
106 else obj.push_back(Pair("notarizedtxid_height", "mempool"));
107 if ( ASSETCHAINS_SYMBOL[0] != 0 )
108 obj.push_back(Pair("KMDnotarized_height", kmdnotarized_height));
109 obj.push_back(Pair("notarized_confirms", txid_height < kmdnotarized_height ? (kmdnotarized_height - txid_height + 1) : 0));
112 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
113 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
114 if ( ASSETCHAINS_SYMBOL[0] == 0 )
115 obj.push_back(Pair("interest", ValueFromAmount(komodo_interestsum())));
118 obj.push_back(Pair("blocks", (int)chainActive.Height()));
119 if ( (longestchain= komodo_longestchain()) != 0 && chainActive.Height() > longestchain )
120 longestchain = chainActive.Height();
121 obj.push_back(Pair("longestchain", longestchain));
122 obj.push_back(Pair("timeoffset", GetTimeOffset()));
123 if ( chainActive.Tip() != 0 )
124 obj.push_back(Pair("tiptime", (int)chainActive.Tip()->nTime));
125 obj.push_back(Pair("connections", (int)vNodes.size()));
126 obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string())));
127 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
128 obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
131 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
132 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
134 if (pwalletMain && pwalletMain->IsCrypted())
135 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
136 obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
138 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
139 obj.push_back(Pair("errors", GetWarnings("statusbar")));
141 char pubkeystr[65]; int32_t notaryid;
142 if ( (notaryid= komodo_whoami(pubkeystr,(int32_t)chainActive.Tip()->nHeight,(int32_t)(uint32_t)(uint32_t)chainActive.Tip()->GetBlocktime())) >= 0 )
144 obj.push_back(Pair("notaryid", notaryid));
145 obj.push_back(Pair("pubkey", pubkeystr));
146 if ( KOMODO_LASTMINED != 0 )
147 obj.push_back(Pair("lastmined", KOMODO_LASTMINED));
154 class DescribeAddressVisitor : public boost::static_visitor<UniValue>
157 UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
159 UniValue operator()(const CKeyID &keyID) const {
160 UniValue obj(UniValue::VOBJ);
162 obj.push_back(Pair("isscript", false));
163 if (pwalletMain && pwalletMain->GetPubKey(keyID, vchPubKey)) {
164 obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
165 obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
170 UniValue operator()(const CScriptID &scriptID) const {
171 UniValue obj(UniValue::VOBJ);
173 obj.push_back(Pair("isscript", true));
174 if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) {
175 std::vector<CTxDestination> addresses;
176 txnouttype whichType;
178 ExtractDestinations(subscript, whichType, addresses, nRequired);
179 obj.push_back(Pair("script", GetTxnOutputType(whichType)));
180 obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
181 UniValue a(UniValue::VARR);
182 BOOST_FOREACH(const CTxDestination& addr, addresses)
183 a.push_back(CBitcoinAddress(addr).ToString());
184 obj.push_back(Pair("addresses", a));
185 if (whichType == TX_MULTISIG)
186 obj.push_back(Pair("sigsrequired", nRequired));
193 UniValue jumblr_deposit(const UniValue& params, bool fHelp)
195 int32_t retval; UniValue result(UniValue::VOBJ);
196 if (fHelp || params.size() != 1)
197 throw runtime_error("jumblr_deposit \"depositaddress\"\n");
198 CBitcoinAddress address(params[0].get_str());
199 bool isValid = address.IsValid();
202 string addr = params[0].get_str();
203 if ( (retval= Jumblr_depositaddradd((char *)addr.c_str())) >= 0 )
204 result.push_back(Pair("result", retval));
205 else result.push_back(Pair("error", retval));
206 } else result.push_back(Pair("error", "invalid address"));
210 UniValue jumblr_secret(const UniValue& params, bool fHelp)
212 int32_t retval; UniValue result(UniValue::VOBJ);
213 if (fHelp || params.size() != 1)
214 throw runtime_error("jumblr_secret \"secretaddress\"\n");
215 CBitcoinAddress address(params[0].get_str());
216 bool isValid = address.IsValid();
219 string addr = params[0].get_str();
220 retval = Jumblr_secretaddradd((char *)addr.c_str());
221 result.push_back(Pair("result", "success"));
222 result.push_back(Pair("num", retval));
223 } else result.push_back(Pair("error", "invalid address"));
227 UniValue jumblr_pause(const UniValue& params, bool fHelp)
229 int32_t retval; UniValue result(UniValue::VOBJ);
231 throw runtime_error("jumblr_pause\n");
233 result.push_back(Pair("result", "paused"));
237 UniValue jumblr_resume(const UniValue& params, bool fHelp)
239 int32_t retval; UniValue result(UniValue::VOBJ);
241 throw runtime_error("jumblr_resume\n");
243 result.push_back(Pair("result", "resumed"));
247 UniValue validateaddress(const UniValue& params, bool fHelp)
249 if (fHelp || params.size() != 1)
251 "validateaddress \"bitcoinaddress\"\n"
252 "\nReturn information about the given bitcoin address.\n"
254 "1. \"bitcoinaddress\" (string, required) The bitcoin address to validate\n"
257 " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
258 " \"address\" : \"bitcoinaddress\", (string) The bitcoin address validated\n"
259 " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
260 " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
261 " \"isscript\" : true|false, (boolean) If the key is a script\n"
262 " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
263 " \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
264 " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
267 + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
268 + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
272 LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
277 CBitcoinAddress address(params[0].get_str());
278 bool isValid = address.IsValid();
280 UniValue ret(UniValue::VOBJ);
281 ret.push_back(Pair("isvalid", isValid));
284 CTxDestination dest = address.Get();
285 string currentAddress = address.ToString();
286 ret.push_back(Pair("address", currentAddress));
288 CScript scriptPubKey = GetScriptForDestination(dest);
289 ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
292 isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
293 ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
294 ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
295 UniValue detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
297 if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
298 ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
305 UniValue z_validateaddress(const UniValue& params, bool fHelp)
307 if (fHelp || params.size() != 1)
309 "z_validateaddress \"zaddr\"\n"
310 "\nReturn information about the given z address.\n"
312 "1. \"zaddr\" (string, required) The z address to validate\n"
315 " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
316 " \"address\" : \"zaddr\", (string) The z address validated\n"
317 " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
318 " \"payingkey\" : \"hex\", (string) The hex value of the paying key, a_pk\n"
319 " \"transmissionkey\" : \"hex\", (string) The hex value of the transmission key, pk_enc\n"
323 + HelpExampleCli("validateaddress", "\"zcWsmqT4X2V4jgxbgiCzyrAfRT1vi1F4sn7M5Pkh66izzw8Uk7LBGAH3DtcSMJeUb2pi3W4SQF8LMKkU2cUuVP68yAGcomL\"")
328 LOCK2(cs_main, pwalletMain->cs_wallet);
333 bool isValid = false;
335 std::string payingKey, transmissionKey;
337 string strAddress = params[0].get_str();
339 CZCPaymentAddress address(strAddress);
340 libzcash::PaymentAddress addr = address.Get();
343 isMine = pwalletMain->HaveSpendingKey(addr);
345 payingKey = addr.a_pk.GetHex();
346 transmissionKey = addr.pk_enc.GetHex();
348 } catch (std::runtime_error e) {
349 // address is invalid, nop here as isValid is false.
352 UniValue ret(UniValue::VOBJ);
353 ret.push_back(Pair("isvalid", isValid));
356 ret.push_back(Pair("address", strAddress));
357 ret.push_back(Pair("payingkey", payingKey));
358 ret.push_back(Pair("transmissionkey", transmissionKey));
360 ret.push_back(Pair("ismine", isMine));
368 * Used by addmultisigaddress / createmultisig:
370 CScript _createmultisig_redeemScript(const UniValue& params)
372 int nRequired = params[0].get_int();
373 const UniValue& keys = params[1].get_array();
375 // Gather public keys
377 throw runtime_error("a multisignature address must require at least one key to redeem");
378 if ((int)keys.size() < nRequired)
380 strprintf("not enough keys supplied "
381 "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
382 if (keys.size() > 16)
383 throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
384 std::vector<CPubKey> pubkeys;
385 pubkeys.resize(keys.size());
386 for (unsigned int i = 0; i < keys.size(); i++)
388 const std::string& ks = keys[i].get_str();
390 // Case 1: Bitcoin address and we have full public key:
391 CBitcoinAddress address(ks);
392 if (pwalletMain && address.IsValid())
395 if (!address.GetKeyID(keyID))
397 strprintf("%s does not refer to a key",ks));
399 if (!pwalletMain->GetPubKey(keyID, vchPubKey))
401 strprintf("no full public key for address %s",ks));
402 if (!vchPubKey.IsFullyValid())
403 throw runtime_error(" Invalid public key: "+ks);
404 pubkeys[i] = vchPubKey;
407 // Case 2: hex public key
412 CPubKey vchPubKey(ParseHex(ks));
413 if (!vchPubKey.IsFullyValid())
414 throw runtime_error(" Invalid public key: "+ks);
415 pubkeys[i] = vchPubKey;
419 throw runtime_error(" Invalid public key: "+ks);
422 CScript result = GetScriptForMultisig(nRequired, pubkeys);
424 if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
426 strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
431 UniValue createmultisig(const UniValue& params, bool fHelp)
433 if (fHelp || params.size() < 2 || params.size() > 2)
435 string msg = "createmultisig nrequired [\"key\",...]\n"
436 "\nCreates a multi-signature address with n signature of m keys required.\n"
437 "It returns a json object with the address and redeemScript.\n"
440 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
441 "2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
443 " \"key\" (string) bitcoin address or hex-encoded public key\n"
449 " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
450 " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
454 "\nCreate a multisig address from 2 addresses\n"
455 + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
456 "\nAs a json rpc call\n"
457 + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
459 throw runtime_error(msg);
462 // Construct using pay-to-script-hash:
463 CScript inner = _createmultisig_redeemScript(params);
464 CScriptID innerID(inner);
465 CBitcoinAddress address(innerID);
467 UniValue result(UniValue::VOBJ);
468 result.push_back(Pair("address", address.ToString()));
469 result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
474 UniValue verifymessage(const UniValue& params, bool fHelp)
476 if (fHelp || params.size() != 3)
478 "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
479 "\nVerify a signed message\n"
481 "1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the signature.\n"
482 "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
483 "3. \"message\" (string, required) The message that was signed.\n"
485 "true|false (boolean) If the signature is verified or not.\n"
487 "\nUnlock the wallet for 30 seconds\n"
488 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
489 "\nCreate the signature\n"
490 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
491 "\nVerify the signature\n"
492 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
494 + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
499 string strAddress = params[0].get_str();
500 string strSign = params[1].get_str();
501 string strMessage = params[2].get_str();
503 CBitcoinAddress addr(strAddress);
505 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
508 if (!addr.GetKeyID(keyID))
509 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
511 bool fInvalid = false;
512 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
515 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
517 CHashWriter ss(SER_GETHASH, 0);
518 ss << strMessageMagic;
522 if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
525 return (pubkey.GetID() == keyID);
528 UniValue setmocktime(const UniValue& params, bool fHelp)
530 if (fHelp || params.size() != 1)
532 "setmocktime timestamp\n"
533 "\nSet the local time to given timestamp (-regtest only)\n"
535 "1. timestamp (integer, required) Unix seconds-since-epoch timestamp\n"
536 " Pass 0 to go back to using the system time."
539 if (!Params().MineBlocksOnDemand())
540 throw runtime_error("setmocktime for regression testing (-regtest mode) only");
542 // cs_vNodes is locked and node send/receive times are updated
543 // atomically with the time change to prevent peers from being
544 // disconnected because we think we haven't communicated with them
546 LOCK2(cs_main, cs_vNodes);
548 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
549 SetMockTime(params[0].get_int64());
551 uint64_t t = GetTime();
552 BOOST_FOREACH(CNode* pnode, vNodes) {
553 pnode->nLastSend = pnode->nLastRecv = t;