]> Git Repo - VerusCoin.git/blob - src/rpcmisc.cpp
test
[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 uint64_t komodo_interestsum();
43 int32_t komodo_longestchain();
44 int32_t komodo_notarized_height(uint256 *hashp,uint256 *txidp);
45 int32_t komodo_whoami(char *pubkeystr,int32_t height);
46
47 Value getinfo(const Array& params, bool fHelp)
48 {
49     uint256 notarized_hash,notarized_desttxid;
50     int32_t notarized_height,longestchain;
51     if (fHelp || params.size() != 0)
52         throw runtime_error(
53             "getinfo\n"
54             "Returns an object containing various state info.\n"
55             "\nResult:\n"
56             "{\n"
57             "  \"version\": xxxxx,           (numeric) the server version\n"
58             "  \"protocolversion\": xxxxx,   (numeric) the protocol version\n"
59             "  \"walletversion\": xxxxx,     (numeric) the wallet version\n"
60             "  \"balance\": xxxxxxx,         (numeric) the total bitcoin balance of the wallet\n"
61             "  \"blocks\": xxxxxx,           (numeric) the current number of blocks processed in the server\n"
62             "  \"timeoffset\": xxxxx,        (numeric) the time offset\n"
63             "  \"connections\": xxxxx,       (numeric) the number of connections\n"
64             "  \"proxy\": \"host:port\",     (string, optional) the proxy used by the server\n"
65             "  \"difficulty\": xxxxxx,       (numeric) the current difficulty\n"
66             "  \"testnet\": true|false,      (boolean) if the server is using testnet or not\n"
67             "  \"keypoololdest\": xxxxxx,    (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
68             "  \"keypoolsize\": xxxx,        (numeric) how many new keys are pre-generated\n"
69             "  \"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"
70             "  \"paytxfee\": x.xxxx,         (numeric) the transaction fee set in btc/kb\n"
71             "  \"relayfee\": x.xxxx,         (numeric) minimum relay fee for non-free transactions in btc/kb\n"
72             "  \"errors\": \"...\"           (string) any error messages\n"
73             "}\n"
74             "\nExamples:\n"
75             + HelpExampleCli("getinfo", "")
76             + HelpExampleRpc("getinfo", "")
77         );
78
79 #ifdef ENABLE_WALLET
80     LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
81 #else
82     LOCK(cs_main);
83 #endif
84
85     proxyType proxy;
86     GetProxy(NET_IPV4, proxy);
87     notarized_height = komodo_notarized_height(&notarized_hash,&notarized_desttxid);
88
89     Object obj;
90     obj.push_back(Pair("version", CLIENT_VERSION));
91     obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
92     obj.push_back(Pair("notarized", notarized_height));
93     obj.push_back(Pair("notarizedhash", notarized_hash.ToString()));
94     obj.push_back(Pair("notarizedtxid", notarized_desttxid.ToString()));
95 #ifdef ENABLE_WALLET
96     if (pwalletMain) {
97         obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
98         obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
99         obj.push_back(Pair("interest",       ValueFromAmount(komodo_interestsum())));
100     }
101 #endif
102     obj.push_back(Pair("blocks",        (int)chainActive.Height()));
103     if ( (longestchain= komodo_longestchain()) != 0 && chainActive.Height() > longestchain )
104         longestchain = chainActive.Height();
105     obj.push_back(Pair("longestchain",        longestchain));
106     obj.push_back(Pair("timeoffset",    GetTimeOffset()));
107     if ( chainActive.Tip() != 0 )
108         obj.push_back(Pair("tiptime", (int)chainActive.Tip()->nTime));
109     obj.push_back(Pair("connections",   (int)vNodes.size()));
110     obj.push_back(Pair("proxy",         (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string())));
111     obj.push_back(Pair("difficulty",    (double)GetDifficulty()));
112     obj.push_back(Pair("testnet",       Params().TestnetToBeDeprecatedFieldRPC()));
113 #ifdef ENABLE_WALLET
114     if (pwalletMain) {
115         obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
116         obj.push_back(Pair("keypoolsize",   (int)pwalletMain->GetKeyPoolSize()));
117     }
118     if (pwalletMain && pwalletMain->IsCrypted())
119         obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
120     obj.push_back(Pair("paytxfee",      ValueFromAmount(payTxFee.GetFeePerK())));
121 #endif
122     obj.push_back(Pair("relayfee",      ValueFromAmount(::minRelayTxFee.GetFeePerK())));
123     obj.push_back(Pair("errors",        GetWarnings("statusbar")));
124     {
125         char pubkeystr[65]; int32_t notaryid;
126         notaryid = komodo_whoami(pubkeystr,longestchain);
127         obj.push_back(Pair("notaryid",        notaryid));
128         obj.push_back(Pair("pubkey",        pubkeystr));
129     }
130     return obj;
131 }
132
133 #ifdef ENABLE_WALLET
134 class DescribeAddressVisitor : public boost::static_visitor<Object>
135 {
136 private:
137     isminetype mine;
138
139 public:
140     DescribeAddressVisitor(isminetype mineIn) : mine(mineIn) {}
141
142     Object operator()(const CNoDestination &dest) const { return Object(); }
143
144     Object operator()(const CKeyID &keyID) const {
145         Object obj;
146         CPubKey vchPubKey;
147         obj.push_back(Pair("isscript", false));
148         if (mine == ISMINE_SPENDABLE) {
149             pwalletMain->GetPubKey(keyID, vchPubKey);
150             obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
151             obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
152         }
153         return obj;
154     }
155
156     Object operator()(const CScriptID &scriptID) const {
157         Object obj;
158         obj.push_back(Pair("isscript", true));
159         if (mine != ISMINE_NO) {
160             CScript subscript;
161             pwalletMain->GetCScript(scriptID, subscript);
162             std::vector<CTxDestination> addresses;
163             txnouttype whichType;
164             int nRequired;
165             ExtractDestinations(subscript, whichType, addresses, nRequired);
166             obj.push_back(Pair("script", GetTxnOutputType(whichType)));
167             obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
168             Array a;
169             BOOST_FOREACH(const CTxDestination& addr, addresses)
170                 a.push_back(CBitcoinAddress(addr).ToString());
171             obj.push_back(Pair("addresses", a));
172             if (whichType == TX_MULTISIG)
173                 obj.push_back(Pair("sigsrequired", nRequired));
174         }
175         return obj;
176     }
177 };
178 #endif
179
180 Value validateaddress(const Array& params, bool fHelp)
181 {
182     if (fHelp || params.size() != 1)
183         throw runtime_error(
184             "validateaddress \"bitcoinaddress\"\n"
185             "\nReturn information about the given bitcoin address.\n"
186             "\nArguments:\n"
187             "1. \"bitcoinaddress\"     (string, required) The bitcoin address to validate\n"
188             "\nResult:\n"
189             "{\n"
190             "  \"isvalid\" : true|false,         (boolean) If the address is valid or not. If not, this is the only property returned.\n"
191             "  \"address\" : \"bitcoinaddress\", (string) The bitcoin address validated\n"
192             "  \"scriptPubKey\" : \"hex\",       (string) The hex encoded scriptPubKey generated by the address\n"
193             "  \"ismine\" : true|false,          (boolean) If the address is yours or not\n"
194             "  \"isscript\" : true|false,        (boolean) If the key is a script\n"
195             "  \"pubkey\" : \"publickeyhex\",    (string) The hex value of the raw public key\n"
196             "  \"iscompressed\" : true|false,    (boolean) If the address is compressed\n"
197             "  \"account\" : \"account\"         (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
198             "}\n"
199             "\nExamples:\n"
200             + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
201             + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
202         );
203
204 #ifdef ENABLE_WALLET
205     LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
206 #else
207     LOCK(cs_main);
208 #endif
209
210     CBitcoinAddress address(params[0].get_str());
211     bool isValid = address.IsValid();
212
213     Object ret;
214     ret.push_back(Pair("isvalid", isValid));
215     if (isValid)
216     {
217         CTxDestination dest = address.Get();
218         string currentAddress = address.ToString();
219         ret.push_back(Pair("address", currentAddress));
220
221         CScript scriptPubKey = GetScriptForDestination(dest);
222         ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
223
224 #ifdef ENABLE_WALLET
225         isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
226         ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
227         if (mine != ISMINE_NO) {
228             ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
229             Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest);
230             ret.insert(ret.end(), detail.begin(), detail.end());
231         }
232         if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
233             ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
234 #endif
235     }
236     return ret;
237 }
238
239 /**
240  * Used by addmultisigaddress / createmultisig:
241  */
242 CScript _createmultisig_redeemScript(const Array& params)
243 {
244     int nRequired = params[0].get_int();
245     const Array& keys = params[1].get_array();
246
247     // Gather public keys
248     if (nRequired < 1)
249         throw runtime_error("a multisignature address must require at least one key to redeem");
250     if ((int)keys.size() < nRequired)
251         throw runtime_error(
252             strprintf("not enough keys supplied "
253                       "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
254     if (keys.size() > 16)
255         throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
256     std::vector<CPubKey> pubkeys;
257     pubkeys.resize(keys.size());
258     for (unsigned int i = 0; i < keys.size(); i++)
259     {
260         const std::string& ks = keys[i].get_str();
261 #ifdef ENABLE_WALLET
262         // Case 1: Bitcoin address and we have full public key:
263         CBitcoinAddress address(ks);
264         if (pwalletMain && address.IsValid())
265         {
266             CKeyID keyID;
267             if (!address.GetKeyID(keyID))
268                 throw runtime_error(
269                     strprintf("%s does not refer to a key",ks));
270             CPubKey vchPubKey;
271             if (!pwalletMain->GetPubKey(keyID, vchPubKey))
272                 throw runtime_error(
273                     strprintf("no full public key for address %s",ks));
274             if (!vchPubKey.IsFullyValid())
275                 throw runtime_error(" Invalid public key: "+ks);
276             pubkeys[i] = vchPubKey;
277         }
278
279         // Case 2: hex public key
280         else
281 #endif
282         if (IsHex(ks))
283         {
284             CPubKey vchPubKey(ParseHex(ks));
285             if (!vchPubKey.IsFullyValid())
286                 throw runtime_error(" Invalid public key: "+ks);
287             pubkeys[i] = vchPubKey;
288         }
289         else
290         {
291             throw runtime_error(" Invalid public key: "+ks);
292         }
293     }
294     CScript result = GetScriptForMultisig(nRequired, pubkeys);
295
296     if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
297         throw runtime_error(
298                 strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
299
300     return result;
301 }
302
303 Value createmultisig(const Array& params, bool fHelp)
304 {
305     if (fHelp || params.size() < 2 || params.size() > 2)
306     {
307         string msg = "createmultisig nrequired [\"key\",...]\n"
308             "\nCreates a multi-signature address with n signature of m keys required.\n"
309             "It returns a json object with the address and redeemScript.\n"
310
311             "\nArguments:\n"
312             "1. nrequired      (numeric, required) The number of required signatures out of the n keys or addresses.\n"
313             "2. \"keys\"       (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
314             "     [\n"
315             "       \"key\"    (string) bitcoin address or hex-encoded public key\n"
316             "       ,...\n"
317             "     ]\n"
318
319             "\nResult:\n"
320             "{\n"
321             "  \"address\":\"multisigaddress\",  (string) The value of the new multisig address.\n"
322             "  \"redeemScript\":\"script\"       (string) The string value of the hex-encoded redemption script.\n"
323             "}\n"
324
325             "\nExamples:\n"
326             "\nCreate a multisig address from 2 addresses\n"
327             + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
328             "\nAs a json rpc call\n"
329             + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
330         ;
331         throw runtime_error(msg);
332     }
333
334     // Construct using pay-to-script-hash:
335     CScript inner = _createmultisig_redeemScript(params);
336     CScriptID innerID(inner);
337     CBitcoinAddress address(innerID);
338
339     Object result;
340     result.push_back(Pair("address", address.ToString()));
341     result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
342
343     return result;
344 }
345
346 Value verifymessage(const Array& params, bool fHelp)
347 {
348     if (fHelp || params.size() != 3)
349         throw runtime_error(
350             "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
351             "\nVerify a signed message\n"
352             "\nArguments:\n"
353             "1. \"bitcoinaddress\"  (string, required) The bitcoin address to use for the signature.\n"
354             "2. \"signature\"       (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
355             "3. \"message\"         (string, required) The message that was signed.\n"
356             "\nResult:\n"
357             "true|false   (boolean) If the signature is verified or not.\n"
358             "\nExamples:\n"
359             "\nUnlock the wallet for 30 seconds\n"
360             + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
361             "\nCreate the signature\n"
362             + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
363             "\nVerify the signature\n"
364             + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
365             "\nAs json rpc\n"
366             + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
367         );
368
369     LOCK(cs_main);
370
371     string strAddress  = params[0].get_str();
372     string strSign     = params[1].get_str();
373     string strMessage  = params[2].get_str();
374
375     CBitcoinAddress addr(strAddress);
376     if (!addr.IsValid())
377         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
378
379     CKeyID keyID;
380     if (!addr.GetKeyID(keyID))
381         throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
382
383     bool fInvalid = false;
384     vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
385
386     if (fInvalid)
387         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
388
389     CHashWriter ss(SER_GETHASH, 0);
390     ss << strMessageMagic;
391     ss << strMessage;
392
393     CPubKey pubkey;
394     if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
395         return false;
396
397     return (pubkey.GetID() == keyID);
398 }
399
400 Value setmocktime(const Array& params, bool fHelp)
401 {
402     if (fHelp || params.size() != 1)
403         throw runtime_error(
404             "setmocktime timestamp\n"
405             "\nSet the local time to given timestamp (-regtest only)\n"
406             "\nArguments:\n"
407             "1. timestamp  (integer, required) Unix seconds-since-epoch timestamp\n"
408             "   Pass 0 to go back to using the system time."
409         );
410
411     if (!Params().MineBlocksOnDemand())
412         throw runtime_error("setmocktime for regression testing (-regtest mode) only");
413
414     LOCK(cs_main);
415
416     RPCTypeCheck(params, boost::assign::list_of(int_type));
417     SetMockTime(params[0].get_int64());
418
419     return Value::null;
420 }
This page took 0.046462 seconds and 4 git commands to generate.