]> Git Repo - VerusCoin.git/blob - src/rpcmisc.cpp
Type-safe CFeeRate class
[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",    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", pwalletMain->GetOldestKeyPoolTime()));
80         obj.push_back(Pair("keypoolsize",   (int)pwalletMain->GetKeyPoolSize()));
81     }
82     if (pwalletMain && pwalletMain->IsCrypted())
83         obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
84     obj.push_back(Pair("paytxfee",      ValueFromAmount(payTxFee.GetFeePerK())));
85 #endif
86     obj.push_back(Pair("relayfee",      ValueFromAmount(CTransaction::minRelayTxFee.GetFeePerK())));
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_redeemScript(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 %u 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
232     if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
233         throw runtime_error(
234                 strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
235
236     return result;
237 }
238
239 Value createmultisig(const Array& params, bool fHelp)
240 {
241     if (fHelp || params.size() < 2 || params.size() > 2)
242     {
243         string msg = "createmultisig nrequired [\"key\",...]\n"
244             "\nCreates a multi-signature address with n signature of m keys required.\n"
245             "It returns a json object with the address and redeemScript.\n"
246
247             "\nArguments:\n"
248             "1. nrequired      (numeric, required) The number of required signatures out of the n keys or addresses.\n"
249             "2. \"keys\"       (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
250             "     [\n"
251             "       \"key\"    (string) bitcoin address or hex-encoded public key\n"
252             "       ,...\n"
253             "     ]\n"
254
255             "\nResult:\n"
256             "{\n"
257             "  \"address\":\"multisigaddress\",  (string) The value of the new multisig address.\n"
258             "  \"redeemScript\":\"script\"       (string) The string value of the hex-encoded redemption script.\n"
259             "}\n"
260
261             "\nExamples:\n"
262             "\nCreate a multisig address from 2 addresses\n"
263             + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
264             "\nAs a json rpc call\n"
265             + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
266         ;
267         throw runtime_error(msg);
268     }
269
270     // Construct using pay-to-script-hash:
271     CScript inner = _createmultisig_redeemScript(params);
272     CScriptID innerID = inner.GetID();
273     CBitcoinAddress address(innerID);
274
275     Object result;
276     result.push_back(Pair("address", address.ToString()));
277     result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
278
279     return result;
280 }
281
282 Value verifymessage(const Array& params, bool fHelp)
283 {
284     if (fHelp || params.size() != 3)
285         throw runtime_error(
286             "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
287             "\nVerify a signed message\n"
288             "\nArguments:\n"
289             "1. \"bitcoinaddress\"  (string, required) The bitcoin address to use for the signature.\n"
290             "2. \"signature\"       (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
291             "3. \"message\"         (string, required) The message that was signed.\n"
292             "\nResult:\n"
293             "true|false   (boolean) If the signature is verified or not.\n"
294             "\nExamples:\n"
295             "\nUnlock the wallet for 30 seconds\n"
296             + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
297             "\nCreate the signature\n"
298             + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
299             "\nVerify the signature\n"
300             + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
301             "\nAs json rpc\n"
302             + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
303         );
304
305     string strAddress  = params[0].get_str();
306     string strSign     = params[1].get_str();
307     string strMessage  = params[2].get_str();
308
309     CBitcoinAddress addr(strAddress);
310     if (!addr.IsValid())
311         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
312
313     CKeyID keyID;
314     if (!addr.GetKeyID(keyID))
315         throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
316
317     bool fInvalid = false;
318     vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
319
320     if (fInvalid)
321         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
322
323     CHashWriter ss(SER_GETHASH, 0);
324     ss << strMessageMagic;
325     ss << strMessage;
326
327     CPubKey pubkey;
328     if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
329         return false;
330
331     return (pubkey.GetID() == keyID);
332 }
This page took 0.044276 seconds and 4 git commands to generate.