008eb35f95
The IDE include checker got to the point where it is actually useful and this removes a lot of unneeded includes. Naturally, especially for headers like util.h, this may mean we need to re-add includes in consuming cpp files that bloats the diff a bit.
345 lines
14 KiB
C++
345 lines
14 KiB
C++
/*
|
|
* This file is part of the Flowee project
|
|
* Copyright (C) 2010 Satoshi Nakamoto
|
|
* Copyright (C) 2009-2015 The Bitcoin Core developers
|
|
* Copyright (C) 2016-2021 Tom Zander <tom@flowee.org>
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "encodings_legacy.h"
|
|
#include "clientversion.h"
|
|
#include "main.h"
|
|
#include <hash.h>
|
|
#include "net.h"
|
|
#include "netbase.h"
|
|
#include "rpcserver.h"
|
|
#include "timedata.h"
|
|
#include "utiltime.h"
|
|
#include "utilstrencodings.h"
|
|
#include "chainparams.h"
|
|
#include <primitives/ScriptDefines.h> // for MAX_SCRIPT_ELEMENT_SIZE
|
|
#include <boost/assign/list_of.hpp>
|
|
#include <boost/foreach.hpp>
|
|
|
|
#include <univalue.h>
|
|
|
|
/**
|
|
* @note Do not add or change anything in the information returned by this
|
|
* method. `getinfo` exists for backwards-compatibility only. It combines
|
|
* information from wildly different sources in the program, which is a mess,
|
|
* and is thus planned to be deprecated eventually.
|
|
*
|
|
* Based on the source of the information, new information should be added to:
|
|
* - `getblockchaininfo`,
|
|
* - `getnetworkinfo` or
|
|
* - `getwalletinfo`
|
|
*
|
|
* Or alternatively, create a specific query method for the information.
|
|
**/
|
|
UniValue getinfo(const UniValue& params, bool fHelp)
|
|
{
|
|
if (fHelp || params.size() != 0)
|
|
throw std::runtime_error(
|
|
"getinfo\n"
|
|
"Returns an object containing various state info.\n"
|
|
"\nResult:\n"
|
|
"{\n"
|
|
" \"version\": xxxxx, (numeric) the server version\n"
|
|
" \"protocolversion\": xxxxx, (numeric) the protocol version\n"
|
|
" \"walletversion\": xxxxx, (numeric) the wallet version\n"
|
|
" \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n"
|
|
" \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
|
|
" \"timeoffset\": xxxxx, (numeric) the time offset\n"
|
|
" \"connections\": xxxxx, (numeric) the number of connections\n"
|
|
" \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n"
|
|
" \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
|
|
" \"testnet\": true|false, (boolean) if the server is using testnet or not\n"
|
|
" \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
|
|
" \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
|
|
" \"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"
|
|
" \"paytxfee\": x.xxxx, (numeric) the transaction fee set in BCH/kB\n"
|
|
" \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in BCH/kB\n"
|
|
" \"errors\": \"...\" (string) any error messages\n"
|
|
"}\n"
|
|
"\nExamples:\n"
|
|
+ HelpExampleCli("getinfo", "")
|
|
+ HelpExampleRpc("getinfo", "")
|
|
);
|
|
|
|
LOCK(cs_main);
|
|
|
|
proxyType proxy;
|
|
GetProxy(CNetAddr::NET_IPV4, proxy);
|
|
|
|
UniValue obj(UniValue::VOBJ);
|
|
obj.push_back(Pair("version", CLIENT_VERSION));
|
|
obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
|
|
obj.push_back(Pair("blocks", (int)chainActive.Height()));
|
|
obj.push_back(Pair("timeoffset", GetTimeOffset()));
|
|
obj.push_back(Pair("connections", (int)vNodes.size()));
|
|
obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : std::string())));
|
|
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
|
|
obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
|
|
obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
|
|
obj.push_back(Pair("errors", GetWarnings("statusbar")));
|
|
return obj;
|
|
}
|
|
|
|
UniValue validateaddress(const UniValue& params, bool fHelp)
|
|
{
|
|
if (fHelp || params.size() != 1)
|
|
throw std::runtime_error(
|
|
"validateaddress \"bitcoinaddress\"\n"
|
|
"\nReturn information about the given bitcoin address.\n"
|
|
"\nArguments:\n"
|
|
"1. \"bitcoinaddress\" (string, required) The bitcoin address to validate\n"
|
|
"\nResult:\n"
|
|
"{\n"
|
|
" \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
|
|
" \"address\" : \"bitcoinaddress\", (string) The bitcoin address validated\n"
|
|
" \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
|
|
" \"ismine\" : true|false, (boolean) If the address is yours or not\n"
|
|
" \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n"
|
|
" \"isscript\" : true|false, (boolean) If the key is a script\n"
|
|
" \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
|
|
" \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
|
|
" \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
|
|
"}\n"
|
|
"\nExamples:\n"
|
|
+ HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
|
|
+ HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
|
|
);
|
|
|
|
LOCK(cs_main);
|
|
|
|
CBitcoinAddress address(params[0].get_str());
|
|
bool isValid = address.IsValid();
|
|
|
|
UniValue ret(UniValue::VOBJ);
|
|
ret.push_back(Pair("isvalid", isValid));
|
|
if (isValid)
|
|
{
|
|
CTxDestination dest = address.Get();
|
|
std::string currentAddress = address.ToString();
|
|
ret.push_back(Pair("address", currentAddress));
|
|
|
|
CScript scriptPubKey = GetScriptForDestination(dest);
|
|
ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Used by addmultisigaddress / createmultisig:
|
|
*/
|
|
CScript _createmultisig_redeemScript(const UniValue& params)
|
|
{
|
|
int nRequired = params[0].get_int();
|
|
const UniValue& keys = params[1].get_array();
|
|
|
|
// Gather public keys
|
|
if (nRequired < 1)
|
|
throw std::runtime_error("a multisignature address must require at least one key to redeem");
|
|
if ((int)keys.size() < nRequired)
|
|
throw std::runtime_error(
|
|
strprintf("not enough keys supplied "
|
|
"(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
|
|
if (keys.size() > 16)
|
|
throw std::runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
|
|
std::vector<PublicKey> pubkeys;
|
|
pubkeys.resize(keys.size());
|
|
for (unsigned int i = 0; i < keys.size(); i++)
|
|
{
|
|
const std::string& ks = keys[i].get_str();
|
|
if (IsHex(ks))
|
|
{
|
|
PublicKey vchPubKey(ParseHex(ks));
|
|
if (!vchPubKey.isFullyValid())
|
|
throw std::runtime_error(" Invalid public key: "+ks);
|
|
pubkeys[i] = vchPubKey;
|
|
}
|
|
else
|
|
{
|
|
throw std::runtime_error(" Invalid public key: "+ks);
|
|
}
|
|
}
|
|
CScript result = GetScriptForMultisig(nRequired, pubkeys);
|
|
|
|
if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
|
|
throw std::runtime_error(
|
|
strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
|
|
|
|
return result;
|
|
}
|
|
|
|
UniValue createmultisig(const UniValue& params, bool fHelp)
|
|
{
|
|
if (fHelp || params.size() < 2 || params.size() > 2)
|
|
{
|
|
std::string msg = "createmultisig nrequired [\"key\",...]\n"
|
|
"\nCreates a multi-signature address with n signature of m keys required.\n"
|
|
"It returns a json object with the address and redeemScript.\n"
|
|
|
|
"\nArguments:\n"
|
|
"1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
|
|
"2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
|
|
" [\n"
|
|
" \"key\" (string) bitcoin address or hex-encoded public key\n"
|
|
" ,...\n"
|
|
" ]\n"
|
|
|
|
"\nResult:\n"
|
|
"{\n"
|
|
" \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
|
|
" \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
|
|
"}\n"
|
|
|
|
"\nExamples:\n"
|
|
"\nCreate a multisig address from 2 addresses\n"
|
|
+ HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
|
|
"\nAs a json rpc call\n"
|
|
+ HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
|
|
;
|
|
throw std::runtime_error(msg);
|
|
}
|
|
|
|
// Construct using pay-to-script-hash:
|
|
CScript inner = _createmultisig_redeemScript(params);
|
|
CScriptID innerID(inner);
|
|
CBitcoinAddress address(innerID);
|
|
|
|
UniValue result(UniValue::VOBJ);
|
|
result.push_back(Pair("address", address.ToString()));
|
|
result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
|
|
|
|
return result;
|
|
}
|
|
|
|
UniValue verifymessage(const UniValue& params, bool fHelp)
|
|
{
|
|
if (fHelp || params.size() != 3)
|
|
throw std::runtime_error(
|
|
"verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
|
|
"\nVerify a signed message\n"
|
|
"\nArguments:\n"
|
|
"1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the signature.\n"
|
|
"2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
|
|
"3. \"message\" (string, required) The message that was signed.\n"
|
|
"\nResult:\n"
|
|
"true|false (boolean) If the signature is verified or not.\n"
|
|
"\nExamples:\n"
|
|
"\nUnlock the wallet for 30 seconds\n"
|
|
+ HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
|
|
"\nCreate the signature\n"
|
|
+ HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
|
|
"\nVerify the signature\n"
|
|
+ HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
|
|
"\nAs json rpc\n"
|
|
+ HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
|
|
);
|
|
|
|
LOCK(cs_main);
|
|
|
|
std::string strAddress = params[0].get_str();
|
|
std::string strSign = params[1].get_str();
|
|
std::string strMessage = params[2].get_str();
|
|
|
|
CBitcoinAddress addr(strAddress);
|
|
if (!addr.IsValid())
|
|
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
|
|
|
|
KeyId keyID;
|
|
if (!addr.GetKeyID(keyID))
|
|
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
|
|
|
|
bool fInvalid = false;
|
|
std::vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
|
|
|
|
if (fInvalid)
|
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
|
|
|
|
CHashWriter ss(SER_GETHASH, 0);
|
|
ss << strMessageMagic;
|
|
ss << strMessage;
|
|
|
|
PublicKey pubkey;
|
|
if (!pubkey.recoverCompact(ss.finalizeHash(), vchSig))
|
|
return false;
|
|
|
|
return (pubkey.getKeyId() == keyID);
|
|
}
|
|
|
|
UniValue setmocktime(const UniValue& params, bool fHelp)
|
|
{
|
|
if (fHelp || params.size() != 1)
|
|
throw std::runtime_error(
|
|
"setmocktime timestamp\n"
|
|
"\nSet the local time to given timestamp (-regtest only)\n"
|
|
"\nArguments:\n"
|
|
"1. timestamp (integer, required) Unix seconds-since-epoch timestamp\n"
|
|
" Pass 0 to go back to using the system time."
|
|
);
|
|
|
|
if (!Params().MineBlocksOnDemand())
|
|
throw std::runtime_error("setmocktime for regression testing (-regtest mode) only");
|
|
|
|
// cs_vNodes is locked and node send/receive times are updated
|
|
// atomically with the time change to prevent peers from being
|
|
// disconnected because we think we haven't communicated with them
|
|
// in a long time.
|
|
LOCK2(cs_main, cs_vNodes);
|
|
|
|
RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
|
|
SetMockTime(params[0].get_int64());
|
|
|
|
uint64_t t = GetTime();
|
|
BOOST_FOREACH(CNode* pnode, vNodes) {
|
|
pnode->nLastSend = pnode->nLastRecv = t;
|
|
}
|
|
|
|
return NullUniValue;
|
|
}
|
|
|
|
UniValue createaddress(const UniValue& params, bool fHelp)
|
|
{
|
|
if (fHelp || params.size() != 0)
|
|
throw std::runtime_error(
|
|
"createaddress\n"
|
|
"\nCreates a new address and returns the public and private keys, after which the server immediately forgets the address and keys\n"
|
|
"\nResult:\n"
|
|
"{\n"
|
|
" \"address\" : \"bitcoinaddress\", (string) The bitcoin address\n"
|
|
" \"scriptPubKey\" : \"hex\", (string) The byte-sequence to use pay to address\n"
|
|
" \"pubkey\" : \"hex\", (string) The raw (hex encoded) pubkey\n"
|
|
" \"private\" : \"hex\", (string) The base58 encoded private key\n"
|
|
"}\n"
|
|
);
|
|
|
|
PrivateKey key;
|
|
key.makeNewKey();
|
|
|
|
// return all useful descriptions of key
|
|
UniValue ret(UniValue::VOBJ);
|
|
const PublicKey pubkey = key.getPubKey();
|
|
const KeyId pubKeyId = pubkey.getKeyId();
|
|
ret.push_back(Pair("address", CBitcoinAddress(pubKeyId).ToString()));
|
|
const CScript scriptPubKey = GetScriptForDestination(pubKeyId);
|
|
ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey)));
|
|
ret.push_back(Pair("pubkey", HexStr(pubkey.begin(), pubkey.end())));
|
|
ret.push_back(Pair("private", CBitcoinSecret(key).ToString()));
|
|
|
|
return ret;
|
|
}
|