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.
11 #include "rpcserver.h"
20 #include <boost/assign/list_of.hpp>
21 #include "json/json_spirit_utils.h"
22 #include "json/json_spirit_value.h"
25 using namespace boost;
26 using namespace boost::assign;
27 using namespace json_spirit;
29 Value getinfo(const Array& params, bool fHelp)
31 if (fHelp || params.size() != 0)
34 "Returns an object containing various state info.\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"
55 + HelpExampleCli("getinfo", "")
56 + HelpExampleRpc("getinfo", "")
60 GetProxy(NET_IPV4, proxy);
63 obj.push_back(Pair("version", (int)CLIENT_VERSION));
64 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
67 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
68 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
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()));
79 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
80 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
82 if (pwalletMain && pwalletMain->IsCrypted())
83 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
84 obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
86 obj.push_back(Pair("relayfee", ValueFromAmount(CTransaction::minRelayTxFee.GetFeePerK())));
87 obj.push_back(Pair("errors", GetWarnings("statusbar")));
92 class DescribeAddressVisitor : public boost::static_visitor<Object>
95 Object operator()(const CNoDestination &dest) const { return Object(); }
97 Object operator()(const CKeyID &keyID) const {
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()));
107 Object operator()(const CScriptID &scriptID) const {
109 obj.push_back(Pair("isscript", true));
111 pwalletMain->GetCScript(scriptID, subscript);
112 std::vector<CTxDestination> addresses;
113 txnouttype whichType;
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())));
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));
129 Value validateaddress(const Array& params, bool fHelp)
131 if (fHelp || params.size() != 1)
133 "validateaddress \"bitcoinaddress\"\n"
134 "\nReturn information about the given bitcoin address.\n"
136 "1. \"bitcoinaddress\" (string, required) The bitcoin address to validate\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"
148 + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
149 + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
152 CBitcoinAddress address(params[0].get_str());
153 bool isValid = address.IsValid();
156 ret.push_back(Pair("isvalid", isValid));
159 CTxDestination dest = address.Get();
160 string currentAddress = address.ToString();
161 ret.push_back(Pair("address", currentAddress));
163 bool fMine = pwalletMain ? IsMine(*pwalletMain, dest) : false;
164 ret.push_back(Pair("ismine", fMine));
166 Object detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
167 ret.insert(ret.end(), detail.begin(), detail.end());
169 if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
170 ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
177 // Used by addmultisigaddress / createmultisig:
179 CScript _createmultisig_redeemScript(const Array& params)
181 int nRequired = params[0].get_int();
182 const Array& keys = params[1].get_array();
184 // Gather public keys
186 throw runtime_error("a multisignature address must require at least one key to redeem");
187 if ((int)keys.size() < nRequired)
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++)
195 const std::string& ks = keys[i].get_str();
197 // Case 1: Bitcoin address and we have full public key:
198 CBitcoinAddress address(ks);
199 if (pwalletMain && address.IsValid())
202 if (!address.GetKeyID(keyID))
204 strprintf("%s does not refer to a key",ks));
206 if (!pwalletMain->GetPubKey(keyID, vchPubKey))
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;
214 // Case 2: hex public key
219 CPubKey vchPubKey(ParseHex(ks));
220 if (!vchPubKey.IsFullyValid())
221 throw runtime_error(" Invalid public key: "+ks);
222 pubkeys[i] = vchPubKey;
226 throw runtime_error(" Invalid public key: "+ks);
230 result.SetMultisig(nRequired, pubkeys);
232 if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
234 strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
239 Value createmultisig(const Array& params, bool fHelp)
241 if (fHelp || params.size() < 2 || params.size() > 2)
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"
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"
251 " \"key\" (string) bitcoin address or hex-encoded public key\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"
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\\\"]\"")
267 throw runtime_error(msg);
270 // Construct using pay-to-script-hash:
271 CScript inner = _createmultisig_redeemScript(params);
272 CScriptID innerID = inner.GetID();
273 CBitcoinAddress address(innerID);
276 result.push_back(Pair("address", address.ToString()));
277 result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
282 Value verifymessage(const Array& params, bool fHelp)
284 if (fHelp || params.size() != 3)
286 "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
287 "\nVerify a signed message\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"
293 "true|false (boolean) If the signature is verified or not.\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\"") +
302 + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
305 string strAddress = params[0].get_str();
306 string strSign = params[1].get_str();
307 string strMessage = params[2].get_str();
309 CBitcoinAddress addr(strAddress);
311 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
314 if (!addr.GetKeyID(keyID))
315 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
317 bool fInvalid = false;
318 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
321 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
323 CHashWriter ss(SER_GETHASH, 0);
324 ss << strMessageMagic;
328 if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
331 return (pubkey.GetID() == keyID);