]> Git Repo - VerusCoin.git/blame - src/rpcmisc.cpp
Merge pull request #4928
[VerusCoin.git] / src / rpcmisc.cpp
CommitLineData
652e1569 1// Copyright (c) 2010 Satoshi Nakamoto
57702541 2// Copyright (c) 2009-2014 The Bitcoin developers
652e1569
WL
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"
652e1569
WL
7#include "init.h"
8#include "main.h"
9#include "net.h"
10#include "netbase.h"
c037531d 11#include "rpcserver.h"
14f888ca 12#include "timedata.h"
652e1569
WL
13#include "util.h"
14#ifdef ENABLE_WALLET
15#include "wallet.h"
16#include "walletdb.h"
17#endif
18
19#include <stdint.h>
20
21#include <boost/assign/list_of.hpp>
22#include "json/json_spirit_utils.h"
23#include "json/json_spirit_value.h"
24
652e1569
WL
25using namespace boost;
26using namespace boost::assign;
27using namespace json_spirit;
40a158e1 28using namespace std;
652e1569 29
f9de17ec
WL
30/**
31 * @note Do not add or change anything in the information returned by this
32 * method. `getinfo` exists for backwards-compatibilty only. It combines
33 * information from wildly different sources in the program, which is a mess,
34 * and is thus planned to be deprecated eventually.
35 *
36 * Based on the source of the information, new information should be added to:
37 * - `getblockchaininfo`,
38 * - `getnetworkinfo` or
39 * - `getwalletinfo`
40 *
41 * Or alternatively, create a specific query method for the information.
42 **/
16bc9aaf
WL
43Value getinfo(const Array& params, bool fHelp)
44{
45 if (fHelp || params.size() != 0)
46 throw runtime_error(
47 "getinfo\n"
48 "Returns an object containing various state info.\n"
49 "\nResult:\n"
50 "{\n"
51 " \"version\": xxxxx, (numeric) the server version\n"
52 " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
53 " \"walletversion\": xxxxx, (numeric) the wallet version\n"
54 " \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n"
55 " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
56 " \"timeoffset\": xxxxx, (numeric) the time offset\n"
57 " \"connections\": xxxxx, (numeric) the number of connections\n"
58 " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n"
59 " \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
60 " \"testnet\": true|false, (boolean) if the server is using testnet or not\n"
61 " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
62 " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
16bc9aaf 63 " \"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"
1294cdc4
GM
64 " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in btc/kb\n"
65 " \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n"
16bc9aaf
WL
66 " \"errors\": \"...\" (string) any error messages\n"
67 "}\n"
68 "\nExamples:\n"
69 + HelpExampleCli("getinfo", "")
70 + HelpExampleRpc("getinfo", "")
71 );
72
73 proxyType proxy;
74 GetProxy(NET_IPV4, proxy);
75
76 Object obj;
faadbe17
PK
77 obj.push_back(Pair("version", CLIENT_VERSION));
78 obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
16bc9aaf
WL
79#ifdef ENABLE_WALLET
80 if (pwalletMain) {
81 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
82 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
83 }
84#endif
85 obj.push_back(Pair("blocks", (int)chainActive.Height()));
d56e30ca 86 obj.push_back(Pair("timeoffset", GetTimeOffset()));
16bc9aaf 87 obj.push_back(Pair("connections", (int)vNodes.size()));
0127a9be 88 obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.ToStringIPPort() : string())));
16bc9aaf 89 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
84ce18ca 90 obj.push_back(Pair("testnet", Params().NetworkID() == CBaseChainParams::TESTNET));
16bc9aaf
WL
91#ifdef ENABLE_WALLET
92 if (pwalletMain) {
d56e30ca 93 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
16bc9aaf
WL
94 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
95 }
16bc9aaf 96 if (pwalletMain && pwalletMain->IsCrypted())
d56e30ca 97 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
c6cb21d1 98 obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
16bc9aaf 99#endif
13fc83c7 100 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
16bc9aaf
WL
101 obj.push_back(Pair("errors", GetWarnings("statusbar")));
102 return obj;
103}
104
452955f5
WL
105#ifdef ENABLE_WALLET
106class DescribeAddressVisitor : public boost::static_visitor<Object>
107{
c8988460
PW
108private:
109 isminetype mine;
110
452955f5 111public:
c8988460
PW
112 DescribeAddressVisitor(isminetype mineIn) : mine(mineIn) {}
113
452955f5
WL
114 Object operator()(const CNoDestination &dest) const { return Object(); }
115
116 Object operator()(const CKeyID &keyID) const {
117 Object obj;
118 CPubKey vchPubKey;
452955f5 119 obj.push_back(Pair("isscript", false));
a3e192a3 120 if (mine == ISMINE_SPENDABLE) {
c8988460
PW
121 pwalletMain->GetPubKey(keyID, vchPubKey);
122 obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
123 obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
124 }
452955f5
WL
125 return obj;
126 }
127
128 Object operator()(const CScriptID &scriptID) const {
129 Object obj;
130 obj.push_back(Pair("isscript", true));
a3e192a3 131 if (mine != ISMINE_NO) {
c8988460
PW
132 CScript subscript;
133 pwalletMain->GetCScript(scriptID, subscript);
134 std::vector<CTxDestination> addresses;
135 txnouttype whichType;
136 int nRequired;
137 ExtractDestinations(subscript, whichType, addresses, nRequired);
138 obj.push_back(Pair("script", GetTxnOutputType(whichType)));
139 obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
140 Array a;
141 BOOST_FOREACH(const CTxDestination& addr, addresses)
142 a.push_back(CBitcoinAddress(addr).ToString());
143 obj.push_back(Pair("addresses", a));
144 if (whichType == TX_MULTISIG)
145 obj.push_back(Pair("sigsrequired", nRequired));
146 }
452955f5
WL
147 return obj;
148 }
149};
150#endif
151
152Value validateaddress(const Array& params, bool fHelp)
153{
154 if (fHelp || params.size() != 1)
155 throw runtime_error(
156 "validateaddress \"bitcoinaddress\"\n"
157 "\nReturn information about the given bitcoin address.\n"
158 "\nArguments:\n"
159 "1. \"bitcoinaddress\" (string, required) The bitcoin address to validate\n"
160 "\nResult:\n"
161 "{\n"
162 " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
163 " \"address\" : \"bitcoinaddress\", (string) The bitcoin address validated\n"
164 " \"ismine\" : true|false, (boolean) If the address is yours or not\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) The account associated with the address, \"\" is the default account\n"
169 "}\n"
170 "\nExamples:\n"
171 + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
172 + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
173 );
174
175 CBitcoinAddress address(params[0].get_str());
176 bool isValid = address.IsValid();
177
178 Object ret;
179 ret.push_back(Pair("isvalid", isValid));
180 if (isValid)
181 {
182 CTxDestination dest = address.Get();
183 string currentAddress = address.ToString();
184 ret.push_back(Pair("address", currentAddress));
185#ifdef ENABLE_WALLET
a3e192a3
J
186 isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
187 ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
188 if (mine != ISMINE_NO) {
189 ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
c8988460 190 Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest);
452955f5
WL
191 ret.insert(ret.end(), detail.begin(), detail.end());
192 }
193 if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
194 ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
195#endif
196 }
197 return ret;
198}
199
723a03d2
WL
200//
201// Used by addmultisigaddress / createmultisig:
202//
787ee0c9 203CScript _createmultisig_redeemScript(const Array& params)
723a03d2
WL
204{
205 int nRequired = params[0].get_int();
206 const Array& keys = params[1].get_array();
207
208 // Gather public keys
209 if (nRequired < 1)
210 throw runtime_error("a multisignature address must require at least one key to redeem");
211 if ((int)keys.size() < nRequired)
212 throw runtime_error(
213 strprintf("not enough keys supplied "
783b182c 214 "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
723a03d2
WL
215 std::vector<CPubKey> pubkeys;
216 pubkeys.resize(keys.size());
217 for (unsigned int i = 0; i < keys.size(); i++)
218 {
219 const std::string& ks = keys[i].get_str();
220#ifdef ENABLE_WALLET
221 // Case 1: Bitcoin address and we have full public key:
222 CBitcoinAddress address(ks);
223 if (pwalletMain && address.IsValid())
224 {
225 CKeyID keyID;
226 if (!address.GetKeyID(keyID))
227 throw runtime_error(
7d9d134b 228 strprintf("%s does not refer to a key",ks));
723a03d2
WL
229 CPubKey vchPubKey;
230 if (!pwalletMain->GetPubKey(keyID, vchPubKey))
231 throw runtime_error(
7d9d134b 232 strprintf("no full public key for address %s",ks));
723a03d2
WL
233 if (!vchPubKey.IsFullyValid())
234 throw runtime_error(" Invalid public key: "+ks);
235 pubkeys[i] = vchPubKey;
236 }
237
238 // Case 2: hex public key
239 else
240#endif
241 if (IsHex(ks))
242 {
243 CPubKey vchPubKey(ParseHex(ks));
244 if (!vchPubKey.IsFullyValid())
245 throw runtime_error(" Invalid public key: "+ks);
246 pubkeys[i] = vchPubKey;
247 }
248 else
249 {
250 throw runtime_error(" Invalid public key: "+ks);
251 }
252 }
253 CScript result;
254 result.SetMultisig(nRequired, pubkeys);
787ee0c9
PT
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
723a03d2
WL
260 return result;
261}
262
263Value 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"
e3e3728f 289 + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
723a03d2
WL
290 ;
291 throw runtime_error(msg);
292 }
293
294 // Construct using pay-to-script-hash:
787ee0c9 295 CScript inner = _createmultisig_redeemScript(params);
723a03d2
WL
296 CScriptID innerID = inner.GetID();
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
c3a7f516
WL
306Value 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}
This page took 0.140813 seconds and 4 git commands to generate.