~ubuntu-branches/debian/stretch/bitcoin/stretch

« back to all changes in this revision

Viewing changes to src/rpcmisc.cpp

  • Committer: Package Import Robot
  • Author(s): Anthony Towns
  • Date: 2016-10-21 17:13:13 UTC
  • mfrom: (1.3.2)
  • Revision ID: package-import@ubuntu.com-20161021171313-7eu2ltpbk0xag3q1
Tags: 0.13.0-0.1
* Non-maintainer upload.
* New upstream release.
* Allow compilation with gcc/g++ 6. (Closes: Bug#835963)
* Additional fixes for openssl 1.1 compatibility. (See Bug#828248)
* Check if -latomic is needed (it is on mips*).
* Remove reproducible build patch, since leveldb build system is
  no longer used in 0.13. (See Bug#791834)
* Update description since the blockchain is much more than "several GB"
  now. (Closes: Bug#835809)

Show diffs side-by-side

added added

removed removed

Lines of Context:
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.
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
 
UniValue getinfo(const UniValue& params, bool fHelp)
43
 
{
44
 
    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
 
            "  \"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"
66
 
            "}\n"
67
 
            "\nExamples:\n"
68
 
            + HelpExampleCli("getinfo", "")
69
 
            + HelpExampleRpc("getinfo", "")
70
 
        );
71
 
 
72
 
#ifdef ENABLE_WALLET
73
 
    LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
74
 
#else
75
 
    LOCK(cs_main);
76
 
#endif
77
 
 
78
 
    proxyType proxy;
79
 
    GetProxy(NET_IPV4, proxy);
80
 
 
81
 
    UniValue obj(UniValue::VOBJ);
82
 
    obj.push_back(Pair("version", CLIENT_VERSION));
83
 
    obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
84
 
#ifdef ENABLE_WALLET
85
 
    if (pwalletMain) {
86
 
        obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
87
 
        obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
88
 
    }
89
 
#endif
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()));
96
 
#ifdef ENABLE_WALLET
97
 
    if (pwalletMain) {
98
 
        obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
99
 
        obj.push_back(Pair("keypoolsize",   (int)pwalletMain->GetKeyPoolSize()));
100
 
    }
101
 
    if (pwalletMain && pwalletMain->IsCrypted())
102
 
        obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
103
 
    obj.push_back(Pair("paytxfee",      ValueFromAmount(payTxFee.GetFeePerK())));
104
 
#endif
105
 
    obj.push_back(Pair("relayfee",      ValueFromAmount(::minRelayTxFee.GetFeePerK())));
106
 
    obj.push_back(Pair("errors",        GetWarnings("statusbar")));
107
 
    return obj;
108
 
}
109
 
 
110
 
#ifdef ENABLE_WALLET
111
 
class DescribeAddressVisitor : public boost::static_visitor<UniValue>
112
 
{
113
 
public:
114
 
    UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
115
 
 
116
 
    UniValue operator()(const CKeyID &keyID) const {
117
 
        UniValue obj(UniValue::VOBJ);
118
 
        CPubKey vchPubKey;
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()));
123
 
        }
124
 
        return obj;
125
 
    }
126
 
 
127
 
    UniValue operator()(const CScriptID &scriptID) const {
128
 
        UniValue obj(UniValue::VOBJ);
129
 
        CScript subscript;
130
 
        obj.push_back(Pair("isscript", true));
131
 
        if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) {
132
 
            std::vector<CTxDestination> addresses;
133
 
            txnouttype whichType;
134
 
            int nRequired;
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));
144
 
        }
145
 
        return obj;
146
 
    }
147
 
};
148
 
#endif
149
 
 
150
 
UniValue validateaddress(const UniValue& params, bool fHelp)
151
 
{
152
 
    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
 
            + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
172
 
            + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
173
 
        );
174
 
 
175
 
#ifdef ENABLE_WALLET
176
 
    LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
177
 
#else
178
 
    LOCK(cs_main);
179
 
#endif
180
 
 
181
 
    CBitcoinAddress address(params[0].get_str());
182
 
    bool isValid = address.IsValid();
183
 
 
184
 
    UniValue ret(UniValue::VOBJ);
185
 
    ret.push_back(Pair("isvalid", isValid));
186
 
    if (isValid)
187
 
    {
188
 
        CTxDestination dest = address.Get();
189
 
        string currentAddress = address.ToString();
190
 
        ret.push_back(Pair("address", currentAddress));
191
 
 
192
 
        CScript scriptPubKey = GetScriptForDestination(dest);
193
 
        ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
194
 
 
195
 
#ifdef ENABLE_WALLET
196
 
        isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
197
 
        ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
198
 
        ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false));
199
 
        UniValue detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
200
 
        ret.pushKVs(detail);
201
 
        if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
202
 
            ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
203
 
#endif
204
 
    }
205
 
    return ret;
206
 
}
207
 
 
208
 
/**
209
 
 * Used by addmultisigaddress / createmultisig:
210
 
 */
211
 
