LCOV - code coverage report
Current view: top level - src - rpcmisc.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 108 156 69.2 %
Date: 2015-10-12 22:39:14 Functions: 9 13 69.2 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include "utilstrencodings.h"
      16             : #ifdef ENABLE_WALLET
      17             : #include "wallet/wallet.h"
      18             : #include "wallet/walletdb.h"
      19             : #endif
      20             : 
      21             : #include <stdint.h>
      22             : 
      23             : #include <boost/assign/list_of.hpp>
      24             : 
      25             : #include <univalue.h>
      26             : 
      27             : using namespace std;
      28             : 
      29             : /**
      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.
      34             :  *
      35             :  * Based on the source of the information, new information should be added to:
      36             :  * - `getblockchaininfo`,
      37             :  * - `getnetworkinfo` or
      38             :  * - `getwalletinfo`
      39             :  *
      40             :  * Or alternatively, create a specific query method for the information.
      41             :  **/
      42           0 : UniValue getinfo(const UniValue& params, bool fHelp)
      43             : {
      44           0 :     if (fHelp || params.size() != 0)
      45             :         throw runtime_error(
      46             :             "getinfo\n"
      47             :             "Returns an object containing various state info.\n"
      48             :             "\nResult:\n"
      49             :             "{\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           0 :             "  \"paytxfee\": x.xxxx,         (numeric) the transaction fee set in " + CURRENCY_UNIT + "/kB\n"
      64           0 :             "  \"relayfee\": x.xxxx,         (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n"
      65             :             "  \"errors\": \"...\"           (string) any error messages\n"
      66             :             "}\n"
      67             :             "\nExamples:\n"
      68           0 :             + HelpExampleCli("getinfo", "")
      69           0 :             + HelpExampleRpc("getinfo", "")
      70           0 :         );
      71             : 
      72             : #ifdef ENABLE_WALLET
      73           0 :     LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
      74             : #else
      75             :     LOCK(cs_main);
      76             : #endif
      77             : 
      78             :     proxyType proxy;
      79           0 :     GetProxy(NET_IPV4, proxy);
      80             : 
      81           0 :     UniValue obj(UniValue::VOBJ);
      82           0 :     obj.push_back(Pair("version", CLIENT_VERSION));
      83           0 :     obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
      84             : #ifdef ENABLE_WALLET
      85           0 :     if (pwalletMain) {
      86           0 :         obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
      87           0 :         obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
      88             :     }
      89             : #endif
      90           0 :     obj.push_back(Pair("blocks",        (int)chainActive.Height()));
      91           0 :     obj.push_back(Pair("timeoffset",    GetTimeOffset()));
      92           0 :     obj.push_back(Pair("connections",   (int)vNodes.size()));
      93           0 :     obj.push_back(Pair("proxy",         (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string())));
      94           0 :     obj.push_back(Pair("difficulty",    (double)GetDifficulty()));
      95           0 :     obj.push_back(Pair("testnet",       Params().TestnetToBeDeprecatedFieldRPC()));
      96             : #ifdef ENABLE_WALLET
      97           0 :     if (pwalletMain) {
      98           0 :         obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
      99           0 :         obj.push_back(Pair("keypoolsize",   (int)pwalletMain->GetKeyPoolSize()));
     100             :     }
     101           0 :     if (pwalletMain && pwalletMain->IsCrypted())
     102           0 :         obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
     103           0 :     obj.push_back(Pair("paytxfee",      ValueFromAmount(payTxFee.GetFeePerK())));
     104             : #endif
     105           0 :     obj.push_back(Pair("relayfee",      ValueFromAmount(::minRelayTxFee.GetFeePerK())));
     106           0 :     obj.push_back(Pair("errors",        GetWarnings("statusbar")));
     107           0 :     return obj;
     108             : }
     109             : 
     110             : #ifdef ENABLE_WALLET
     111          17 : class DescribeAddressVisitor : public boost::static_visitor<UniValue>
     112             : {
     113             : public:
     114           0 :     UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
     115             : 
     116          15 :     UniValue operator()(const CKeyID &keyID) const {
     117          45 :         UniValue obj(UniValue::VOBJ);
     118             :         CPubKey vchPubKey;
     119          30 :         obj.push_back(Pair("isscript", false));
     120          15 :         if (pwalletMain->GetPubKey(keyID, vchPubKey)) {
     121          45 :             obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
     122          30 :             obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
     123             :         }
     124          15 :         return obj;
     125             :     }
     126             : 
     127           2 :     UniValue operator()(const CScriptID &scriptID) const {
     128           6 :         UniValue obj(UniValue::VOBJ);
     129             :         CScript subscript;
     130           4 :         obj.push_back(Pair("isscript", true));
     131           2 :         if (pwalletMain->GetCScript(scriptID, subscript)) {
     132             :             std::vector<CTxDestination> addresses;
     133             :             txnouttype whichType;
     134             :             int nRequired;
     135           2 :             ExtractDestinations(subscript, whichType, addresses, nRequired);
     136           4 :             obj.push_back(Pair("script", GetTxnOutputType(whichType)));
     137           6 :             obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
     138           8 :             UniValue a(UniValue::VARR);
     139          37 :             BOOST_FOREACH(const CTxDestination& addr, addresses)
     140          15 :                 a.push_back(CBitcoinAddress(addr).ToString());
     141           4 :             obj.push_back(Pair("addresses", a));
     142           2 :             if (whichType == TX_MULTISIG)
     143           6 :                 obj.push_back(Pair("sigsrequired", nRequired));
     144             :         }
     145           2 :         return obj;
     146             :     }
     147             : };
     148             : #endif
     149             : 
     150          17 : UniValue validateaddress(const UniValue& params, bool fHelp)
     151             : {
     152          34 :     if (fHelp || params.size() != 1)
     153             :         throw runtime_error(
     154             :             "validateaddress \"bitcoinaddress\"\n"
     155             :             "\nReturn information about the given bitcoin address.\n"
     156             :             "\nArguments:\n"
     157             :             "1. \"bitcoinaddress\"     (string, required) The bitcoin address to validate\n"
     158             :             "\nResult:\n"
     159             :             "{\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             :             "}\n"
     170             :             "\nExamples:\n"
     171           0 :             + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
     172           0 :             + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
     173           0 :         );
     174             : 
     175             : #ifdef ENABLE_WALLET
     176          17 :     LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
     177             : #else
     178             :     LOCK(cs_main);
     179             : #endif
     180             : 
     181          34 :     CBitcoinAddress address(params[0].get_str());
     182          17 :     bool isValid = address.IsValid();
     183             : 
     184          51 :     UniValue ret(UniValue::VOBJ);
     185          34 :     ret.push_back(Pair("isvalid", isValid));
     186          17 :     if (isValid)
     187             :     {
     188          17 :         CTxDestination dest = address.Get();
     189          17 :         string currentAddress = address.ToString();
     190          51 :         ret.push_back(Pair("address", currentAddress));
     191             : 
     192          17 :         CScript scriptPubKey = GetScriptForDestination(dest);
     193          51 :         ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
     194             : 
     195             : #ifdef ENABLE_WALLET
     196          17 :         isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
     197          34 :         ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
     198          34 :         ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
     199          34 :         UniValue detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
     200          17 :         ret.pushKVs(detail);
     201          34 :         if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
     202          51 :             ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
     203             : #endif
     204             :     }
     205          17 :     return ret;
     206             : }
     207             : 
     208             : /**
     209             :  * Used by addmultisigaddress / createmultisig:
     210             :  */
     211          16 : CScript _createmultisig_redeemScript(const UniValue& params)
     212             : {
     213          16 :     int nRequired = params[0].get_int();
     214          16 :     const UniValue& keys = params[1].get_array();
     215             : 
     216             :     // Gather public keys
     217          16 :     if (nRequired < 1)
     218           3 :         throw runtime_error("a multisignature address must require at least one key to redeem");
     219          15 :     if ((int)keys.size() < nRequired)
     220             :         throw runtime_error(
     221             :             strprintf("not enough keys supplied "
     222          12 :                       "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
     223          11 :     if (keys.size() > 16)
     224           0 :         throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
     225             :     std::vector<CPubKey> pubkeys;
     226          11 :     pubkeys.resize(keys.size());
     227          62 :     for (unsigned int i = 0; i < keys.size(); i++)
     228             :     {
     229          22 :         const std::string& ks = keys[i].get_str();
     230             : #ifdef ENABLE_WALLET
     231             :         // Case 1: Bitcoin address and we have full public key:
     232          22 :         CBitcoinAddress address(ks);
     233          22 :         if (pwalletMain && address.IsValid())
     234             :         {
     235             :             CKeyID keyID;
     236           1 :             if (!address.GetKeyID(keyID))
     237             :                 throw runtime_error(
     238           0 :                     strprintf("%s does not refer to a key",ks));
     239             :             CPubKey vchPubKey;
     240           1 :             if (!pwalletMain->GetPubKey(keyID, vchPubKey))
     241             :                 throw runtime_error(
     242           0 :                     strprintf("no full public key for address %s",ks));
     243           1 :             if (!vchPubKey.IsFullyValid())
     244           0 :                 throw runtime_error(" Invalid public key: "+ks);
     245           2 :             pubkeys[i] = vchPubKey;
     246             :         }
     247             : 
     248             :         // Case 2: hex public key
     249             :         else
     250             : #endif
     251          21 :         if (IsHex(ks))
     252             :         {
     253          38 :             CPubKey vchPubKey(ParseHex(ks));
     254          19 :             if (!vchPubKey.IsFullyValid())
     255           0 :                 throw runtime_error(" Invalid public key: "+ks);
     256          38 :             pubkeys[i] = vchPubKey;
     257             :         }
     258             :         else
     259             :         {
     260           4 :             throw runtime_error(" Invalid public key: "+ks);
     261             :         }
     262             :     }
     263           9 :     CScript result = GetScriptForMultisig(nRequired, pubkeys);
     264             : 
     265          18 :     if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
     266             :         throw runtime_error(
     267           0 :                 strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
     268             : 
     269           9 :     return result;
     270             : }
     271             : 
     272           1 : UniValue createmultisig(const UniValue& params, bool fHelp)
     273             : {
     274           3 :     if (fHelp || params.size() < 2 || params.size() > 2)
     275             :     {
     276             :         string msg = "createmultisig nrequired [\"key\",...]\n"
     277             :             "\nCreates a multi-signature address with n signature of m keys required.\n"
     278             :             "It returns a json object with the address and redeemScript.\n"
     279             : 
     280             :             "\nArguments:\n"
     281             :             "1. nrequired      (numeric, required) The number of required signatures out of the n keys or addresses.\n"
     282             :             "2. \"keys\"       (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
     283             :             "     [\n"
     284             :             "       \"key\"    (string) bitcoin address or hex-encoded public key\n"
     285             :             "       ,...\n"
     286             :             "     ]\n"
     287             : 
     288             :             "\nResult:\n"
     289             :             "{\n"
     290             :             "  \"address\":\"multisigaddress\",  (string) The value of the new multisig address.\n"
     291             :             "  \"redeemScript\":\"script\"       (string) The string value of the hex-encoded redemption script.\n"
     292             :             "}\n"
     293             : 
     294             :             "\nExamples:\n"
     295             :             "\nCreate a multisig address from 2 addresses\n"
     296           0 :             + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
     297             :             "\nAs a json rpc call\n"
     298           0 :             + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
     299             :         ;
     300           0 :         throw runtime_error(msg);
     301             :     }
     302             : 
     303             :     // Construct using pay-to-script-hash:
     304           1 :     CScript inner = _createmultisig_redeemScript(params);
     305           1 :     CScriptID innerID(inner);
     306           2 :     CBitcoinAddress address(innerID);
     307             : 
     308           3 :     UniValue result(UniValue::VOBJ);
     309           3 :     result.push_back(Pair("address", address.ToString()));
     310           3 :     result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
     311             : 
     312           1 :     return result;
     313             : }
     314             : 
     315           6 : UniValue verifymessage(const UniValue& params, bool fHelp)
     316             : {
     317          12 :     if (fHelp || params.size() != 3)
     318             :         throw runtime_error(
     319             :             "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
     320             :             "\nVerify a signed message\n"
     321             :             "\nArguments:\n"
     322             :             "1. \"bitcoinaddress\"  (string, required) The bitcoin address to use for the signature.\n"
     323             :             "2. \"signature\"       (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
     324             :             "3. \"message\"         (string, required) The message that was signed.\n"
     325             :             "\nResult:\n"
     326             :             "true|false   (boolean) If the signature is verified or not.\n"
     327             :             "\nExamples:\n"
     328             :             "\nUnlock the wallet for 30 seconds\n"
     329          16 :             + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
     330             :             "\nCreate the signature\n"
     331          18 :             + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
     332             :             "\nVerify the signature\n"
     333          18 :             + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
     334             :             "\nAs json rpc\n"
     335          16 :             + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
     336           6 :         );
     337             : 
     338           4 :     LOCK(cs_main);
     339             : 
     340           4 :     string strAddress  = params[0].get_str();
     341           4 :     string strSign     = params[1].get_str();
     342           4 :     string strMessage  = params[2].get_str();
     343             : 
     344           4 :     CBitcoinAddress addr(strAddress);
     345           4 :     if (!addr.IsValid())
     346           3 :         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
     347             : 
     348             :     CKeyID keyID;
     349           3 :     if (!addr.GetKeyID(keyID))
     350           0 :         throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
     351             : 
     352           3 :     bool fInvalid = false;
     353           3 :     vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
     354             : 
     355           3 :     if (fInvalid)
     356           0 :         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
     357             : 
     358             :     CHashWriter ss(SER_GETHASH, 0);
     359             :     ss << strMessageMagic;
     360             :     ss << strMessage;
     361             : 
     362             :     CPubKey pubkey;
     363           3 :     if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
     364           0 :         return false;
     365             : 
     366           6 :     return (pubkey.GetID() == keyID);
     367             : }
     368             : 
     369         800 : UniValue setmocktime(const UniValue& params, bool fHelp)
     370             : {
     371        1600 :     if (fHelp || params.size() != 1)
     372             :         throw runtime_error(
     373             :             "setmocktime timestamp\n"
     374             :             "\nSet the local time to given timestamp (-regtest only)\n"
     375             :             "\nArguments:\n"
     376             :             "1. timestamp  (integer, required) Unix seconds-since-epoch timestamp\n"
     377             :             "   Pass 0 to go back to using the system time."
     378           0 :         );
     379             : 
     380         800 :     if (!Params().MineBlocksOnDemand())
     381           0 :         throw runtime_error("setmocktime for regression testing (-regtest mode) only");
     382             : 
     383             :     // cs_vNodes is locked and node send/receive times are updated
     384             :     // atomically with the time change to prevent peers from being
     385             :     // disconnected because we think we haven't communicated with them
     386             :     // in a long time.
     387         800 :     LOCK2(cs_main, cs_vNodes);
     388             : 
     389        3200 :     RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
     390         800 :     SetMockTime(params[0].get_int64());
     391             : 
     392         800 :     uint64_t t = GetTime();
     393       10800 :     BOOST_FOREACH(CNode* pnode, vNodes) {
     394        1200 :         pnode->nLastSend = pnode->nLastRecv = t;
     395             :     }
     396             : 
     397        1600 :     return NullUniValue;
     398         288 : }

Generated by: LCOV version 1.11