mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-24 22:04:30 +00:00
a8db31c83d
Currently it is only possible to use `walletpassphrase` to unlock the wallet when bitcoin is started in server mode. Almost everything that manipulates the wallet in the RPC console needs the wallet to be unlocked and is thus unusable without -server. This is pretty unintuitive to me, and I'm sure it's even more confusing to users. Solve this with a very minimal change: by making the GUI start a dummy RPC thread just to handle timeouts.
138 lines
6.1 KiB
C++
138 lines
6.1 KiB
C++
// Copyright (c) 2010 Satoshi Nakamoto
|
|
// Copyright (c) 2009-2013 The Bitcoin developers
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#ifndef _BITCOINRPC_PROTOCOL_H_
|
|
#define _BITCOINRPC_PROTOCOL_H_ 1
|
|
|
|
#include <list>
|
|
#include <map>
|
|
#include <stdint.h>
|
|
#include <string>
|
|
#include <boost/iostreams/concepts.hpp>
|
|
#include <boost/iostreams/stream.hpp>
|
|
#include <boost/asio.hpp>
|
|
#include <boost/asio/ssl.hpp>
|
|
|
|
#include "json/json_spirit_reader_template.h"
|
|
#include "json/json_spirit_utils.h"
|
|
#include "json/json_spirit_writer_template.h"
|
|
|
|
// HTTP status codes
|
|
enum HTTPStatusCode
|
|
{
|
|
HTTP_OK = 200,
|
|
HTTP_BAD_REQUEST = 400,
|
|
HTTP_UNAUTHORIZED = 401,
|
|
HTTP_FORBIDDEN = 403,
|
|
HTTP_NOT_FOUND = 404,
|
|
HTTP_INTERNAL_SERVER_ERROR = 500,
|
|
};
|
|
|
|
// Bitcoin RPC error codes
|
|
enum RPCErrorCode
|
|
{
|
|
// Standard JSON-RPC 2.0 errors
|
|
RPC_INVALID_REQUEST = -32600,
|
|
RPC_METHOD_NOT_FOUND = -32601,
|
|
RPC_INVALID_PARAMS = -32602,
|
|
RPC_INTERNAL_ERROR = -32603,
|
|
RPC_PARSE_ERROR = -32700,
|
|
|
|
// General application defined errors
|
|
RPC_MISC_ERROR = -1, // std::exception thrown in command handling
|
|
RPC_FORBIDDEN_BY_SAFE_MODE = -2, // Server is in safe mode, and command is not allowed in safe mode
|
|
RPC_TYPE_ERROR = -3, // Unexpected type was passed as parameter
|
|
RPC_INVALID_ADDRESS_OR_KEY = -5, // Invalid address or key
|
|
RPC_OUT_OF_MEMORY = -7, // Ran out of memory during operation
|
|
RPC_INVALID_PARAMETER = -8, // Invalid, missing or duplicate parameter
|
|
RPC_DATABASE_ERROR = -20, // Database error
|
|
RPC_DESERIALIZATION_ERROR = -22, // Error parsing or validating structure in raw format
|
|
|
|
// P2P client errors
|
|
RPC_CLIENT_NOT_CONNECTED = -9, // Bitcoin is not connected
|
|
RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, // Still downloading initial blocks
|
|
RPC_CLIENT_NODE_ALREADY_ADDED = -23, // Node is already added
|
|
RPC_CLIENT_NODE_NOT_ADDED = -24, // Node has not been added before
|
|
|
|
// Wallet errors
|
|
RPC_WALLET_ERROR = -4, // Unspecified problem with wallet (key not found etc.)
|
|
RPC_WALLET_INSUFFICIENT_FUNDS = -6, // Not enough funds in wallet or account
|
|
RPC_WALLET_INVALID_ACCOUNT_NAME = -11, // Invalid account name
|
|
RPC_WALLET_KEYPOOL_RAN_OUT = -12, // Keypool ran out, call keypoolrefill first
|
|
RPC_WALLET_UNLOCK_NEEDED = -13, // Enter the wallet passphrase with walletpassphrase first
|
|
RPC_WALLET_PASSPHRASE_INCORRECT = -14, // The wallet passphrase entered was incorrect
|
|
RPC_WALLET_WRONG_ENC_STATE = -15, // Command given in wrong wallet encryption state (encrypting an encrypted wallet etc.)
|
|
RPC_WALLET_ENCRYPTION_FAILED = -16, // Failed to encrypt the wallet
|
|
RPC_WALLET_ALREADY_UNLOCKED = -17, // Wallet is already unlocked
|
|
};
|
|
|
|
//
|
|
// IOStream device that speaks SSL but can also speak non-SSL
|
|
//
|
|
template <typename Protocol>
|
|
class SSLIOStreamDevice : public boost::iostreams::device<boost::iostreams::bidirectional> {
|
|
public:
|
|
SSLIOStreamDevice(boost::asio::ssl::stream<typename Protocol::socket> &streamIn, bool fUseSSLIn) : stream(streamIn)
|
|
{
|
|
fUseSSL = fUseSSLIn;
|
|
fNeedHandshake = fUseSSLIn;
|
|
}
|
|
|
|
void handshake(boost::asio::ssl::stream_base::handshake_type role)
|
|
{
|
|
if (!fNeedHandshake) return;
|
|
fNeedHandshake = false;
|
|
stream.handshake(role);
|
|
}
|
|
std::streamsize read(char* s, std::streamsize n)
|
|
{
|
|
handshake(boost::asio::ssl::stream_base::server); // HTTPS servers read first
|
|
if (fUseSSL) return stream.read_some(boost::asio::buffer(s, n));
|
|
return stream.next_layer().read_some(boost::asio::buffer(s, n));
|
|
}
|
|
std::streamsize write(const char* s, std::streamsize n)
|
|
{
|
|
handshake(boost::asio::ssl::stream_base::client); // HTTPS clients write first
|
|
if (fUseSSL) return boost::asio::write(stream, boost::asio::buffer(s, n));
|
|
return boost::asio::write(stream.next_layer(), boost::asio::buffer(s, n));
|
|
}
|
|
bool connect(const std::string& server, const std::string& port)
|
|
{
|
|
boost::asio::ip::tcp::resolver resolver(stream.get_io_service());
|
|
boost::asio::ip::tcp::resolver::query query(server.c_str(), port.c_str());
|
|
boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
|
|
boost::asio::ip::tcp::resolver::iterator end;
|
|
boost::system::error_code error = boost::asio::error::host_not_found;
|
|
while (error && endpoint_iterator != end)
|
|
{
|
|
stream.lowest_layer().close();
|
|
stream.lowest_layer().connect(*endpoint_iterator++, error);
|
|
}
|
|
if (error)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
bool fNeedHandshake;
|
|
bool fUseSSL;
|
|
boost::asio::ssl::stream<typename Protocol::socket>& stream;
|
|
};
|
|
|
|
std::string HTTPPost(const std::string& strMsg, const std::map<std::string,std::string>& mapRequestHeaders);
|
|
std::string HTTPReply(int nStatus, const std::string& strMsg, bool keepalive);
|
|
bool ReadHTTPRequestLine(std::basic_istream<char>& stream, int &proto,
|
|
std::string& http_method, std::string& http_uri);
|
|
int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto);
|
|
int ReadHTTPHeaders(std::basic_istream<char>& stream, std::map<std::string, std::string>& mapHeadersRet);
|
|
int ReadHTTPMessage(std::basic_istream<char>& stream, std::map<std::string, std::string>& mapHeadersRet,
|
|
std::string& strMessageRet, int nProto);
|
|
std::string JSONRPCRequest(const std::string& strMethod, const json_spirit::Array& params, const json_spirit::Value& id);
|
|
json_spirit::Object JSONRPCReplyObj(const json_spirit::Value& result, const json_spirit::Value& error, const json_spirit::Value& id);
|
|
std::string JSONRPCReply(const json_spirit::Value& result, const json_spirit::Value& error, const json_spirit::Value& id);
|
|
json_spirit::Object JSONRPCError(int code, const std::string& message);
|
|
|
|
#endif
|