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>
23 #include "json/json_spirit_utils.h"
24 #include "json/json_spirit_value.h"
26 using namespace json_spirit;
30 * @note Do not add or change anything in the information returned by this
31 * method. `getinfo` exists for backwards-compatibility only. It combines
32 * information from wildly different sources in the program, which is a mess,
33 * and is thus planned to be deprecated eventually.
35 * Based on the source of the information, new information should be added to:
36 * - `getblockchaininfo`,
37 * - `getnetworkinfo` or
40 * Or alternatively, create a specific query method for the information.
42 Value getinfo(const Array& params, bool fHelp)
44 if (fHelp || params.size() != 0)
47 "Returns an object containing various state info.\n"
50 " \"version\": xxxxx, (numeric) the server version\n"
51 " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
52 " \"walletversion\": xxxxx, (numeric) the wallet version\n"
53 " \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n"
54 " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
55 " \"timeoffset\": xxxxx, (numeric) the time offset\n"
56 " \"connections\": xxxxx, (numeric) the number of connections\n"
57 " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n"
58 " \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
59 " \"testnet\": true|false, (boolean) if the server is using testnet or not\n"
60 " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
61 " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
62 " \"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"
63 " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in btc/kb\n"
64 " \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n"
65 " \"errors\": \"...\" (string) any error messages\n"
68 + HelpExampleCli("getinfo", "")
69 + HelpExampleRpc("getinfo", "")
73 LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
79 GetProxy(NET_IPV4, proxy);
82 obj.push_back(Pair("version", CLIENT_VERSION));
83 obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
86 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
87 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
90 obj.push_back(Pair("blocks", (int)chainActive.Height()));
91 obj.push_back(Pair("timeoffset", GetTimeOffset()));
92 obj.push_back(Pair("connections", (int)vNodes.size()));
93 obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.ToStringIPPort() : string())));
94 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
95 obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
98 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
99 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
101 if (pwalletMain && pwalletMain->IsCrypted())
102 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
103 obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
105 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
106 obj.push_back(Pair("errors", GetWarnings("statusbar")));
111 class DescribeAddressVisitor : public boost::static_visitor<Object>
117 DescribeAddressVisitor(isminetype mineIn) : mine(mineIn) {}
119 Object operator()(const CNoDestination &dest) const { return Object(); }
121 Object operator()(const CKeyID &keyID) const {
124 obj.push_back(Pair("isscript", false));
125 if (mine == ISMINE_SPENDABLE) {
126 pwalletMain->GetPubKey(keyID, vchPubKey);
127 obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
128 obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
133 Object operator()(const CScriptID &scriptID) const {
135 obj.push_back(Pair("isscript", true));
136 if (mine != ISMINE_NO) {
138 pwalletMain->GetCScript(scriptID, subscript);
139 std::vector<CTxDestination> addresses;
140 txnouttype whichType;
142 ExtractDestinations(subscript, whichType, addresses, nRequired);
143 obj.push_back(Pair("script", GetTxnOutputType(whichType)));
144 obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
146 BOOST_FOREACH(const CTxDestination& addr, addresses)
147 a.push_back(CBitcoinAddress(addr).ToString());
148 obj.push_back(Pair("addresses", a));
149 if (whichType == TX_MULTISIG)
150 obj.push_back(Pair("sigsrequired", nRequired));
157 Value validateaddress(const Array& params, bool fHelp)
159 if (fHelp || params.size() != 1)
161 "validateaddress \"bitcoinaddress\"\n"
162 "\nReturn information about the given bitcoin address.\n"
164 "1. \"bitcoinaddress\" (string, required) The bitcoin address to validate\n"
167 " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
168 " \"address\" : \"bitcoinaddress\", (string) The bitcoin address validated\n"
169 " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
170 " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
171 " \"isscript\" : true|false, (boolean) If the key is a script\n"
172 " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
173 " \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
174 " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
177 + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
178 + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
182 LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
187 CBitcoinAddress address(params[0].get_str());
188 bool isValid = address.IsValid();
191 ret.push_back(Pair("isvalid", isValid));
194 CTxDestination dest = address.Get();
195 string currentAddress = address.ToString();
196 ret.push_back(Pair("address", currentAddress));
198 CScript scriptPubKey = GetScriptForDestination(dest);
199 ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
202 isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
203 ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
204 if (mine != ISMINE_NO) {
205 ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
206 Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest);
207 ret.insert(ret.end(), detail.begin(), detail.end());
209 if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
210 ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
217 * Used by addmultisigaddress / createmultisig:
219 CScript _createmultisig_redeemScript(const Array& params)
221 int nRequired = params[0].get_int();
222 const Array& keys = params[1].get_array();
224 // Gather public keys
226 throw runtime_error("a multisignature address must require at least one key to redeem");
227 if ((int)keys.size() < nRequired)
229 strprintf("not enough keys supplied "
230 "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
231 if (keys.size() > 16)
232 throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
233 std::vector<CPubKey> pubkeys;
234 pubkeys.resize(keys.size());
235 for (unsigned int i = 0; i < keys.size(); i++)
237 const std::string& ks = keys[i].get_str();
239 // Case 1: Bitcoin address and we have full public key:
240 CBitcoinAddress address(ks);
241 if (pwalletMain && address.IsValid())
244 if (!address.GetKeyID(keyID))
246 strprintf("%s does not refer to a key",ks));
248 if (!pwalletMain->GetPubKey(keyID, vchPubKey))
250 strprintf("no full public key for address %s",ks));
251 if (!vchPubKey.IsFullyValid())
252 throw runtime_error(" Invalid public key: "+ks);
253 pubkeys[i] = vchPubKey;
256 // Case 2: hex public key
261 CPubKey vchPubKey(ParseHex(ks));
262 if (!vchPubKey.IsFullyValid())
263 throw runtime_error(" Invalid public key: "+ks);
264 pubkeys[i] = vchPubKey;
268 throw runtime_error(" Invalid public key: "+ks);
271 CScript result = GetScriptForMultisig(nRequired, pubkeys);
273 if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
275 strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
280 Value createmultisig(const Array& params, bool fHelp)
282 if (fHelp || params.size() < 2 || params.size() > 2)
284 string msg = "createmultisig nrequired [\"key\",...]\n"
285 "\nCreates a multi-signature address with n signature of m keys required.\n"
286 "It returns a json object with the address and redeemScript.\n"
289 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
290 "2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
292 " \"key\" (string) bitcoin address or hex-encoded public key\n"
298 " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
299 " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
303 "\nCreate a multisig address from 2 addresses\n"
304 + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
305 "\nAs a json rpc call\n"
306 + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
308 throw runtime_error(msg);
311 // Construct using pay-to-script-hash:
312 CScript inner = _createmultisig_redeemScript(params);
313 CScriptID innerID(inner);
314 CBitcoinAddress address(innerID);
317 result.push_back(Pair("address", address.ToString()));
318 result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
323 Value verifymessage(const Array& params, bool fHelp)
325 if (fHelp || params.size() != 3)
327 "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
328 "\nVerify a signed message\n"
330 "1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the signature.\n"
331 "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
332 "3. \"message\" (string, required) The message that was signed.\n"
334 "true|false (boolean) If the signature is verified or not.\n"
336 "\nUnlock the wallet for 30 seconds\n"
337 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
338 "\nCreate the signature\n"
339 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
340 "\nVerify the signature\n"
341 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
343 + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
348 string strAddress = params[0].get_str();
349 string strSign = params[1].get_str();
350 string strMessage = params[2].get_str();
352 CBitcoinAddress addr(strAddress);
354 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
357 if (!addr.GetKeyID(keyID))
358 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
360 bool fInvalid = false;
361 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
364 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
366 CHashWriter ss(SER_GETHASH, 0);
367 ss << strMessageMagic;
371 if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
374 return (pubkey.GetID() == keyID);
377 Value setmocktime(const Array& params, bool fHelp)
379 if (fHelp || params.size() != 1)
381 "setmocktime timestamp\n"
382 "\nSet the local time to given timestamp (-regtest only)\n"
384 "1. timestamp (integer, required) Unix seconds-since-epoch timestamp\n"
385 " Pass 0 to go back to using the system time."
388 if (!Params().MineBlocksOnDemand())
389 throw runtime_error("setmocktime for regression testing (-regtest mode) only");
393 RPCTypeCheck(params, boost::assign::list_of(int_type));
394 SetMockTime(params[0].get_int64());