1
// Copyright (c) 2010 Satoshi Nakamoto
2
// Copyright (c) 2009-2015 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.
7
#include "clientversion.h"
12
#include "rpc/server.h"
15
#include "utilstrencodings.h"
17
#include "wallet/wallet.h"
18
#include "wallet/walletdb.h"
23
#include <boost/assign/list_of.hpp>
30
* @note Do not add or change anything in the information returned by this
31
* method. `getinfo` exists for backwards-compatibility only. It combines
32
* information from wildly different sources in the program, which is a mess,
33
* and is thus planned to be deprecated eventually.
35
* Based on the source of the information, new information should be added to:
36
* - `getblockchaininfo`,
37
* - `getnetworkinfo` or
40
* Or alternatively, create a specific query method for the information.
42
UniValue getinfo(const UniValue& params, bool fHelp)
44
if (fHelp || params.size() != 0)
47
"Returns an object containing various state info.\n"
50
" \"version\": xxxxx, (numeric) the server version\n"
51
" \"protocolversion\": xxxxx, (numeric) the protocol version\n"
52
" \"walletversion\": xxxxx, (numeric) the wallet version\n"
53
" \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n"
54
" \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
55
" \"timeoffset\": xxxxx, (numeric) the time offset\n"
56
" \"connections\": xxxxx, (numeric) the number of connections\n"
57
" \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n"
58
" \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
59
" \"testnet\": true|false, (boolean) if the server is using testnet or not\n"
60
" \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
61
" \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
62
" \"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"
63
" \"paytxfee\": x.xxxx, (numeric) the transaction fee set in " + CURRENCY_UNIT + "/kB\n"
64
" \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n"
65
" \"errors\": \"...\" (string) any error messages\n"
68
+ HelpExampleCli("getinfo", "")
69
+ HelpExampleRpc("getinfo", "")
73
LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
79
GetProxy(NET_IPV4, proxy);
81
UniValue obj(UniValue::VOBJ);
82
obj.push_back(Pair("version", CLIENT_VERSION));
83
obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
86
obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
87
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
90
obj.push_back(Pair("blocks", (int)chainActive.Height()));
91
obj.push_back(Pair("timeoffset", GetTimeOffset()));
92
obj.push_back(Pair("connections", (int)vNodes.size()));
93
obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string())));
94
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
95
obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
98
obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
99
obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
101
if (pwalletMain && pwalletMain->IsCrypted())
102
obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
103
obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
105
obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
106
obj.push_back(Pair("errors", GetWarnings("statusbar")));
111
class DescribeAddressVisitor : public boost::static_visitor<UniValue>
114
UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
116
UniValue operator()(const CKeyID &keyID) const {
117
UniValue obj(UniValue::VOBJ);
119
obj.push_back(Pair("isscript", false));
120
if (pwalletMain && pwalletMain->GetPubKey(keyID, vchPubKey)) {
121
obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
122
obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
127
UniValue operator()(const CScriptID &scriptID) const {
128
UniValue obj(UniValue::VOBJ);
130
obj.push_back(Pair("isscript", true));
131
if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) {
132
std::vector<CTxDestination> addresses;
133
txnouttype whichType;
135
ExtractDestinations(subscript, whichType, addresses, nRequired);
136
obj.push_back(Pair("script", GetTxnOutputType(whichType)));
137
obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
138
UniValue a(UniValue::VARR);
139
BOOST_FOREACH(const CTxDestination& addr, addresses)
140
a.push_back(CBitcoinAddress(addr).ToString());
141
obj.push_back(Pair("addresses", a));
142
if (whichType == TX_MULTISIG)
143
obj.push_back(Pair("sigsrequired", nRequired));
150
UniValue validateaddress(const UniValue& params, bool fHelp)
152
if (fHelp || params.size() != 1)
154
"validateaddress \"bitcoinaddress\"\n"
155
"\nReturn information about the given bitcoin address.\n"
157
"1. \"bitcoinaddress\" (string, required) The bitcoin address to validate\n"
160
" \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
161
" \"address\" : \"bitcoinaddress\", (string) The bitcoin address validated\n"
162
" \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
163
" \"ismine\" : true|false, (boolean) If the address is yours or not\n"
164
" \"iswatchonly\" : true|false, (boolean) If the address is watchonly\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) DEPRECATED. The account associated with the address, \"\" is the default account\n"
169
" \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n"
170
" \"hdmasterkeyid\" : \"<hash160>\" (string, optional) The Hash160 of the HD master pubkey\n"
173
+ HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
174
+ HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
178
LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
183
CBitcoinAddress address(params[0].get_str());
184
bool isValid = address.IsValid();
186
UniValue ret(UniValue::VOBJ);
187
ret.push_back(Pair("isvalid", isValid));
190
CTxDestination dest = address.Get();
191
string currentAddress = address.ToString();
192
ret.push_back(Pair("address", currentAddress));
194
CScript scriptPubKey = GetScriptForDestination(dest);
195
ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
198
isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
199
ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
200
ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
201
UniValue detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
203
if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
204
ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
206
if (pwalletMain && address.GetKeyID(keyID) && pwalletMain->mapKeyMetadata.count(keyID) && !pwalletMain->mapKeyMetadata[keyID].hdKeypath.empty())
208
ret.push_back(Pair("hdkeypath", pwalletMain->mapKeyMetadata[keyID].hdKeypath));
209
ret.push_back(Pair("hdmasterkeyid", pwalletMain->mapKeyMetadata[keyID].hdMasterKeyID.GetHex()));
217
* Used by addmultisigaddress / createmultisig:
219
CScript _createmultisig_redeemScript(const UniValue& params)
221
int nRequired = params[0].get_int();
222
const UniValue& keys = params[1].get_array();
224
// Gather public keys
226
throw runtime_error("a multisignature address must require at least one key to redeem");
227
if ((int)keys.size() < nRequired)
229
strprintf("not enough keys supplied "
230
"(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
231
if (keys.size() > 16)
232
throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
233
std::vector<CPubKey> pubkeys;
234
pubkeys.resize(keys.size());
235
for (unsigned int i = 0; i < keys.size(); i++)
237
const std::string& ks = keys[i].get_str();
239
// Case 1: Bitcoin address and we have full public key:
240
CBitcoinAddress address(ks);
241
if (pwalletMain && address.IsValid())
244
if (!address.GetKeyID(keyID))
246
strprintf("%s does not refer to a key",ks));
248
if (!pwalletMain->GetPubKey(keyID, vchPubKey))
250
strprintf("no full public key for address %s",ks));
251
if (!vchPubKey.IsFullyValid())
252
throw runtime_error(" Invalid public key: "+ks);
253
pubkeys[i] = vchPubKey;
256
// Case 2: hex public key
261
CPubKey vchPubKey(ParseHex(ks));
262
if (!vchPubKey.IsFullyValid())
263
throw runtime_error(" Invalid public key: "+ks);
264
pubkeys[i] = vchPubKey;
268
throw runtime_error(" Invalid public key: "+ks);
271
CScript result = GetScriptForMultisig(nRequired, pubkeys);
273
if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
275
strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
280
UniValue createmultisig(const UniValue& params, bool fHelp)
282
if (fHelp || params.size() < 2 || params.size() > 2)
284
string msg = "createmultisig nrequired [\"key\",...]\n"
285
"\nCreates a multi-signature address with n signature of m keys required.\n"
286
"It returns a json object with the address and redeemScript.\n"
289
"1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
290
"2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
292
" \"key\" (string) bitcoin address or hex-encoded public key\n"
298
" \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
299
" \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
303
"\nCreate a multisig address from 2 addresses\n"
304
+ HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
305
"\nAs a json rpc call\n"
306
+ HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
308
throw runtime_error(msg);
311
// Construct using pay-to-script-hash:
312
CScript inner = _createmultisig_redeemScript(params);
313
CScriptID innerID(inner);
314
CBitcoinAddress address(innerID);
316
UniValue result(UniValue::VOBJ);
317
result.push_back(Pair("address", address.ToString()));
318
result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
323
UniValue createwitnessaddress(const UniValue& params, bool fHelp)
325
if (fHelp || params.size() < 1 || params.size() > 1)
327
string msg = "createwitnessaddress \"script\"\n"
328
"\nCreates a witness address for a particular script.\n"
329
"It returns a json object with the address and witness script.\n"
332
"1. \"script\" (string, required) A hex encoded script\n"
336
" \"address\":\"multisigaddress\", (string) The value of the new address (P2SH of witness script).\n"
337
" \"witnessScript\":\"script\" (string) The string value of the hex-encoded witness script.\n"
340
throw runtime_error(msg);
343
if (!IsHex(params[0].get_str())) {
344
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Script must be hex-encoded");
347
std::vector<unsigned char> code = ParseHex(params[0].get_str());
348
CScript script(code.begin(), code.end());
349
CScript witscript = GetScriptForWitness(script);
350
CScriptID witscriptid(witscript);
351
CBitcoinAddress address(witscriptid);
353
UniValue result(UniValue::VOBJ);
354
result.push_back(Pair("address", address.ToString()));
355
result.push_back(Pair("witnessScript", HexStr(witscript.begin(), witscript.end())));
360
UniValue verifymessage(const UniValue& params, bool fHelp)
362
if (fHelp || params.size() != 3)
364
"verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
365
"\nVerify a signed message\n"
367
"1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the signature.\n"
368
"2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
369
"3. \"message\" (string, required) The message that was signed.\n"
371
"true|false (boolean) If the signature is verified or not.\n"
373
"\nUnlock the wallet for 30 seconds\n"
374
+ HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
375
"\nCreate the signature\n"
376
+ HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
377
"\nVerify the signature\n"
378
+ HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
380
+ HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
385
string strAddress = params[0].get_str();
386
string strSign = params[1].get_str();
387
string strMessage = params[2].get_str();
389
CBitcoinAddress addr(strAddress);
391
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
394
if (!addr.GetKeyID(keyID))
395
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
397
bool fInvalid = false;
398
vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
401
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
403
CHashWriter ss(SER_GETHASH, 0);
404
ss << strMessageMagic;
408
if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
411
return (pubkey.GetID() == keyID);
414
UniValue signmessagewithprivkey(const UniValue& params, bool fHelp)
416
if (fHelp || params.size() != 2)
418
"signmessagewithprivkey \"privkey\" \"message\"\n"
419
"\nSign a message with the private key of an address\n"
421
"1. \"privkey\" (string, required) The private key to sign the message with.\n"
422
"2. \"message\" (string, required) The message to create a signature of.\n"
424
"\"signature\" (string) The signature of the message encoded in base 64\n"
426
"\nCreate the signature\n"
427
+ HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") +
428
"\nVerify the signature\n"
429
+ HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
431
+ HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"")
434
string strPrivkey = params[0].get_str();
435
string strMessage = params[1].get_str();
437
CBitcoinSecret vchSecret;
438
bool fGood = vchSecret.SetString(strPrivkey);
440
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
441
CKey key = vchSecret.GetKey();
443
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
445
CHashWriter ss(SER_GETHASH, 0);
446
ss << strMessageMagic;
449
vector<unsigned char> vchSig;
450
if (!key.SignCompact(ss.GetHash(), vchSig))
451
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
453
return EncodeBase64(&vchSig[0], vchSig.size());
456
UniValue setmocktime(const UniValue& params, bool fHelp)
458
if (fHelp || params.size() != 1)
460
"setmocktime timestamp\n"
461
"\nSet the local time to given timestamp (-regtest only)\n"
463
"1. timestamp (integer, required) Unix seconds-since-epoch timestamp\n"
464
" Pass 0 to go back to using the system time."
467
if (!Params().MineBlocksOnDemand())
468
throw runtime_error("setmocktime for regression testing (-regtest mode) only");
470
// cs_vNodes is locked and node send/receive times are updated
471
// atomically with the time change to prevent peers from being
472
// disconnected because we think we haven't communicated with them
474
LOCK2(cs_main, cs_vNodes);
476
RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
477
SetMockTime(params[0].get_int64());
479
uint64_t t = GetTime();
480
BOOST_FOREACH(CNode* pnode, vNodes) {
481
pnode->nLastSend = pnode->nLastRecv = t;
487
static const CRPCCommand commands[] =
488
{ // category name actor (function) okSafeMode
489
// --------------------- ------------------------ ----------------------- ----------
490
{ "control", "getinfo", &getinfo, true }, /* uses wallet if enabled */
491
{ "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */
492
{ "util", "createmultisig", &createmultisig, true },
493
{ "util", "createwitnessaddress", &createwitnessaddress, true },
494
{ "util", "verifymessage", &verifymessage, true },
495
{ "util", "signmessagewithprivkey", &signmessagewithprivkey, true },
497
/* Not shown in help */
498
{ "hidden", "setmocktime", &setmocktime, true },
501
void RegisterMiscRPCCommands(CRPCTable &tableRPC)
503
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
504
tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);