]> Git Repo - VerusCoin.git/blob - src/rpcmisc.cpp
Merge pull request #3914
[VerusCoin.git] / src / rpcmisc.cpp
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "base58.h"
7 #include "init.h"
8 #include "main.h"
9 #include "net.h"
10 #include "netbase.h"
11 #include "rpcserver.h"
12 #include "util.h"
13 #ifdef ENABLE_WALLET
14 #include "wallet.h"
15 #include "walletdb.h"
16 #endif
17
18 #include <stdint.h>
19
20 #include <boost/assign/list_of.hpp>
21 #include "json/json_spirit_utils.h"
22 #include "json/json_spirit_value.h"
23
24 using namespace std;
25 using namespace boost;
26 using namespace boost::assign;
27 using namespace json_spirit;
28
29 Value getinfo(const Array& params, bool fHelp)
30 {
31     if (fHelp || params.size() != 0)
32         throw runtime_error(
33             "getinfo\n"
34             "Returns an object containing various state info.\n"
35             "\nResult:\n"
36             "{\n"
37             "  \"version\": xxxxx,           (numeric) the server version\n"
38             "  \"protocolversion\": xxxxx,   (numeric) the protocol version\n"
39             "  \"walletversion\": xxxxx,     (numeric) the wallet version\n"
40             "  \"balance\": xxxxxxx,         (numeric) the total bitcoin balance of the wallet\n"
41             "  \"blocks\": xxxxxx,           (numeric) the current number of blocks processed in the server\n"
42             "  \"timeoffset\": xxxxx,        (numeric) the time offset\n"
43             "  \"connections\": xxxxx,       (numeric) the number of connections\n"
44             "  \"proxy\": \"host:port\",     (string, optional) the proxy used by the server\n"
45             "  \"difficulty\": xxxxxx,       (numeric) the current difficulty\n"
46             "  \"testnet\": true|false,      (boolean) if the server is using testnet or not\n"
47             "  \"keypoololdest\": xxxxxx,    (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
48             "  \"keypoolsize\": xxxx,        (numeric) how many new keys are pre-generated\n"
49             "  \"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"
50             "  \"paytxfee\": x.xxxx,         (numeric) the transaction fee set in btc/kb\n"
51             "  \"relayfee\": x.xxxx,         (numeric) minimum relay fee for non-free transactions in btc/kb\n"
52             "  \"errors\": \"...\"           (string) any error messages\n"
53             "}\n"
54             "\nExamples:\n"
55             + HelpExampleCli("getinfo", "")
56             + HelpExampleRpc("getinfo", "")
57         );
58
59     proxyType proxy;
60     GetProxy(NET_IPV4, proxy);
61
62     Object obj;
63     obj.push_back(Pair("version",       (int)CLIENT_VERSION));
64     obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
65 #ifdef ENABLE_WALLET
66     if (pwalletMain) {
67         obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
68         obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
69     }
70 #endif
71     obj.push_back(Pair("blocks",        (int)chainActive.Height()));
72     obj.push_back(Pair("timeoffset",    (boost::int64_t)GetTimeOffset()));
73     obj.push_back(Pair("connections",   (int)vNodes.size()));
74     obj.push_back(Pair("proxy",         (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
75     obj.push_back(Pair("difficulty",    (double)GetDifficulty()));
76     obj.push_back(Pair("testnet",       TestNet()));
77 #ifdef ENABLE_WALLET
78     if (pwalletMain) {
79         obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
80         obj.push_back(Pair("keypoolsize",   (int)pwalletMain->GetKeyPoolSize()));
81     }
82     if (pwalletMain && pwalletMain->IsCrypted())
83         obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
84     obj.push_back(Pair("paytxfee",      ValueFromAmount(nTransactionFee)));
85 #endif
86     obj.push_back(Pair("relayfee",      ValueFromAmount(CTransaction::nMinRelayTxFee)));
87     obj.push_back(Pair("errors",        GetWarnings("statusbar")));
88     return obj;
89 }
90
91 #ifdef ENABLE_WALLET
92 class DescribeAddressVisitor : public boost::static_visitor<Object>
93 {
94 public:
95     Object operator()(const CNoDestination &dest) const { return Object(); }
96
97     Object operator()(const CKeyID &keyID) const {
98         Object obj;
99         CPubKey vchPubKey;
100         pwalletMain->GetPubKey(keyID, vchPubKey);
101         obj.push_back(Pair("isscript", false));
102         obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
103         obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
104         return obj;
105     }
106
107     Object operator()(const CScriptID &scriptID) const {
108         Object obj;
109         obj.push_back(Pair("isscript", true));
110         CScript subscript;
111         pwalletMain->GetCScript(scriptID, subscript);
112         std::vector<CTxDestination> addresses;
113         txnouttype whichType;
114         int nRequired;
115         ExtractDestinations(subscript, whichType, addresses, nRequired);
116         obj.push_back(Pair("script", GetTxnOutputType(whichType)));
117         obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
118         Array a;
119         BOOST_FOREACH(const CTxDestination& addr, addresses)
120             a.push_back(CBitcoinAddress(addr).ToString());
121         obj.push_back(Pair("addresses", a));
122         if (whichType == TX_MULTISIG)
123             obj.push_back(Pair("sigsrequired", nRequired));
124         return obj;
125     }
126 };
127 #endif
128
129 Value validateaddress(const Array& params, bool fHelp)
130 {
131     if (fHelp || params.size() != 1)
132         throw runtime_error(
133             "validateaddress \"bitcoinaddress\"\n"
134             "\nReturn information about the given bitcoin address.\n"
135             "\nArguments:\n"
136             "1. \"bitcoinaddress\"     (string, required) The bitcoin address to validate\n"
137             "\nResult:\n"
138             "{\n"
139             "  \"isvalid\" : true|false,         (boolean) If the address is valid or not. If not, this is the only property returned.\n"
140             "  \"address\" : \"bitcoinaddress\", (string) The bitcoin address validated\n"
141             "  \"ismine\" : true|false,          (boolean) If the address is yours or not\n"
142             "  \"isscript\" : true|false,        (boolean) If the key is a script\n"
143             "  \"pubkey\" : \"publickeyhex\",    (string) The hex value of the raw public key\n"
144             "  \"iscompressed\" : true|false,    (boolean) If the address is compressed\n"
145             "  \"account\" : \"account\"         (string) The account associated with the address, \"\" is the default account\n"
146             "}\n"
147             "\nExamples:\n"
148             + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
149             + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
150         );
151
152     CBitcoinAddress address(params[0].get_str());
153     bool isValid = address.IsValid();
154
155     Object ret;
156     ret.push_back(Pair("isvalid", isValid));
157     if (isValid)
158     {
159         CTxDestination dest = address.Get();
160         string currentAddress = address.ToString();
161         ret.push_back(Pair("address", currentAddress));
162 #ifdef ENABLE_WALLET
163         bool fMine = pwalletMain ? IsMine(*pwalletMain, dest) : false;
164         ret.push_back(Pair("ismine", fMine));
165         if (fMine) {
166             Object detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
167             ret.insert(ret.end(), detail.begin(), detail.end());
168         }
169         if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
170             ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
171 #endif
172     }
173     return ret;
174 }
175
176 //
177 // Used by addmultisigaddress / createmultisig:
178 //
179 CScript _createmultisig(const Array& params)
180 {
181     int nRequired = params[0].get_int();
182     const Array& keys = params[1].get_array();
183
184     // Gather public keys
185     if (nRequired < 1)
186         throw runtime_error("a multisignature address must require at least one key to redeem");
187     if ((int)keys.size() < nRequired)
188         throw runtime_error(
189             strprintf("not enough keys supplied "
190                       "(got %"PRIszu" keys, but need at least %d to redeem)", keys.size(), nRequired));
191     std::vector<CPubKey> pubkeys;
192     pubkeys.resize(keys.size());
193     for (unsigned int i = 0; i < keys.size(); i++)
194     {
195         const std::string& ks = keys[i].get_str();
196 #ifdef ENABLE_WALLET
197         // Case 1: Bitcoin address and we have full public key:
198         CBitcoinAddress address(ks);
199         if (pwalletMain && address.IsValid())
200         {
201             CKeyID keyID;
202             if (!address.GetKeyID(keyID))
203                 throw runtime_error(
204                     strprintf("%s does not refer to a key",ks));
205             CPubKey vchPubKey;
206             if (!pwalletMain->GetPubKey(keyID, vchPubKey))
207                 throw runtime_error(
208                     strprintf("no full public key for address %s",ks));
209             if (!vchPubKey.IsFullyValid())
210                 throw runtime_error(" Invalid public key: "+ks);
211             pubkeys[i] = vchPubKey;
212         }
213
214         // Case 2: hex public key
215         else
216 #endif
217         if (IsHex(ks))
218         {
219             CPubKey vchPubKey(ParseHex(ks));
220             if (!vchPubKey.IsFullyValid())
221                 throw runtime_error(" Invalid public key: "+ks);
222             pubkeys[i] = vchPubKey;
223         }
224         else
225         {
226             throw runtime_error(" Invalid public key: "+ks);
227         }
228     }
229     CScript result;
230     result.SetMultisig(nRequired, pubkeys);
231     return result;
232 }
233
234 Value createmultisig(const Array& params, bool fHelp)
235 {
236     if (fHelp || params.size() < 2 || params.size() > 2)
237     {
238         string msg = "createmultisig nrequired [\"key\",...]\n"
239             "\nCreates a multi-signature address with n signature of m keys required.\n"
240             "It returns a json object with the address and redeemScript.\n"
241
242             "\nArguments:\n"
243             "1. nrequired      (numeric, required) The number of required signatures out of the n keys or addresses.\n"
244             "2. \"keys\"       (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
245             "     [\n"
246             "       \"key\"    (string) bitcoin address or hex-encoded public key\n"
247             "       ,...\n"
248             "     ]\n"
249
250             "\nResult:\n"
251             "{\n"
252             "  \"address\":\"multisigaddress\",  (string) The value of the new multisig address.\n"
253             "  \"redeemScript\":\"script\"       (string) The string value of the hex-encoded redemption script.\n"
254             "}\n"
255
256             "\nExamples:\n"
257             "\nCreate a multisig address from 2 addresses\n"
258             + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
259             "\nAs a json rpc call\n"
260             + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
261         ;
262         throw runtime_error(msg);
263     }
264
265     // Construct using pay-to-script-hash:
266     CScript inner = _createmultisig(params);
267     CScriptID innerID = inner.GetID();
268     CBitcoinAddress address(innerID);
269
270     Object result;
271     result.push_back(Pair("address", address.ToString()));
272     result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
273
274     return result;
275 }
276
277 Value verifymessage(const Array& params, bool fHelp)
278 {
279     if (fHelp || params.size() != 3)
280         throw runtime_error(
281             "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
282             "\nVerify a signed message\n"
283             "\nArguments:\n"
284             "1. \"bitcoinaddress\"  (string, required) The bitcoin address to use for the signature.\n"
285             "2. \"signature\"       (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
286             "3. \"message\"         (string, required) The message that was signed.\n"
287             "\nResult:\n"
288             "true|false   (boolean) If the signature is verified or not.\n"
289             "\nExamples:\n"
290             "\nUnlock the wallet for 30 seconds\n"
291             + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
292             "\nCreate the signature\n"
293             + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
294             "\nVerify the signature\n"
295             + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
296             "\nAs json rpc\n"
297             + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
298         );
299
300     string strAddress  = params[0].get_str();
301     string strSign     = params[1].get_str();
302     string strMessage  = params[2].get_str();
303
304     CBitcoinAddress addr(strAddress);
305     if (!addr.IsValid())
306         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
307
308     CKeyID keyID;
309     if (!addr.GetKeyID(keyID))
310         throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
311
312     bool fInvalid = false;
313     vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
314
315     if (fInvalid)
316         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
317
318     CHashWriter ss(SER_GETHASH, 0);
319     ss << strMessageMagic;
320     ss << strMessage;
321
322     CPubKey pubkey;
323     if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
324         return false;
325
326     return (pubkey.GetID() == keyID);
327 }
This page took 0.045258 seconds and 4 git commands to generate.