1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin 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"
22 #include <boost/assign/list_of.hpp>
23 #include "json/json_spirit_utils.h"
24 #include "json/json_spirit_value.h"
26 using namespace boost;
27 using namespace boost::assign;
28 using namespace json_spirit;
32 * @note Do not add or change anything in the information returned by this
33 * method. `getinfo` exists for backwards-compatibility only. It combines
34 * information from wildly different sources in the program, which is a mess,
35 * and is thus planned to be deprecated eventually.
37 * Based on the source of the information, new information should be added to:
38 * - `getblockchaininfo`,
39 * - `getnetworkinfo` or
42 * Or alternatively, create a specific query method for the information.
44 Value getinfo(const Array& params, bool fHelp)
46 if (fHelp || params.size() != 0)
49 "Returns an object containing various state info.\n"
52 " \"version\": xxxxx, (numeric) the server version\n"
53 " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
54 " \"walletversion\": xxxxx, (numeric) the wallet version\n"
55 " \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n"
56 " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
57 " \"timeoffset\": xxxxx, (numeric) the time offset\n"
58 " \"connections\": xxxxx, (numeric) the number of connections\n"
59 " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n"
60 " \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
61 " \"testnet\": true|false, (boolean) if the server is using testnet or not\n"
62 " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
63 " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
64 " \"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"
65 " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in btc/kb\n"
66 " \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n"
67 " \"errors\": \"...\" (string) any error messages\n"
70 + HelpExampleCli("getinfo", "")
71 + HelpExampleRpc("getinfo", "")
75 GetProxy(NET_IPV4, proxy);
78 obj.push_back(Pair("version", CLIENT_VERSION));
79 obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
82 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
83 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
86 obj.push_back(Pair("blocks", (int)chainActive.Height()));
87 obj.push_back(Pair("timeoffset", GetTimeOffset()));
88 obj.push_back(Pair("connections", (int)vNodes.size()));
89 obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.ToStringIPPort() : string())));
90 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
91 obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
94 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
95 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
97 if (pwalletMain && pwalletMain->IsCrypted())
98 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
99 obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
101 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
102 obj.push_back(Pair("errors", GetWarnings("statusbar")));
107 class DescribeAddressVisitor : public boost::static_visitor<Object>
113 DescribeAddressVisitor(isminetype mineIn) : mine(mineIn) {}
115 Object operator()(const CNoDestination &dest) const { return Object(); }
117 Object operator()(const CKeyID &keyID) const {
120 obj.push_back(Pair("isscript", false));
121 if (mine == ISMINE_SPENDABLE) {
122 pwalletMain->GetPubKey(keyID, vchPubKey);
123 obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
124 obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
129 Object operator()(const CScriptID &scriptID) const {
131 obj.push_back(Pair("isscript", true));
132 if (mine != ISMINE_NO) {
134 pwalletMain->GetCScript(scriptID, subscript);
135 std::vector<CTxDestination> addresses;
136 txnouttype whichType;
138 ExtractDestinations(subscript, whichType, addresses, nRequired);
139 obj.push_back(Pair("script", GetTxnOutputType(whichType)));
140 obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
142 BOOST_FOREACH(const CTxDestination& addr, addresses)
143 a.push_back(CBitcoinAddress(addr).ToString());
144 obj.push_back(Pair("addresses", a));
145 if (whichType == TX_MULTISIG)
146 obj.push_back(Pair("sigsrequired", nRequired));
153 Value validateaddress(const Array& params, bool fHelp)
155 if (fHelp || params.size() != 1)
157 "validateaddress \"bitcoinaddress\"\n"
158 "\nReturn information about the given bitcoin address.\n"
160 "1. \"bitcoinaddress\" (string, required) The bitcoin address to validate\n"
163 " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
164 " \"address\" : \"bitcoinaddress\", (string) The bitcoin address validated\n"
165 " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
166 " \"isscript\" : true|false, (boolean) If the key is a script\n"
167 " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
168 " \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
169 " \"account\" : \"account\" (string) The account associated with the address, \"\" is the default account\n"
172 + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
173 + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
176 CBitcoinAddress address(params[0].get_str());
177 bool isValid = address.IsValid();
180 ret.push_back(Pair("isvalid", isValid));
183 CTxDestination dest = address.Get();
184 string currentAddress = address.ToString();
185 ret.push_back(Pair("address", currentAddress));
187 isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
188 ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
189 if (mine != ISMINE_NO) {
190 ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
191 Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest);
192 ret.insert(ret.end(), detail.begin(), detail.end());
194 if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
195 ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
202 * Used by addmultisigaddress / createmultisig:
204 CScript _createmultisig_redeemScript(const Array& params)
206 int nRequired = params[0].get_int();
207 const Array& keys = params[1].get_array();
209 // Gather public keys
211 throw runtime_error("a multisignature address must require at least one key to redeem");
212 if ((int)keys.size() < nRequired)
214 strprintf("not enough keys supplied "
215 "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
216 std::vector<CPubKey> pubkeys;
217 pubkeys.resize(keys.size());
218 for (unsigned int i = 0; i < keys.size(); i++)
220 const std::string& ks = keys[i].get_str();
222 // Case 1: Bitcoin address and we have full public key:
223 CBitcoinAddress address(ks);
224 if (pwalletMain && address.IsValid())
227 if (!address.GetKeyID(keyID))
229 strprintf("%s does not refer to a key",ks));
231 if (!pwalletMain->GetPubKey(keyID, vchPubKey))
233 strprintf("no full public key for address %s",ks));
234 if (!vchPubKey.IsFullyValid())
235 throw runtime_error(" Invalid public key: "+ks);
236 pubkeys[i] = vchPubKey;
239 // Case 2: hex public key
244 CPubKey vchPubKey(ParseHex(ks));
245 if (!vchPubKey.IsFullyValid())
246 throw runtime_error(" Invalid public key: "+ks);
247 pubkeys[i] = vchPubKey;
251 throw runtime_error(" Invalid public key: "+ks);
254 CScript result = GetScriptForMultisig(nRequired, pubkeys);
256 if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
258 strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
263 Value createmultisig(const Array& params, bool fHelp)
265 if (fHelp || params.size() < 2 || params.size() > 2)
267 string msg = "createmultisig nrequired [\"key\",...]\n"
268 "\nCreates a multi-signature address with n signature of m keys required.\n"
269 "It returns a json object with the address and redeemScript.\n"
272 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
273 "2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
275 " \"key\" (string) bitcoin address or hex-encoded public key\n"
281 " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
282 " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
286 "\nCreate a multisig address from 2 addresses\n"
287 + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
288 "\nAs a json rpc call\n"
289 + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
291 throw runtime_error(msg);
294 // Construct using pay-to-script-hash:
295 CScript inner = _createmultisig_redeemScript(params);
296 CScriptID innerID(inner);
297 CBitcoinAddress address(innerID);
300 result.push_back(Pair("address", address.ToString()));
301 result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
306 Value verifymessage(const Array& params, bool fHelp)
308 if (fHelp || params.size() != 3)
310 "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
311 "\nVerify a signed message\n"
313 "1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the signature.\n"
314 "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
315 "3. \"message\" (string, required) The message that was signed.\n"
317 "true|false (boolean) If the signature is verified or not.\n"
319 "\nUnlock the wallet for 30 seconds\n"
320 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
321 "\nCreate the signature\n"
322 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
323 "\nVerify the signature\n"
324 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
326 + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
329 string strAddress = params[0].get_str();
330 string strSign = params[1].get_str();
331 string strMessage = params[2].get_str();
333 CBitcoinAddress addr(strAddress);
335 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
338 if (!addr.GetKeyID(keyID))
339 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
341 bool fInvalid = false;
342 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
345 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
347 CHashWriter ss(SER_GETHASH, 0);
348 ss << strMessageMagic;
352 if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
355 return (pubkey.GetID() == keyID);
358 Value setmocktime(const Array& params, bool fHelp)
360 if (fHelp || params.size() != 1)
362 "setmocktime timestamp\n"
363 "\nSet the local time to given timestamp (-regtest only)\n"
365 "1. timestamp (integer, required) Unix seconds-since-epoch timestamp\n"
366 " Pass 0 to go back to using the system time."
369 if (!Params().MineBlocksOnDemand())
370 throw runtime_error("setmocktime for regression testing (-regtest mode) only");
372 RPCTypeCheck(params, boost::assign::list_of(int_type));
373 SetMockTime(params[0].get_int64());