]> Git Repo - VerusCoin.git/blob - src/rpcmisc.cpp
Merge pull request #5833
[VerusCoin.git] / src / rpcmisc.cpp
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 #ifdef ENABLE_WALLET
16 #include "wallet/wallet.h"
17 #include "wallet/walletdb.h"
18 #endif
19
20 #include <stdint.h>
21
22 #include <boost/assign/list_of.hpp>
23 #include "json/json_spirit_utils.h"
24 #include "json/json_spirit_value.h"
25
26 using namespace json_spirit;
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 Value getinfo(const Array& params, bool fHelp)
43 {
44     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             "  \"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"
66             "}\n"
67             "\nExamples:\n"
68             + HelpExampleCli("getinfo", "")
69             + HelpExampleRpc("getinfo", "")
70         );
71
72 #ifdef ENABLE_WALLET
73     LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
74 #else
75     LOCK(cs_main);
76 #endif
77
78     proxyType proxy;
79     GetProxy(NET_IPV4, proxy);
80
81     Object obj;
82     obj.push_back(Pair("version", CLIENT_VERSION));
83     obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
84 #ifdef ENABLE_WALLET
85     if (pwalletMain) {
86         obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
87         obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
88     }
89 #endif
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()));
96 #ifdef ENABLE_WALLET
97     if (pwalletMain) {
98         obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
99         obj.push_back(Pair("keypoolsize",   (int)pwalletMain->GetKeyPoolSize()));
100     }
101     if (pwalletMain && pwalletMain->IsCrypted())
102         obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
103     obj.push_back(Pair("paytxfee",      ValueFromAmount(payTxFee.GetFeePerK())));
104 #endif
105     obj.push_back(Pair("relayfee",      ValueFromAmount(::minRelayTxFee.GetFeePerK())));
106     obj.push_back(Pair("errors",        GetWarnings("statusbar")));
107     return obj;
108 }
109
110 #ifdef ENABLE_WALLET
111 class DescribeAddressVisitor : public boost::static_visitor<Object>
112 {
113 private:
114     isminetype mine;
115
116 public:
117     DescribeAddressVisitor(isminetype mineIn) : mine(mineIn) {}
118
119     Object operator()(const CNoDestination &dest) const { return Object(); }
120
121     Object operator()(const CKeyID &keyID) const {
122         Object obj;
123         CPubKey vchPubKey;
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()));
129         }
130         return obj;
131     }
132
133     Object operator()(const CScriptID &scriptID) const {
134         Object obj;
135         obj.push_back(Pair("isscript", true));
136         if (mine != ISMINE_NO) {
137             CScript subscript;
138             pwalletMain->GetCScript(scriptID, subscript);
139             std::vector<CTxDestination> addresses;
140             txnouttype whichType;
141             int nRequired;
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())));
145             Array a;
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));
151         }
152         return obj;
153     }
154 };
155 #endif
156
157 Value validateaddress(const Array& params, bool fHelp)
158 {
159     if (fHelp || params.size() != 1)
160         throw runtime_error(
161             "validateaddress \"bitcoinaddress\"\n"
162             "\nReturn information about the given bitcoin address.\n"
163             "\nArguments:\n"
164             "1. \"bitcoinaddress\"     (string, required) The bitcoin address to validate\n"
165             "\nResult:\n"
166             "{\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"
175             "}\n"
176             "\nExamples:\n"
177             + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
178             + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
179         );
180
181 #ifdef ENABLE_WALLET
182     LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
183 #else
184     LOCK(cs_main);
185 #endif
186
187     CBitcoinAddress address(params[0].get_str());
188     bool isValid = address.IsValid();
189
190     Object ret;
191     ret.push_back(Pair("isvalid", isValid));
192     if (isValid)
193     {
194         CTxDestination dest = address.Get();
195         string currentAddress = address.ToString();
196         ret.push_back(Pair("address", currentAddress));
197
198         CScript scriptPubKey = GetScriptForDestination(dest);
199         ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
200
201 #ifdef ENABLE_WALLET
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());
208         }
209         if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
210             ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
211 #endif
212     }
213     return ret;
214 }
215
216 /**
217  * Used by addmultisigaddress / createmultisig:
218  */
219 CScript _createmultisig_redeemScript(const Array& params)
220 {
221     int nRequired = params[0].get_int();
222     const Array& keys = params[1].get_array();
223
224     // Gather public keys
225     if (nRequired < 1)
226         throw runtime_error("a multisignature address must require at least one key to redeem");
227     if ((int)keys.size() < nRequired)
228         throw runtime_error(
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++)
236     {
237         const std::string& ks = keys[i].get_str();
238 #ifdef ENABLE_WALLET
239         // Case 1: Bitcoin address and we have full public key:
240         CBitcoinAddress address(ks);
241         if (pwalletMain && address.IsValid())
242         {
243             CKeyID keyID;
244             if (!address.GetKeyID(keyID))
245                 throw runtime_error(
246                     strprintf("%s does not refer to a key",ks));
247             CPubKey vchPubKey;
248             if (!pwalletMain->GetPubKey(keyID, vchPubKey))
249                 throw runtime_error(
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;
254         }
255
256         // Case 2: hex public key
257         else
258 #endif
259         if (IsHex(ks))
260         {
261             CPubKey vchPubKey(ParseHex(ks));
262             if (!vchPubKey.IsFullyValid())
263                 throw runtime_error(" Invalid public key: "+ks);
264             pubkeys[i] = vchPubKey;
265         }
266         else
267         {
268             throw runtime_error(" Invalid public key: "+ks);
269         }
270     }
271     CScript result = GetScriptForMultisig(nRequired, pubkeys);
272
273     if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
274         throw runtime_error(
275                 strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
276
277     return result;
278 }
279
280 Value createmultisig(const Array& params, bool fHelp)
281 {
282     if (fHelp || params.size() < 2 || params.size() > 2)
283     {
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"
287
288             "\nArguments:\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"
291             "     [\n"
292             "       \"key\"    (string) bitcoin address or hex-encoded public key\n"
293             "       ,...\n"
294             "     ]\n"
295
296             "\nResult:\n"
297             "{\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"
300             "}\n"
301
302             "\nExamples:\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\\\"]\"")
307         ;
308         throw runtime_error(msg);
309     }
310
311     // Construct using pay-to-script-hash:
312     CScript inner = _createmultisig_redeemScript(params);
313     CScriptID innerID(inner);
314     CBitcoinAddress address(innerID);
315
316     Object result;
317     result.push_back(Pair("address", address.ToString()));
318     result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
319
320     return result;
321 }
322
323 Value verifymessage(const Array& params, bool fHelp)
324 {
325     if (fHelp || params.size() != 3)
326         throw runtime_error(
327             "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
328             "\nVerify a signed message\n"
329             "\nArguments:\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"
333             "\nResult:\n"
334             "true|false   (boolean) If the signature is verified or not.\n"
335             "\nExamples:\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\"") +
342             "\nAs json rpc\n"
343             + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
344         );
345
346     LOCK(cs_main);
347
348     string strAddress  = params[0].get_str();
349     string strSign     = params[1].get_str();
350     string strMessage  = params[2].get_str();
351
352     CBitcoinAddress addr(strAddress);
353     if (!addr.IsValid())
354         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
355
356     CKeyID keyID;
357     if (!addr.GetKeyID(keyID))
358         throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
359
360     bool fInvalid = false;
361     vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
362
363     if (fInvalid)
364         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
365
366     CHashWriter ss(SER_GETHASH, 0);
367     ss << strMessageMagic;
368     ss << strMessage;
369
370     CPubKey pubkey;
371     if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
372         return false;
373
374     return (pubkey.GetID() == keyID);
375 }
376
377 Value setmocktime(const Array& params, bool fHelp)
378 {
379     if (fHelp || params.size() != 1)
380         throw runtime_error(
381             "setmocktime timestamp\n"
382             "\nSet the local time to given timestamp (-regtest only)\n"
383             "\nArguments:\n"
384             "1. timestamp  (integer, required) Unix seconds-since-epoch timestamp\n"
385             "   Pass 0 to go back to using the system time."
386         );
387
388     if (!Params().MineBlocksOnDemand())
389         throw runtime_error("setmocktime for regression testing (-regtest mode) only");
390
391     LOCK(cs_main);
392
393     RPCTypeCheck(params, boost::assign::list_of(int_type));
394     SetMockTime(params[0].get_int64());
395
396     return Value::null;
397 }
This page took 0.049675 seconds and 4 git commands to generate.