CScript _createmultisig_redeemScript(const UniValue& params)
212
 
{
213
 
    int nRequired = params[0].get_int();
214
 
    const UniValue& keys = params[1].get_array();
215
 
 
216
 
    // Gather public keys
217
 
    if (nRequired < 1)
218
 
        throw runtime_error("a multisignature address must require at least one key to redeem");
219
 
    if ((int)keys.size() < nRequired)
220
 
        throw runtime_error(
221
 
            strprintf("not enough keys supplied "
222
 
                      "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
223
 
    if (keys.size() > 16)
224
 
        throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
225
 
    std::vector<CPubKey> pubkeys;
226
 
    pubkeys.resize(keys.size());
227
 
    for (unsigned int i = 0; i < keys.size(); i++)
228
 
    {
229
 
        const std::string& ks = keys[i].get_str();
230
 
#ifdef ENABLE_WALLET
231
 
        // Case 1: Bitcoin address and we have full public key:
232
 
        CBitcoinAddress address(ks);
233
 
        if (pwalletMain && address.IsValid())
234
 
        {
235
 
            CKeyID keyID;
236
 
            if (!address.GetKeyID(keyID))
237
 
                throw runtime_error(
238
 
                    strprintf("%s does not refer to a key",ks));
239
 
            CPubKey vchPubKey;
240
 
            if (!pwalletMain->GetPubKey(keyID, vchPubKey))
241
 
                throw runtime_error(
242
 
                    strprintf("no full public key for address %s",ks));
243
 
            if (!vchPubKey.IsFullyValid())
244
 
                throw runtime_error(" Invalid public key: "+ks);
245
 
            pubkeys[i] = vchPubKey;
246
 
        }
247
 
 
248
 
        // Case 2: hex public key
249
 
        else
250
 
#endif
251
 
        if (IsHex(ks))
252
 
        {
253
 
            CPubKey vchPubKey(ParseHex(ks));
254
 
            if (!vchPubKey.IsFullyValid())
255
 
                throw runtime_error(" Invalid public key: "+ks);
256
 
            pubkeys[i] = vchPubKey;
257
 
        }
258
 
        else
259
 
        {
260
 
            throw runtime_error(" Invalid public key: "+ks);
261
 
        }
262
 
    }
263
 
    CScript result = GetScriptForMultisig(nRequired, pubkeys);
264
 
 
265
 
    if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
266
 
        throw runtime_error(
267
 
                strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
268
 
 
269
 
    return result;
270
 
}
271
 
 
272
 
UniValue createmultisig(const UniValue& params, bool fHelp)
273
 
{
274
 
    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
 
            + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
297
 
            "\nAs a json rpc call\n"
298
 
            + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
299
 
        ;
300
 
        throw runtime_error(msg);
301
 
    }
302
 
 
303
 
    // Construct using pay-to-script-hash:
304
 
    CScript inner = _createmultisig_redeemScript(params);
305
 
    CScriptID innerID(inner);
306
 
    CBitcoinAddress address(innerID);
307
 
 
308
 
    UniValue result(UniValue::VOBJ);
309
 
    result.push_back(Pair("address", address.ToString()));
310
 
    result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
311
 
 
312
 
    return result;
313
 
}
314
 
 
315
 
UniValue verifymessage(const UniValue& params, bool fHelp)
316
 
{
317
 
    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
 
            + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
330
 
            "\nCreate the signature\n"
331
 
            + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
332
 
            "\nVerify the signature\n"
333
 
            + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
334
 
            "\nAs json rpc\n"
335
 
            + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
336
 
        );
337
 
 
338
 
    LOCK(cs_main);
339
 
 
340
 
    string strAddress  = params[0].get_str();
341
 
    string strSign     = params[1].get_str();
342
 
    string strMessage  = params[2].get_str();
343
 
 
344
 
    CBitcoinAddress addr(strAddress);
345
 
    if (!addr.IsValid())
346
 
        throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
347
 
 
348
 
    CKeyID keyID;
349
 
    if (!addr.GetKeyID(keyID))
350
 
        throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
351
 
 
352
 
    bool fInvalid = false;
353
 
    vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
354
 
 
355
 
    if (fInvalid)
356
 
        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
 
    if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
364
 
        return false;
365
 
 
366
 
    return (pubkey.GetID() == keyID);
367
 
}
368
 
 
369
 
UniValue setmocktime(const UniValue& params, bool fHelp)
370
 
{
371
 
    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
 
        );
379
 
 
380
 
    if (!Params().MineBlocksOnDemand())
381
 
        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
 
    LOCK2(cs_main, cs_vNodes);
388
 
 
389
 
    RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
390
 
    SetMockTime(params[0].get_int64());
391
 
 
392
 
    uint64_t t = GetTime();
393
 
    BOOST_FOREACH(CNode* pnode, vNodes) {
394
 
        pnode->nLastSend = pnode->nLastRecv = t;
395
 
    }
396
 
 
397
 
    return NullUniValue;
398
 
}