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