Line data Source code
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.
5 :
6 : #include "base58.h"
7 : #include "clientversion.h"
8 : #include "init.h"
9 : #include "main.h"
10 : #include "net.h"
11 : #include "netbase.h"
12 : #include "rpcserver.h"
13 : #include "timedata.h"
14 : #include "util.h"
15 : #include "utilstrencodings.h"
16 : #ifdef ENABLE_WALLET
17 : #include "wallet/wallet.h"
18 : #include "wallet/walletdb.h"
19 : #endif
20 :
21 : #include <stdint.h>
22 :
23 : #include <boost/assign/list_of.hpp>
24 :
25 : #include <univalue.h>
26 :
27 : using namespace std;
28 :
29 : /**
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.
34 : *
35 : * Based on the source of the information, new information should be added to:
36 : * - `getblockchaininfo`,
37 : * - `getnetworkinfo` or
38 : * - `getwalletinfo`
39 : *
40 : * Or alternatively, create a specific query method for the information.
41 : **/
42 0 : UniValue getinfo(const UniValue& params, bool fHelp)
43 : {
44 0 : if (fHelp || params.size() != 0)
45 : throw runtime_error(
46 : "getinfo\n"
47 : "Returns an object containing various state info.\n"
48 : "\nResult:\n"
49 : "{\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 0 : " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in " + CURRENCY_UNIT + "/kB\n"
64 0 : " \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n"
65 : " \"errors\": \"...\" (string) any error messages\n"
66 : "}\n"
67 : "\nExamples:\n"
68 0 : + HelpExampleCli("getinfo", "")
69 0 : + HelpExampleRpc("getinfo", "")
70 0 : );
71 :
72 : #ifdef ENABLE_WALLET
73 0 : LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
74 : #else
75 : LOCK(cs_main);
76 : #endif
77 :
78 : proxyType proxy;
79 0 : GetProxy(NET_IPV4, proxy);
80 :
81 0 : UniValue obj(UniValue::VOBJ);
82 0 : obj.push_back(Pair("version", CLIENT_VERSION));
83 0 : obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
84 : #ifdef ENABLE_WALLET
85 0 : if (pwalletMain) {
86 0 : obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
87 0 : obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
88 : }
89 : #endif
90 0 : obj.push_back(Pair("blocks", (int)chainActive.Height()));
91 0 : obj.push_back(Pair("timeoffset", GetTimeOffset()));
92 0 : obj.push_back(Pair("connections", (int)vNodes.size()));
93 0 : obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string())));
94 0 : obj.push_back(Pair("difficulty", (double)GetDifficulty()));
95 0 : obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
96 : #ifdef ENABLE_WALLET
97 0 : if (pwalletMain) {
98 0 : obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
99 0 : obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
100 : }
101 0 : if (pwalletMain && pwalletMain->IsCrypted())
102 0 : obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
103 0 : obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
104 : #endif
105 0 : obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
106 0 : obj.push_back(Pair("errors", GetWarnings("statusbar")));
107 0 : return obj;
108 : }
109 :
110 : #ifdef ENABLE_WALLET
111 17 : class DescribeAddressVisitor : public boost::static_visitor<UniValue>
112 : {
113 : public:
114 0 : UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
115 :
116 15 : UniValue operator()(const CKeyID &keyID) const {
117 45 : UniValue obj(UniValue::VOBJ);
118 : CPubKey vchPubKey;
119 30 : obj.push_back(Pair("isscript", false));
120 15 : if (pwalletMain->GetPubKey(keyID, vchPubKey)) {
121 45 : obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
122 30 : obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
123 : }
124 15 : return obj;
125 : }
126 :
127 2 : UniValue operator()(const CScriptID &scriptID) const {
128 6 : UniValue obj(UniValue::VOBJ);
129 : CScript subscript;
130 4 : obj.push_back(Pair("isscript", true));
131 2 : if (pwalletMain->GetCScript(scriptID, subscript)) {
132 : std::vector<CTxDestination> addresses;
133 : txnouttype whichType;
134 : int nRequired;
135 2 : ExtractDestinations(subscript, whichType, addresses, nRequired);
136 4 : obj.push_back(Pair("script", GetTxnOutputType(whichType)));
137 6 : obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
138 8 : UniValue a(UniValue::VARR);
139 37 : BOOST_FOREACH(const CTxDestination& addr, addresses)
140 15 : a.push_back(CBitcoinAddress(addr).ToString());
141 4 : obj.push_back(Pair("addresses", a));
142 2 : if (whichType == TX_MULTISIG)
143 6 : obj.push_back(Pair("sigsrequired", nRequired));
144 : }
145 2 : return obj;
146 : }
147 : };
148 : #endif
149 :
150 17 : UniValue validateaddress(const UniValue& params, bool fHelp)
151 : {
152 34 : if (fHelp || params.size() != 1)
153 : throw runtime_error(
154 : "validateaddress \"bitcoinaddress\"\n"
155 : "\nReturn information about the given bitcoin address.\n"
156 : "\nArguments:\n"
157 : "1. \"bitcoinaddress\" (string, required) The bitcoin address to validate\n"
158 : "\nResult:\n"
159 : "{\n"
160 : " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
161 : " \"address\" : \"bitcoinaddress\", (string) The bitcoin address validated\n"
162 : " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
163 : " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
164 : " \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n"
165 : " \"isscript\" : true|false, (boolean) If the key is a script\n"
166 : " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
167 : " \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
168 : " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
169 : "}\n"
170 : "\nExamples:\n"
171 0 : + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
172 0 : + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
173 0 : );
174 :
175 : #ifdef ENABLE_WALLET
176 17 : LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
177 : #else
178 : LOCK(cs_main);
179 : #endif
180 :
181 34 : CBitcoinAddress address(params[0].get_str());
182 17 : bool isValid = address.IsValid();
183 :
184 51 : UniValue ret(UniValue::VOBJ);
185 34 : ret.push_back(Pair("isvalid", isValid));
186 17 : if (isValid)
187 : {
188 17 : CTxDestination dest = address.Get();
189 17 : string currentAddress = address.ToString();
190 51 : ret.push_back(Pair("address", currentAddress));
191 :
192 17 : CScript scriptPubKey = GetScriptForDestination(dest);
193 51 : ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
194 :
195 : #ifdef ENABLE_WALLET
196 17 : isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
197 34 : ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
198 34 : ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
199 34 : UniValue detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
200 17 : ret.pushKVs(detail);
201 34 : if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
202 51 : ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
203 : #endif
204 : }
205 17 : return ret;
206 : }
207 :
208 : /**
209 : * Used by addmultisigaddress / createmultisig:
210 : */
211 16 : CScript _createmultisig_redeemScript(const UniValue& params)
212 : {
213 16 : int nRequired = params[0].get_int();
214 16 : const UniValue& keys = params[1].get_array();
215 :
216 : // Gather public keys
217 16 : if (nRequired < 1)
218 3 : throw runtime_error("a multisignature address must require at least one key to redeem");
219 15 : if ((int)keys.size() < nRequired)
220 : throw runtime_error(
221 : strprintf("not enough keys supplied "
222 12 : "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
223 11 : if (keys.size() > 16)
224 0 : throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
225 : std::vector<CPubKey> pubkeys;
226 11 : pubkeys.resize(keys.size());
227 62 : for (unsigned int i = 0; i < keys.size(); i++)
228 : {
229 22 : const std::string& ks = keys[i].get_str();
230 : #ifdef ENABLE_WALLET
231 : // Case 1: Bitcoin address and we have full public key:
232 22 : CBitcoinAddress address(ks);
233 22 : if (pwalletMain && address.IsValid())
234 : {
235 : CKeyID keyID;
236 1 : if (!address.GetKeyID(keyID))
237 : throw runtime_error(
238 0 : strprintf("%s does not refer to a key",ks));
239 : CPubKey vchPubKey;
240 1 : if (!pwalletMain->GetPubKey(keyID, vchPubKey))
241 : throw runtime_error(
242 0 : strprintf("no full public key for address %s",ks));
243 1 : if (!vchPubKey.IsFullyValid())
244 0 : throw runtime_error(" Invalid public key: "+ks);
245 2 : pubkeys[i] = vchPubKey;
246 : }
247 :
248 : // Case 2: hex public key
249 : else
250 : #endif
251 21 : if (IsHex(ks))
252 : {
253 38 : CPubKey vchPubKey(ParseHex(ks));
254 19 : if (!vchPubKey.IsFullyValid())
255 0 : throw runtime_error(" Invalid public key: "+ks);
256 38 : pubkeys[i] = vchPubKey;
257 : }
258 : else
259 : {
260 4 : throw runtime_error(" Invalid public key: "+ks);
261 : }
262 : }
263 9 : CScript result = GetScriptForMultisig(nRequired, pubkeys);
264 :
265 18 : if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
266 : throw runtime_error(
267 0 : strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
268 :
269 9 : return result;
270 : }
271 :
272 1 : UniValue createmultisig(const UniValue& params, bool fHelp)
273 : {
274 3 : if (fHelp || params.size() < 2 || params.size() > 2)
275 : {
276 : string msg = "createmultisig nrequired [\"key\",...]\n"
277 : "\nCreates a multi-signature address with n signature of m keys required.\n"
278 : "It returns a json object with the address and redeemScript.\n"
279 :
280 : "\nArguments:\n"
281 : "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
282 : "2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
283 : " [\n"
284 : " \"key\" (string) bitcoin address or hex-encoded public key\n"
285 : " ,...\n"
286 : " ]\n"
287 :
288 : "\nResult:\n"
289 : "{\n"
290 : " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
291 : " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
292 : "}\n"
293 :
294 : "\nExamples:\n"
295 : "\nCreate a multisig address from 2 addresses\n"
296 0 : + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
297 : "\nAs a json rpc call\n"
298 0 : + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
299 : ;
300 0 : throw runtime_error(msg);
301 : }
302 :
303 : // Construct using pay-to-script-hash:
304 1 : CScript inner = _createmultisig_redeemScript(params);
305 1 : CScriptID innerID(inner);
306 2 : CBitcoinAddress address(innerID);
307 :
308 3 : UniValue result(UniValue::VOBJ);
309 3 : result.push_back(Pair("address", address.ToString()));
310 3 : result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
311 :
312 1 : return result;
313 : }
314 :
315 6 : UniValue verifymessage(const UniValue& params, bool fHelp)
316 : {
317 12 : if (fHelp || params.size() != 3)
318 : throw runtime_error(
319 : "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
320 : "\nVerify a signed message\n"
321 : "\nArguments:\n"
322 : "1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the signature.\n"
323 : "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
324 : "3. \"message\" (string, required) The message that was signed.\n"
325 : "\nResult:\n"
326 : "true|false (boolean) If the signature is verified or not.\n"
327 : "\nExamples:\n"
328 : "\nUnlock the wallet for 30 seconds\n"
329 16 : + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
330 : "\nCreate the signature\n"
331 18 : + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
332 : "\nVerify the signature\n"
333 18 : + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
334 : "\nAs json rpc\n"
335 16 : + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
336 6 : );
337 :
338 4 : LOCK(cs_main);
339 :
340 4 : string strAddress = params[0].get_str();
341 4 : string strSign = params[1].get_str();
342 4 : string strMessage = params[2].get_str();
343 :
344 4 : CBitcoinAddress addr(strAddress);
345 4 : if (!addr.IsValid())
346 3 : throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
347 :
348 : CKeyID keyID;
349 3 : if (!addr.GetKeyID(keyID))
350 0 : throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
351 :
352 3 : bool fInvalid = false;
353 3 : vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
354 :
355 3 : if (fInvalid)
356 0 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
357 :
358 : CHashWriter ss(SER_GETHASH, 0);
359 : ss << strMessageMagic;
360 : ss << strMessage;
361 :
362 : CPubKey pubkey;
363 3 : if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
364 0 : return false;
365 :
366 6 : return (pubkey.GetID() == keyID);
367 : }
368 :
369 800 : UniValue setmocktime(const UniValue& params, bool fHelp)
370 : {
371 1600 : if (fHelp || params.size() != 1)
372 : throw runtime_error(
373 : "setmocktime timestamp\n"
374 : "\nSet the local time to given timestamp (-regtest only)\n"
375 : "\nArguments:\n"
376 : "1. timestamp (integer, required) Unix seconds-since-epoch timestamp\n"
377 : " Pass 0 to go back to using the system time."
378 0 : );
379 :
380 800 : if (!Params().MineBlocksOnDemand())
381 0 : throw runtime_error("setmocktime for regression testing (-regtest mode) only");
382 :
383 : // cs_vNodes is locked and node send/receive times are updated
384 : // atomically with the time change to prevent peers from being
385 : // disconnected because we think we haven't communicated with them
386 : // in a long time.
387 800 : LOCK2(cs_main, cs_vNodes);
388 :
389 3200 : RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
390 800 : SetMockTime(params[0].get_int64());
391 :
392 800 : uint64_t t = GetTime();
393 10800 : BOOST_FOREACH(CNode* pnode, vNodes) {
394 1200 : pnode->nLastSend = pnode->nLastRecv = t;
395 : }
396 :
397 1600 : return NullUniValue;
398 288 : }
|