1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 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"
9 #include "validation.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 JSONRPCRequest
& request
)
44 if (request
.fHelp
|| request
.params
.size() != 0)
47 "\nDEPRECATED. 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 Unix 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()));
93 obj
.push_back(Pair("connections", (int)g_connman
->GetNodeCount(CConnman::CONNECTIONS_ALL
)));
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().NetworkIDString() == CBaseChainParams::TESTNET
));
99 obj
.push_back(Pair("keypoololdest", pwalletMain
->GetOldestKeyPoolTime()));
100 obj
.push_back(Pair("keypoolsize", (int)pwalletMain
->GetKeyPoolSize()));
102 if (pwalletMain
&& pwalletMain
->IsCrypted())
103 obj
.push_back(Pair("unlocked_until", nWalletUnlockTime
));
104 obj
.push_back(Pair("paytxfee", ValueFromAmount(payTxFee
.GetFeePerK())));
106 obj
.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee
.GetFeePerK())));
107 obj
.push_back(Pair("errors", GetWarnings("statusbar")));
112 class DescribeAddressVisitor
: public boost::static_visitor
<UniValue
>
115 UniValue
operator()(const CNoDestination
&dest
) const { return UniValue(UniValue::VOBJ
); }
117 UniValue
operator()(const CKeyID
&keyID
) const {
118 UniValue
obj(UniValue::VOBJ
);
120 obj
.push_back(Pair("isscript", false));
121 if (pwalletMain
&& pwalletMain
->GetPubKey(keyID
, vchPubKey
)) {
122 obj
.push_back(Pair("pubkey", HexStr(vchPubKey
)));
123 obj
.push_back(Pair("iscompressed", vchPubKey
.IsCompressed()));
128 UniValue
operator()(const CScriptID
&scriptID
) const {
129 UniValue
obj(UniValue::VOBJ
);
131 obj
.push_back(Pair("isscript", true));
132 if (pwalletMain
&& pwalletMain
->GetCScript(scriptID
, subscript
)) {
133 std::vector
<CTxDestination
> addresses
;
134 txnouttype whichType
;
136 ExtractDestinations(subscript
, whichType
, addresses
, nRequired
);
137 obj
.push_back(Pair("script", GetTxnOutputType(whichType
)));
138 obj
.push_back(Pair("hex", HexStr(subscript
.begin(), subscript
.end())));
139 UniValue
a(UniValue::VARR
);
140 BOOST_FOREACH(const CTxDestination
& addr
, addresses
)
141 a
.push_back(CBitcoinAddress(addr
).ToString());
142 obj
.push_back(Pair("addresses", a
));
143 if (whichType
== TX_MULTISIG
)
144 obj
.push_back(Pair("sigsrequired", nRequired
));
151 UniValue
validateaddress(const JSONRPCRequest
& request
)
153 if (request
.fHelp
|| request
.params
.size() != 1)
155 "validateaddress \"address\"\n"
156 "\nReturn information about the given bitcoin address.\n"
158 "1. \"address\" (string, required) The bitcoin address to validate\n"
161 " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
162 " \"address\" : \"address\", (string) The bitcoin address validated\n"
163 " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
164 " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
165 " \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n"
166 " \"isscript\" : true|false, (boolean) If the key is a script\n"
167 " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
168 " \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
169 " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
170 " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n"
171 " \"hdmasterkeyid\" : \"<hash160>\" (string, optional) The Hash160 of the HD master pubkey\n"
174 + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
175 + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
179 LOCK2(cs_main
, pwalletMain
? &pwalletMain
->cs_wallet
: NULL
);
184 CBitcoinAddress
address(request
.params
[0].get_str());
185 bool isValid
= address
.IsValid();
187 UniValue
ret(UniValue::VOBJ
);
188 ret
.push_back(Pair("isvalid", isValid
));
191 CTxDestination dest
= address
.Get();
192 string currentAddress
= address
.ToString();
193 ret
.push_back(Pair("address", currentAddress
));
195 CScript scriptPubKey
= GetScriptForDestination(dest
);
196 ret
.push_back(Pair("scriptPubKey", HexStr(scriptPubKey
.begin(), scriptPubKey
.end())));
199 isminetype mine
= pwalletMain
? IsMine(*pwalletMain
, dest
) : ISMINE_NO
;
200 ret
.push_back(Pair("ismine", (mine
& ISMINE_SPENDABLE
) ? true : false));
201 ret
.push_back(Pair("iswatchonly", (mine
& ISMINE_WATCH_ONLY
) ? true: false));
202 UniValue detail
= boost::apply_visitor(DescribeAddressVisitor(), dest
);
204 if (pwalletMain
&& pwalletMain
->mapAddressBook
.count(dest
))
205 ret
.push_back(Pair("account", pwalletMain
->mapAddressBook
[dest
].name
));
207 if (pwalletMain
&& address
.GetKeyID(keyID
) && pwalletMain
->mapKeyMetadata
.count(keyID
) && !pwalletMain
->mapKeyMetadata
[keyID
].hdKeypath
.empty())
209 ret
.push_back(Pair("hdkeypath", pwalletMain
->mapKeyMetadata
[keyID
].hdKeypath
));
210 ret
.push_back(Pair("hdmasterkeyid", pwalletMain
->mapKeyMetadata
[keyID
].hdMasterKeyID
.GetHex()));
218 * Used by addmultisigaddress / createmultisig:
220 CScript
_createmultisig_redeemScript(const UniValue
& params
)
222 int nRequired
= params
[0].get_int();
223 const UniValue
& keys
= params
[1].get_array();
225 // Gather public keys
227 throw runtime_error("a multisignature address must require at least one key to redeem");
228 if ((int)keys
.size() < nRequired
)
230 strprintf("not enough keys supplied "
231 "(got %u keys, but need at least %d to redeem)", keys
.size(), nRequired
));
232 if (keys
.size() > 16)
233 throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
234 std::vector
<CPubKey
> pubkeys
;
235 pubkeys
.resize(keys
.size());
236 for (unsigned int i
= 0; i
< keys
.size(); i
++)
238 const std::string
& ks
= keys
[i
].get_str();
240 // Case 1: Bitcoin address and we have full public key:
241 CBitcoinAddress
address(ks
);
242 if (pwalletMain
&& address
.IsValid())
245 if (!address
.GetKeyID(keyID
))
247 strprintf("%s does not refer to a key",ks
));
249 if (!pwalletMain
->GetPubKey(keyID
, vchPubKey
))
251 strprintf("no full public key for address %s",ks
));
252 if (!vchPubKey
.IsFullyValid())
253 throw runtime_error(" Invalid public key: "+ks
);
254 pubkeys
[i
] = vchPubKey
;
257 // Case 2: hex public key
262 CPubKey
vchPubKey(ParseHex(ks
));
263 if (!vchPubKey
.IsFullyValid())
264 throw runtime_error(" Invalid public key: "+ks
);
265 pubkeys
[i
] = vchPubKey
;
269 throw runtime_error(" Invalid public key: "+ks
);
272 CScript result
= GetScriptForMultisig(nRequired
, pubkeys
);
274 if (result
.size() > MAX_SCRIPT_ELEMENT_SIZE
)
276 strprintf("redeemScript exceeds size limit: %d > %d", result
.size(), MAX_SCRIPT_ELEMENT_SIZE
));
281 UniValue
createmultisig(const JSONRPCRequest
& request
)
283 if (request
.fHelp
|| request
.params
.size() < 2 || request
.params
.size() > 2)
285 string msg
= "createmultisig nrequired [\"key\",...]\n"
286 "\nCreates a multi-signature address with n signature of m keys required.\n"
287 "It returns a json object with the address and redeemScript.\n"
290 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
291 "2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
293 " \"key\" (string) bitcoin address or hex-encoded public key\n"
299 " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
300 " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
304 "\nCreate a multisig address from 2 addresses\n"
305 + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
306 "\nAs a json rpc call\n"
307 + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
309 throw runtime_error(msg
);
312 // Construct using pay-to-script-hash:
313 CScript inner
= _createmultisig_redeemScript(request
.params
);
314 CScriptID
innerID(inner
);
315 CBitcoinAddress
address(innerID
);
317 UniValue
result(UniValue::VOBJ
);
318 result
.push_back(Pair("address", address
.ToString()));
319 result
.push_back(Pair("redeemScript", HexStr(inner
.begin(), inner
.end())));
324 UniValue
verifymessage(const JSONRPCRequest
& request
)
326 if (request
.fHelp
|| request
.params
.size() != 3)
328 "verifymessage \"address\" \"signature\" \"message\"\n"
329 "\nVerify a signed message\n"
331 "1. \"address\" (string, required) The bitcoin address to use for the signature.\n"
332 "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
333 "3. \"message\" (string, required) The message that was signed.\n"
335 "true|false (boolean) If the signature is verified or not.\n"
337 "\nUnlock the wallet for 30 seconds\n"
338 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
339 "\nCreate the signature\n"
340 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
341 "\nVerify the signature\n"
342 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
344 + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
349 string strAddress
= request
.params
[0].get_str();
350 string strSign
= request
.params
[1].get_str();
351 string strMessage
= request
.params
[2].get_str();
353 CBitcoinAddress
addr(strAddress
);
355 throw JSONRPCError(RPC_TYPE_ERROR
, "Invalid address");
358 if (!addr
.GetKeyID(keyID
))
359 throw JSONRPCError(RPC_TYPE_ERROR
, "Address does not refer to key");
361 bool fInvalid
= false;
362 vector
<unsigned char> vchSig
= DecodeBase64(strSign
.c_str(), &fInvalid
);
365 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY
, "Malformed base64 encoding");
367 CHashWriter
ss(SER_GETHASH
, 0);
368 ss
<< strMessageMagic
;
372 if (!pubkey
.RecoverCompact(ss
.GetHash(), vchSig
))
375 return (pubkey
.GetID() == keyID
);
378 UniValue
signmessagewithprivkey(const JSONRPCRequest
& request
)
380 if (request
.fHelp
|| request
.params
.size() != 2)
382 "signmessagewithprivkey \"privkey\" \"message\"\n"
383 "\nSign a message with the private key of an address\n"
385 "1. \"privkey\" (string, required) The private key to sign the message with.\n"
386 "2. \"message\" (string, required) The message to create a signature of.\n"
388 "\"signature\" (string) The signature of the message encoded in base 64\n"
390 "\nCreate the signature\n"
391 + HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") +
392 "\nVerify the signature\n"
393 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
395 + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"")
398 string strPrivkey
= request
.params
[0].get_str();
399 string strMessage
= request
.params
[1].get_str();
401 CBitcoinSecret vchSecret
;
402 bool fGood
= vchSecret
.SetString(strPrivkey
);
404 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY
, "Invalid private key");
405 CKey key
= vchSecret
.GetKey();
407 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY
, "Private key outside allowed range");
409 CHashWriter
ss(SER_GETHASH
, 0);
410 ss
<< strMessageMagic
;
413 vector
<unsigned char> vchSig
;
414 if (!key
.SignCompact(ss
.GetHash(), vchSig
))
415 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY
, "Sign failed");
417 return EncodeBase64(&vchSig
[0], vchSig
.size());
420 UniValue
setmocktime(const JSONRPCRequest
& request
)
422 if (request
.fHelp
|| request
.params
.size() != 1)
424 "setmocktime timestamp\n"
425 "\nSet the local time to given timestamp (-regtest only)\n"
427 "1. timestamp (integer, required) Unix seconds-since-epoch timestamp\n"
428 " Pass 0 to go back to using the system time."
431 if (!Params().MineBlocksOnDemand())
432 throw runtime_error("setmocktime for regression testing (-regtest mode) only");
434 // For now, don't change mocktime if we're in the middle of validation, as
435 // this could have an effect on mempool time-based eviction, as well as
436 // IsCurrentForFeeEstimation() and IsInitialBlockDownload().
437 // TODO: figure out the right way to synchronize around mocktime, and
438 // ensure all call sites of GetTime() are accessing this safely.
441 RPCTypeCheck(request
.params
, boost::assign::list_of(UniValue::VNUM
));
442 SetMockTime(request
.params
[0].get_int64());
447 static UniValue
RPCLockedMemoryInfo()
449 LockedPool::Stats stats
= LockedPoolManager::Instance().stats();
450 UniValue
obj(UniValue::VOBJ
);
451 obj
.push_back(Pair("used", uint64_t(stats
.used
)));
452 obj
.push_back(Pair("free", uint64_t(stats
.free
)));
453 obj
.push_back(Pair("total", uint64_t(stats
.total
)));
454 obj
.push_back(Pair("locked", uint64_t(stats
.locked
)));
455 obj
.push_back(Pair("chunks_used", uint64_t(stats
.chunks_used
)));
456 obj
.push_back(Pair("chunks_free", uint64_t(stats
.chunks_free
)));
460 UniValue
getmemoryinfo(const JSONRPCRequest
& request
)
462 /* Please, avoid using the word "pool" here in the RPC interface or help,
463 * as users will undoubtedly confuse it with the other "memory pool"
465 if (request
.fHelp
|| request
.params
.size() != 0)
468 "Returns an object containing information about memory usage.\n"
471 " \"locked\": { (json object) Information about locked memory manager\n"
472 " \"used\": xxxxx, (numeric) Number of bytes used\n"
473 " \"free\": xxxxx, (numeric) Number of bytes available in current arenas\n"
474 " \"total\": xxxxxxx, (numeric) Total number of bytes managed\n"
475 " \"locked\": xxxxxx, (numeric) Amount of bytes that succeeded locking. If this number is smaller than total, locking pages failed at some point and key data could be swapped to disk.\n"
476 " \"chunks_used\": xxxxx, (numeric) Number allocated chunks\n"
477 " \"chunks_free\": xxxxx, (numeric) Number unused chunks\n"
481 + HelpExampleCli("getmemoryinfo", "")
482 + HelpExampleRpc("getmemoryinfo", "")
484 UniValue
obj(UniValue::VOBJ
);
485 obj
.push_back(Pair("locked", RPCLockedMemoryInfo()));
489 UniValue
echo(const JSONRPCRequest
& request
)
493 "echo|echojson \"message\" ...\n"
494 "\nSimply echo back the input arguments. This command is for testing.\n"
495 "\nThe difference between echo and echojson is that echojson has argument conversion enabled in the client-side table in"
496 "bitcoin-cli and the GUI. There is no server-side difference."
499 return request
.params
;
502 static const CRPCCommand commands
[] =
503 { // category name actor (function) okSafeMode
504 // --------------------- ------------------------ ----------------------- ----------
505 { "control", "getinfo", &getinfo
, true, {} }, /* uses wallet if enabled */
506 { "control", "getmemoryinfo", &getmemoryinfo
, true, {} },
507 { "util", "validateaddress", &validateaddress
, true, {"address"} }, /* uses wallet if enabled */
508 { "util", "createmultisig", &createmultisig
, true, {"nrequired","keys"} },
509 { "util", "verifymessage", &verifymessage
, true, {"address","signature","message"} },
510 { "util", "signmessagewithprivkey", &signmessagewithprivkey
, true, {"privkey","message"} },
512 /* Not shown in help */
513 { "hidden", "setmocktime", &setmocktime
, true, {"timestamp"}},
514 { "hidden", "echo", &echo
, true, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
515 { "hidden", "echojson", &echo
, true, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
518 void RegisterMiscRPCCommands(CRPCTable
&t
)
520 for (unsigned int vcidx
= 0; vcidx
< ARRAYLEN(commands
); vcidx
++)
521 t
.appendCommand(commands
[vcidx
].name
, &commands
[vcidx
]);