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"
21 #include <boost/assign/list_of.hpp>
22 #include "json/json_spirit_utils.h"
23 #include "json/json_spirit_value.h"
25 using namespace boost;
26 using namespace boost::assign;
27 using namespace json_spirit;
30 Value getinfo(const Array& params, bool fHelp)
32 if (fHelp || params.size() != 0)
35 "Returns an object containing various state info.\n"
38 " \"version\": xxxxx, (numeric) the server version\n"
39 " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
40 " \"walletversion\": xxxxx, (numeric) the wallet version\n"
41 " \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n"
42 " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
43 " \"timeoffset\": xxxxx, (numeric) the time offset\n"
44 " \"connections\": xxxxx, (numeric) the number of connections\n"
45 " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n"
46 " \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
47 " \"testnet\": true|false, (boolean) if the server is using testnet or not\n"
48 " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
49 " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
50 " \"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"
51 " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in btc/kb\n"
52 " \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n"
53 " \"errors\": \"...\" (string) any error messages\n"
56 + HelpExampleCli("getinfo", "")
57 + HelpExampleRpc("getinfo", "")
61 GetProxy(NET_IPV4, proxy);
64 obj.push_back(Pair("version", (int)CLIENT_VERSION));
65 obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
68 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
69 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
72 obj.push_back(Pair("blocks", (int)chainActive.Height()));
73 obj.push_back(Pair("timeoffset", GetTimeOffset()));
74 obj.push_back(Pair("connections", (int)vNodes.size()));
75 obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
76 obj.push_back(Pair("difficulty", (double)GetDifficulty()));
77 obj.push_back(Pair("testnet", Params().NetworkID() == CBaseChainParams::TESTNET));
80 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
81 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
83 if (pwalletMain && pwalletMain->IsCrypted())
84 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
85 obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
87 obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
88 obj.push_back(Pair("errors", GetWarnings("statusbar")));
93 class DescribeAddressVisitor : public boost::static_visitor<Object>
96 Object operator()(const CNoDestination &dest) const { return Object(); }
98 Object operator()(const CKeyID &keyID) const {
101 pwalletMain->GetPubKey(keyID, vchPubKey);
102 obj.push_back(Pair("isscript", false));
103 obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
104 obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
108 Object operator()(const CScriptID &scriptID) const {
110 obj.push_back(Pair("isscript", true));
112 pwalletMain->GetCScript(scriptID, subscript);
113 std::vector<CTxDestination> addresses;
114 txnouttype whichType;
116 ExtractDestinations(subscript, whichType, addresses, nRequired);
117 obj.push_back(Pair("script", GetTxnOutputType(whichType)));
118 obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
120 BOOST_FOREACH(const CTxDestination& addr, addresses)
121 a.push_back(CBitcoinAddress(addr).ToString());
122 obj.push_back(Pair("addresses", a));
123 if (whichType == TX_MULTISIG)
124 obj.push_back(Pair("sigsrequired", nRequired));
130 Value validateaddress(const Array& params, bool fHelp)
132 if (fHelp || params.size() != 1)
134 "validateaddress \"bitcoinaddress\"\n"
135 "\nReturn information about the given bitcoin address.\n"
137 "1. \"bitcoinaddress\" (string, required) The bitcoin address to validate\n"
140 " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
141 " \"address\" : \"bitcoinaddress\", (string) The bitcoin address validated\n"
142 " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
143 " \"isscript\" : true|false, (boolean) If the key is a script\n"
144 " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
145 " \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
146 " \"account\" : \"account\" (string) The account associated with the address, \"\" is the default account\n"
149 + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
150 + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
153 CBitcoinAddress address(params[0].get_str());
154 bool isValid = address.IsValid();
157 ret.push_back(Pair("isvalid", isValid));
160 CTxDestination dest = address.Get();
161 string currentAddress = address.ToString();
162 ret.push_back(Pair("address", currentAddress));
164 bool fMine = pwalletMain ? IsMine(*pwalletMain, dest) : false;
165 ret.push_back(Pair("ismine", fMine));
167 Object detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
168 ret.insert(ret.end(), detail.begin(), detail.end());
170 if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
171 ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
178 // Used by addmultisigaddress / createmultisig:
180 CScript _createmultisig_redeemScript(const Array& params)
182 int nRequired = params[0].get_int();
183 const Array& keys = params[1].get_array();
185 // Gather public keys
187 throw runtime_error("a multisignature address must require at least one key to redeem");
188 if ((int)keys.size() < nRequired)
190 strprintf("not enough keys supplied "
191 "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
192 std::vector<CPubKey> pubkeys;
193 pubkeys.resize(keys.size());
194 for (unsigned int i = 0; i < keys.size(); i++)
196 const std::string& ks = keys[i].get_str();
198 // Case 1: Bitcoin address and we have full public key:
199 CBitcoinAddress address(ks);
200 if (pwalletMain && address.IsValid())
203 if (!address.GetKeyID(keyID))
205 strprintf("%s does not refer to a key",ks));
207 if (!pwalletMain->GetPubKey(keyID, vchPubKey))
209 strprintf("no full public key for address %s",ks));
210 if (!vchPubKey.IsFullyValid())
211 throw runtime_error(" Invalid public key: "+ks);
212 pubkeys[i] = vchPubKey;
215 // Case 2: hex public key
220 CPubKey vchPubKey(ParseHex(ks));
221 if (!vchPubKey.IsFullyValid())
222 throw runtime_error(" Invalid public key: "+ks);
223 pubkeys[i] = vchPubKey;
227 throw runtime_error(" Invalid public key: "+ks);
231 result.SetMultisig(nRequired, pubkeys);
233 if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
235 strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
240 Value createmultisig(const Array& params, bool fHelp)
242 if (fHelp || params.size() < 2 || params.size() > 2)
244 string msg = "createmultisig nrequired [\"key\",...]\n"
245 "\nCreates a multi-signature address with n signature of m keys required.\n"
246 "It returns a json object with the address and redeemScript.\n"
249 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
250 "2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
252 " \"key\" (string) bitcoin address or hex-encoded public key\n"
258 " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
259 " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
263 "\nCreate a multisig address from 2 addresses\n"
264 + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
265 "\nAs a json rpc call\n"
266 + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
268 throw runtime_error(msg);
271 // Construct using pay-to-script-hash:
272 CScript inner = _createmultisig_redeemScript(params);
273 CScriptID innerID = inner.GetID();
274 CBitcoinAddress address(innerID);
277 result.push_back(Pair("address", address.ToString()));
278 result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
283 Value verifymessage(const Array& params, bool fHelp)
285 if (fHelp || params.size() != 3)
287 "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
288 "\nVerify a signed message\n"
290 "1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the signature.\n"
291 "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
292 "3. \"message\" (string, required) The message that was signed.\n"
294 "true|false (boolean) If the signature is verified or not.\n"
296 "\nUnlock the wallet for 30 seconds\n"
297 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
298 "\nCreate the signature\n"
299 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
300 "\nVerify the signature\n"
301 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
303 + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
306 string strAddress = params[0].get_str();
307 string strSign = params[1].get_str();
308 string strMessage = params[2].get_str();
310 CBitcoinAddress addr(strAddress);
312 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
315 if (!addr.GetKeyID(keyID))
316 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
318 bool fInvalid = false;
319 vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
322 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
324 CHashWriter ss(SER_GETHASH, 0);
325 ss << strMessageMagic;
329 if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
332 return (pubkey.GetID() == keyID);