]> Git Repo - VerusCoin.git/blob - src/rpcmisc.cpp
Merge pull request #5367
[VerusCoin.git] / src / rpcmisc.cpp
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.
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.h"
17 #include "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 boost;
27 using namespace boost::assign;
28 using namespace json_spirit;
29 using namespace std;
30
31 /**
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.
36  *
37  * Based on the source of the information, new information should be added to:
38  * - `getblockchaininfo`,
39  * - `getnetworkinfo` or
40  * - `getwalletinfo`
41  *
42  * Or alternatively, create a specific query method for the information.
43  **/
44 Value getinfo(const Array& params, bool fHelp)
45 {
46     if (fHelp || params.size() != 0)
47         throw runtime_error(
48             "getinfo\n"
49             "Returns an object containing various state info.\n"
50             "\nResult:\n"
51             "{\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"
68             "}\n"
69             "\nExamples:\n"
70             + HelpExampleCli("getinfo", "")
71             + HelpExampleRpc("getinfo", "")
72         );
73
74     proxyType proxy;
75     GetProxy(NET_IPV4, proxy);
76
77     Object obj;
78     obj.push_back(Pair("version", CLIENT_VERSION));
79     obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
80 #ifdef ENABLE_WALLET
81     if (pwalletMain) {
82         obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
83         obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
84     }
85 #endif
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()));
92 #ifdef ENABLE_WALLET
93     if (pwalletMain) {
94         obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
95         obj.push_back(Pair("keypoolsize",   (int)pwalletMain->GetKeyPoolSize()));
96     }
97     if (pwalletMain && pwalletMain->IsCrypted())
98         obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
99     obj.push_back(Pair("paytxfee",      ValueFromAmount(payTxFee.GetFeePerK())));
100 #endif
101     obj.push_back(Pair("relayfee",      ValueFromAmount(::minRelayTxFee.GetFeePerK())));
102     obj.push_back(Pair("errors",        GetWarnings("statusbar")));
103     return obj;
104 }
105
106 #ifdef ENABLE_WALLET
107 class DescribeAddressVisitor : public boost::static_visitor<Object>
108 {
109 private:
110     isminetype mine;
111
112 public:
113     DescribeAddressVisitor(isminetype mineIn) : mine(mineIn) {}
114
115     Object operator()(const CNoDestination &dest) const { return Object(); }
116
117     Object operator()(const CKeyID &keyID) const {
118         Object obj;
119         CPubKey vchPubKey;
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()));
125         }
126         return obj;
127     }
128
129     Object operator()(const CScriptID &scriptID) const {
130         Object obj;
131         obj.push_back(Pair("isscript", true));
132         if (mine != ISMINE_NO) {
133             CScript subscript;
134             pwalletMain->GetCScript(scriptID, subscript);
135             std::vector<CTxDestination> addresses;
136             txnouttype whichType;
137             int nRequired;
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())));
141             Array a;
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));
147         }
148         return obj;
149     }
150 };
151 #endif
152
153 Value validateaddress(const Array& params, bool fHelp)
154 {
155     if (fHelp || params.size() != 1)
156         throw runtime_error(
157             "validateaddress \"bitcoinaddress\"\n"
158             "\nReturn information about the given bitcoin address.\n"
159             "\nArguments:\n"
160             "1. \"bitcoinaddress\"     (string, required) The bitcoin address to validate\n"
161             "\nResult:\n"
162             "{\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"
170             "}\n"
171             "\nExamples:\n"
172             + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
173             + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
174         );
175
176     CBitcoinAddress address(params[0].get_str());
177     bool isValid = address.IsValid();
178
179     Object ret;
180     ret.push_back(Pair("isvalid", isValid));
181     if (isValid)
182     {
183         CTxDestination dest = address.Get();
184         string currentAddress = address.ToString();
185         ret.push_back(Pair("address", currentAddress));
186 #ifdef ENABLE_WALLET
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());
193         }
194         if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
195             ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
196 #endif
197     }
198     return ret;
199 }
200
201 /**
202  * Used by addmultisigaddress / createmultisig:
203  */
204 CScript _createmultisig_redeemScript(const Array& params)
205 {
206     int nRequired = params[0].get_int();
207     const Array& keys = params[1].get_array();
208
209     // Gather public keys
210     if (nRequired < 1)
211         throw runtime_error("a multisignature address must require at least one key to redeem");
212     if ((int)keys.size() < nRequired)
213         throw runtime_error(
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++)
219     {
220         const std::string& ks = keys[i].get_str();
221 #ifdef ENABLE_WALLET
222         // Case 1: Bitcoin address and we have full public key:
223         CBitcoinAddress address(ks);
224         if (pwalletMain && address.IsValid())
225         {
226             CKeyID keyID;
227             if (!address.GetKeyID(keyID))
228                 throw runtime_error(
229                     strprintf("%s does not refer to a key",ks));
230             CPubKey vchPubKey;
231             if (!pwalletMain->GetPubKey(keyID, vchPubKey))
232                 throw runtime_error(
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;
237         }
238
239         // Case 2: hex public key
240         else
241 #endif
242         if (IsHex(ks))
243         {
244             CPubKey vchPubKey(ParseHex(ks));
245             if (!vchPubKey.IsFullyValid())
246                 throw runtime_error(" Invalid public key: "+ks);
247             pubkeys[i] = vchPubKey;
248         }
249         else
250         {
251             throw runtime_error(" Invalid public key: "+ks);
252         }
253     }
254     CScript result = GetScriptForMultisig(nRequired, pubkeys);
255
256     if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
257         throw runtime_error(
258                 strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
259
260     return result;
261 }
262
263 Value createmultisig(const Array& params, bool fHelp)
264 {
265     if (fHelp || params.size() < 2 || params.size() > 2)
266     {
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"
270
271             "\nArguments:\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"
274             "     [\n"
275             "       \"key\"    (string) bitcoin address or hex-encoded public key\n"
276             "       ,...\n"
277             "     ]\n"
278
279             "\nResult:\n"
280             "{\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"
283             "}\n"
284
285             "\nExamples:\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\\\"]\"")
290         ;
291         throw runtime_error(msg);
292     }
293
294     // Construct using pay-to-script-hash:
295     CScript inner = _createmultisig_redeemScript(params);
296     CScriptID innerID(inner);
297     CBitcoinAddress address(innerID);
298
299     Object result;
300     result.push_back(Pair("address", address.ToString()));
301     result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
302
303     return result;
304 }
305
306 Value verifymessage(const Array& params, bool fHelp)
307 {
308     if (fHelp || params.size() != 3)
309         throw runtime_error(
310             "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
311             "\nVerify a signed message\n"
312             "\nArguments:\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"
316             "\nResult:\n"
317             "true|false   (boolean) If the signature is verified or not.\n"
318             "\nExamples:\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\"") +
325             "\nAs json rpc\n"
326             + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
327         );
328
329     string strAddress  = params[0].get_str();
330     string strSign     = params[1].get_str();
331     string strMessage  = params[2].get_str();
332
333     CBitcoinAddress addr(strAddress);
334     if (!addr.IsValid())
335         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
336
337     CKeyID keyID;
338     if (!addr.GetKeyID(keyID))
339         throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
340
341     bool fInvalid = false;
342     vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
343
344     if (fInvalid)
345         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
346
347     CHashWriter ss(SER_GETHASH, 0);
348     ss << strMessageMagic;
349     ss << strMessage;
350
351     CPubKey pubkey;
352     if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
353         return false;
354
355     return (pubkey.GetID() == keyID);
356 }
357
358 Value setmocktime(const Array& params, bool fHelp)
359 {
360     if (fHelp || params.size() != 1)
361         throw runtime_error(
362             "setmocktime timestamp\n"
363             "\nSet the local time to given timestamp (-regtest only)\n"
364             "\nArguments:\n"
365             "1. timestamp  (integer, required) Unix seconds-since-epoch timestamp\n"
366             "   Pass 0 to go back to using the system time."
367         );
368
369     if (!Params().MineBlocksOnDemand())
370         throw runtime_error("setmocktime for regression testing (-regtest mode) only");
371
372     RPCTypeCheck(params, boost::assign::list_of(int_type));
373     SetMockTime(params[0].get_int64());
374
375     return Value::null;
376 }
This page took 0.047471 seconds and 4 git commands to generate.