]> Git Repo - VerusCoin.git/blame_incremental - src/rpcmisc.cpp
rpc: make `gettxoutsettinfo` run lock-free
[VerusCoin.git] / src / rpcmisc.cpp
... / ...
CommitLineData
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
24#include <univalue.h>
25
26#include "zcash/Address.hpp"
27
28using namespace std;
29
30/**
31 * @note Do not add or change anything in the information returned by this
32 * method. `getinfo` exists for backwards-compatibility 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 **/
43UniValue getinfo(const UniValue& 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"
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"
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"
66 " \"errors\": \"...\" (string) any error messages\n"
67 "}\n"
68 "\nExamples:\n"
69 + HelpExampleCli("getinfo", "")
70 + HelpExampleRpc("getinfo", "")
71 );
72
73#ifdef ENABLE_WALLET
74 LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
75#else
76 LOCK(cs_main);
77#endif
78
79 proxyType proxy;
80 GetProxy(NET_IPV4, proxy);
81
82 UniValue obj(UniValue::VOBJ);
83 obj.push_back(Pair("version", CLIENT_VERSION));
84 obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
85#ifdef ENABLE_WALLET
86 if (pwalletMain) {
87 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
88 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
89 }
90#endif
91 obj.push_back(Pair("blocks", (int)chainActive.Height()));
92 obj.push_back(Pair("timeoffset", GetTimeOffset()));
93 obj.push_back(Pair("connections", (int)vNodes.size()));
94 obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string())));
95 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
96 obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
97#ifdef ENABLE_WALLET
98 if (pwalletMain) {
99 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
100 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
101 }
102 if (pwalletMain && pwalletMain->IsCrypted())
103 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
104 obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
105#endif
106 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
107 obj.push_back(Pair("errors", GetWarnings("statusbar")));
108 return obj;
109}
110
111#ifdef ENABLE_WALLET
112class DescribeAddressVisitor : public boost::static_visitor<UniValue>
113{
114private:
115 isminetype mine;
116
117public:
118 DescribeAddressVisitor(isminetype mineIn) : mine(mineIn) {}
119
120 UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
121
122 UniValue operator()(const CKeyID &keyID) const {
123 UniValue obj(UniValue::VOBJ);
124 CPubKey vchPubKey;
125 obj.push_back(Pair("isscript", false));
126 if (mine == ISMINE_SPENDABLE) {
127 pwalletMain->GetPubKey(keyID, vchPubKey);
128 obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
129 obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
130 }
131 return obj;
132 }
133
134 UniValue operator()(const CScriptID &scriptID) const {
135 UniValue obj(UniValue::VOBJ);
136 obj.push_back(Pair("isscript", true));
137 if (mine != ISMINE_NO) {
138 CScript subscript;
139 pwalletMain->GetCScript(scriptID, subscript);
140 std::vector<CTxDestination> addresses;
141 txnouttype whichType;
142 int nRequired;
143 ExtractDestinations(subscript, whichType, addresses, nRequired);
144 obj.push_back(Pair("script", GetTxnOutputType(whichType)));
145 obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
146 UniValue a(UniValue::VARR);
147 BOOST_FOREACH(const CTxDestination& addr, addresses)
148 a.push_back(CBitcoinAddress(addr).ToString());
149 obj.push_back(Pair("addresses", a));
150 if (whichType == TX_MULTISIG)
151 obj.push_back(Pair("sigsrequired", nRequired));
152 }
153 return obj;
154 }
155};
156#endif
157
158UniValue validateaddress(const UniValue& params, bool fHelp)
159{
160 if (fHelp || params.size() != 1)
161 throw runtime_error(
162 "validateaddress \"bitcoinaddress\"\n"
163 "\nReturn information about the given bitcoin address.\n"
164 "\nArguments:\n"
165 "1. \"bitcoinaddress\" (string, required) The bitcoin address to validate\n"
166 "\nResult:\n"
167 "{\n"
168 " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
169 " \"address\" : \"bitcoinaddress\", (string) The bitcoin address validated\n"
170 " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
171 " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
172 " \"isscript\" : true|false, (boolean) If the key is a script\n"
173 " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
174 " \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
175 " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
176 "}\n"
177 "\nExamples:\n"
178 + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
179 + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
180 );
181
182#ifdef ENABLE_WALLET
183 LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
184#else
185 LOCK(cs_main);
186#endif
187
188 CBitcoinAddress address(params[0].get_str());
189 bool isValid = address.IsValid();
190
191 UniValue ret(UniValue::VOBJ);
192 ret.push_back(Pair("isvalid", isValid));
193 if (isValid)
194 {
195 CTxDestination dest = address.Get();
196 string currentAddress = address.ToString();
197 ret.push_back(Pair("address", currentAddress));
198
199 CScript scriptPubKey = GetScriptForDestination(dest);
200 ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
201
202#ifdef ENABLE_WALLET
203 isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
204 ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
205 if (mine != ISMINE_NO) {
206 ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
207 UniValue detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest);
208 ret.pushKVs(detail);
209 }
210 if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
211 ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
212#endif
213 }
214 return ret;
215}
216
217
218UniValue z_validateaddress(const UniValue& params, bool fHelp)
219{
220 if (fHelp || params.size() != 1)
221 throw runtime_error(
222 "z_validateaddress \"zaddr\"\n"
223 "\nReturn information about the given z address.\n"
224 "\nArguments:\n"
225 "1. \"zaddr\" (string, required) The z address to validate\n"
226 "\nResult:\n"
227 "{\n"
228 " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
229 " \"address\" : \"zaddr\", (string) The z address validated\n"
230 " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
231 " \"payingkey\" : \"hex\", (string) The hex value of the paying key, a_pk\n"
232 " \"transmissionkey\" : \"hex\", (string) The hex value of the transmission key, pk_enc\n"
233
234 "}\n"
235 "\nExamples:\n"
236 + HelpExampleCli("validateaddress", "\"zcWsmqT4X2V4jgxbgiCzyrAfRT1vi1F4sn7M5Pkh66izzw8Uk7LBGAH3DtcSMJeUb2pi3W4SQF8LMKkU2cUuVP68yAGcomL\"")
237 );
238
239
240#ifdef ENABLE_WALLET
241 LOCK2(cs_main, pwalletMain->cs_wallet);
242#else
243 LOCK(cs_main);
244#endif
245
246 bool isValid = false;
247 bool isMine = false;
248 std::string payingKey, transmissionKey;
249
250 string strAddress = params[0].get_str();
251 try {
252 CZCPaymentAddress address(strAddress);
253 libzcash::PaymentAddress addr = address.Get();
254
255#ifdef ENABLE_WALLET
256 isMine = pwalletMain->HaveSpendingKey(addr);
257#endif
258 payingKey = addr.a_pk.GetHex();
259 transmissionKey = addr.pk_enc.GetHex();
260 isValid = true;
261 } catch (std::runtime_error e) {
262 // address is invalid, nop here as isValid is false.
263 }
264
265 UniValue ret(UniValue::VOBJ);
266 ret.push_back(Pair("isvalid", isValid));
267 if (isValid)
268 {
269 ret.push_back(Pair("address", strAddress));
270 ret.push_back(Pair("payingkey", payingKey));
271 ret.push_back(Pair("transmissionkey", transmissionKey));
272#ifdef ENABLE_WALLET
273 ret.push_back(Pair("ismine", isMine));
274#endif
275 }
276 return ret;
277}
278
279
280/**
281 * Used by addmultisigaddress / createmultisig:
282 */
283CScript _createmultisig_redeemScript(const UniValue& params)
284{
285 int nRequired = params[0].get_int();
286 const UniValue& keys = params[1].get_array();
287
288 // Gather public keys
289 if (nRequired < 1)
290 throw runtime_error("a multisignature address must require at least one key to redeem");
291 if ((int)keys.size() < nRequired)
292 throw runtime_error(
293 strprintf("not enough keys supplied "
294 "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
295 if (keys.size() > 16)
296 throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
297 std::vector<CPubKey> pubkeys;
298 pubkeys.resize(keys.size());
299 for (unsigned int i = 0; i < keys.size(); i++)
300 {
301 const std::string& ks = keys[i].get_str();
302#ifdef ENABLE_WALLET
303 // Case 1: Bitcoin address and we have full public key:
304 CBitcoinAddress address(ks);
305 if (pwalletMain && address.IsValid())
306 {
307 CKeyID keyID;
308 if (!address.GetKeyID(keyID))
309 throw runtime_error(
310 strprintf("%s does not refer to a key",ks));
311 CPubKey vchPubKey;
312 if (!pwalletMain->GetPubKey(keyID, vchPubKey))
313 throw runtime_error(
314 strprintf("no full public key for address %s",ks));
315 if (!vchPubKey.IsFullyValid())
316 throw runtime_error(" Invalid public key: "+ks);
317 pubkeys[i] = vchPubKey;
318 }
319
320 // Case 2: hex public key
321 else
322#endif
323 if (IsHex(ks))
324 {
325 CPubKey vchPubKey(ParseHex(ks));
326 if (!vchPubKey.IsFullyValid())
327 throw runtime_error(" Invalid public key: "+ks);
328 pubkeys[i] = vchPubKey;
329 }
330 else
331 {
332 throw runtime_error(" Invalid public key: "+ks);
333 }
334 }
335 CScript result = GetScriptForMultisig(nRequired, pubkeys);
336
337 if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
338 throw runtime_error(
339 strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
340
341 return result;
342}
343
344UniValue createmultisig(const UniValue& params, bool fHelp)
345{
346 if (fHelp || params.size() < 2 || params.size() > 2)
347 {
348 string msg = "createmultisig nrequired [\"key\",...]\n"
349 "\nCreates a multi-signature address with n signature of m keys required.\n"
350 "It returns a json object with the address and redeemScript.\n"
351
352 "\nArguments:\n"
353 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
354 "2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
355 " [\n"
356 " \"key\" (string) bitcoin address or hex-encoded public key\n"
357 " ,...\n"
358 " ]\n"
359
360 "\nResult:\n"
361 "{\n"
362 " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
363 " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
364 "}\n"
365
366 "\nExamples:\n"
367 "\nCreate a multisig address from 2 addresses\n"
368 + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
369 "\nAs a json rpc call\n"
370 + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
371 ;
372 throw runtime_error(msg);
373 }
374
375 // Construct using pay-to-script-hash:
376 CScript inner = _createmultisig_redeemScript(params);
377 CScriptID innerID(inner);
378 CBitcoinAddress address(innerID);
379
380 UniValue result(UniValue::VOBJ);
381 result.push_back(Pair("address", address.ToString()));
382 result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
383
384 return result;
385}
386
387UniValue verifymessage(const UniValue& params, bool fHelp)
388{
389 if (fHelp || params.size() != 3)
390 throw runtime_error(
391 "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
392 "\nVerify a signed message\n"
393 "\nArguments:\n"
394 "1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the signature.\n"
395 "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
396 "3. \"message\" (string, required) The message that was signed.\n"
397 "\nResult:\n"
398 "true|false (boolean) If the signature is verified or not.\n"
399 "\nExamples:\n"
400 "\nUnlock the wallet for 30 seconds\n"
401 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
402 "\nCreate the signature\n"
403 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
404 "\nVerify the signature\n"
405 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
406 "\nAs json rpc\n"
407 + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
408 );
409
410 LOCK(cs_main);
411
412 string strAddress = params[0].get_str();
413 string strSign = params[1].get_str();
414 string strMessage = params[2].get_str();
415
416 CBitcoinAddress addr(strAddress);
417 if (!addr.IsValid())
418 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
419
420 CKeyID keyID;
421 if (!addr.GetKeyID(keyID))
422 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
423
424 bool fInvalid = false;
425 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
426
427 if (fInvalid)
428 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
429
430 CHashWriter ss(SER_GETHASH, 0);
431 ss << strMessageMagic;
432 ss << strMessage;
433
434 CPubKey pubkey;
435 if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
436 return false;
437
438 return (pubkey.GetID() == keyID);
439}
440
441UniValue setmocktime(const UniValue& params, bool fHelp)
442{
443 if (fHelp || params.size() != 1)
444 throw runtime_error(
445 "setmocktime timestamp\n"
446 "\nSet the local time to given timestamp (-regtest only)\n"
447 "\nArguments:\n"
448 "1. timestamp (integer, required) Unix seconds-since-epoch timestamp\n"
449 " Pass 0 to go back to using the system time."
450 );
451
452 if (!Params().MineBlocksOnDemand())
453 throw runtime_error("setmocktime for regression testing (-regtest mode) only");
454
455 LOCK(cs_main);
456
457 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
458 SetMockTime(params[0].get_int64());
459
460 return NullUniValue;
461}
This page took 0.026588 seconds and 4 git commands to generate.