Пример #1
0
def run_electrum_server(rpc, txmonitor, config):
    logger = logging.getLogger('ELECTRUMPERSONALSERVER')
    logger.debug("Starting electrum server")

    hostport = (config.get("electrum-server",
                           "host"), int(config.get("electrum-server", "port")))
    ip_whitelist = []
    for ip in config.get("electrum-server", "ip_whitelist").split(" "):
        if ip == "*":
            #matches everything
            ip_whitelist.append(ip_network("0.0.0.0/0"))
            ip_whitelist.append(ip_network("::0/0"))
        else:
            ip_whitelist.append(ip_network(ip, strict=False))
    poll_interval_listening = int(
        config.get("bitcoin-rpc", "poll_interval_listening"))
    poll_interval_connected = int(
        config.get("bitcoin-rpc", "poll_interval_connected"))
    certfile, keyfile = get_certs(config)
    logger.debug('using cert: {}, key: {}'.format(certfile, keyfile))
    disable_mempool_fee_histogram = config.getboolean(
        "electrum-server", "disable_mempool_fee_histogram", fallback=False)
    broadcast_method = config.get("electrum-server",
                                  "broadcast_method",
                                  fallback="own-node")
    tor_host = config.get("electrum-server", "tor_host", fallback="localhost")
    tor_port = int(config.get("electrum-server", "tor_port", fallback="9050"))
    tor_hostport = (tor_host, tor_port)

    protocol = ElectrumProtocol(rpc, txmonitor, logger, broadcast_method,
                                tor_hostport, disable_mempool_fee_histogram)

    server_sock = create_server_socket(hostport)
    server_sock.settimeout(poll_interval_listening)
    accepting_clients = True
    while True:
        # main server loop, runs forever
        sock = None
        while sock == None:
            # loop waiting for a successful connection from client
            try:
                sock, addr = server_sock.accept()
                if not accepting_clients:
                    logger.debug("Refusing connection from client because" +
                                 " Bitcoin node isnt reachable")
                    raise ConnectionRefusedError()
                if not any(
                    [ip_address(addr[0]) in ipnet for ipnet in ip_whitelist]):
                    logger.debug(addr[0] + " not in whitelist, closing")
                    raise ConnectionRefusedError()
                sock = ssl.wrap_socket(sock,
                                       server_side=True,
                                       certfile=certfile,
                                       keyfile=keyfile,
                                       ssl_version=ssl.PROTOCOL_SSLv23)
            except socket.timeout:
                is_node_reachable = on_heartbeat_listening(txmonitor)
                accepting_clients = is_node_reachable
            except (ConnectionRefusedError, ssl.SSLError, IOError):
                sock.close()
                sock = None
        logger.debug('Electrum connected from ' + str(addr[0]))

        def send_reply_fun(reply):
            line = json.dumps(reply)
            sock.sendall(line.encode('utf-8') + b'\n')
            logger.debug('<= ' + line)

        protocol.set_send_reply_fun(send_reply_fun)

        try:
            sock.settimeout(poll_interval_connected)
            recv_buffer = bytearray()
            while True:
                # loop for replying to client queries
                try:
                    recv_data = sock.recv(4096)
                    if not recv_data or len(recv_data) == 0:
                        raise EOFError()
                    recv_buffer.extend(recv_data)
                    lb = recv_buffer.find(b'\n')
                    if lb == -1:
                        continue
                    while lb != -1:
                        line = recv_buffer[:lb].rstrip()
                        recv_buffer = recv_buffer[lb + 1:]
                        lb = recv_buffer.find(b'\n')
                        try:
                            line = line.decode("utf-8")
                            query = json.loads(line)
                        except (UnicodeDecodeError, JSONDecodeError) as e:
                            raise IOError(repr(e))
                        logger.debug("=> " + line)
                        protocol.handle_query(query)
                except socket.timeout:
                    on_heartbeat_connected(rpc, txmonitor, protocol)
        except JsonRpcError as e:
            logger.debug("Error with node connection, e = " + repr(e) +
                         "\ntraceback = " + str(traceback.format_exc()))
            accepting_clients = False
        except UnknownScripthashError as e:
            logger.debug("Disconnecting client due to misconfiguration. User" +
                         " must correctly configure master public key(s)")
        except (IOError, EOFError) as e:
            if isinstance(e, (EOFError, ConnectionRefusedError)):
                logger.debug("Electrum wallet disconnected")
            else:
                logger.debug("IOError: " + repr(e))
        try:
            if sock != None:
                sock.close()
        except IOError:
            pass
        protocol.on_disconnect()
        time.sleep(0.2)
Пример #2
0
def run_electrum_server(rpc, txmonitor, config):
    logger = logging.getLogger('ELECTRUMPERSONALSERVER')
    logger.info("Starting electrum server")

    hostport = (config.get("electrum-server", "host"),
            int(config.get("electrum-server", "port")))
    ip_whitelist = []
    for ip in config.get("electrum-server", "ip_whitelist").split(" "):
        if ip == "*":
            #matches everything
            ip_whitelist.append(ip_network("0.0.0.0/0"))
            ip_whitelist.append(ip_network("::0/0"))
        else:
            ip_whitelist.append(ip_network(ip, strict=False))
    poll_interval_listening = int(config.get("bitcoin-rpc",
        "poll_interval_listening"))
    poll_interval_connected = int(config.get("bitcoin-rpc",
        "poll_interval_connected"))
    certfile, keyfile = get_certs(config)
    disable_mempool_fee_histogram = config.getboolean("electrum-server",
        "disable_mempool_fee_histogram", fallback=False)
    broadcast_method = config.get("electrum-server", "broadcast_method",
        fallback="own-node")
    tor_host = config.get("electrum-server", "tor_host", fallback="localhost")
    tor_port = int(config.get("electrum-server", "tor_port", fallback="9050"))
    tor_hostport = (tor_host, tor_port)

    protocol = ElectrumProtocol(rpc, txmonitor, logger, broadcast_method,
        tor_hostport, disable_mempool_fee_histogram)

    server_sock = create_server_socket(hostport)
    server_sock.settimeout(poll_interval_listening)
    while True:
        try:
            sock = None
            while sock == None:
                try:
                    sock, addr = server_sock.accept()
                    if not any([ip_address(addr[0]) in ipnet
                            for ipnet in ip_whitelist]):
                        logger.debug(addr[0] + " not in whitelist, closing")
                        raise ConnectionRefusedError()
                    sock = ssl.wrap_socket(sock, server_side=True,
                        certfile=certfile, keyfile=keyfile,
                        ssl_version=ssl.PROTOCOL_SSLv23)
                except socket.timeout:
                    on_heartbeat_listening(txmonitor)
                except (ConnectionRefusedError, ssl.SSLError):
                    sock.close()
                    sock = None

            logger.info('Electrum connected from ' + str(addr[0]))
            protocol.set_send_line_fun(lambda l: sock.sendall(l + b'\n'))
            sock.settimeout(poll_interval_connected)
            recv_buffer = bytearray()
            while True:
                try:
                    recv_data = sock.recv(4096)
                    if not recv_data or len(recv_data) == 0:
                        raise EOFError()
                    recv_buffer.extend(recv_data)
                    lb = recv_buffer.find(b'\n')
                    if lb == -1:
                        continue
                    while lb != -1:
                        line = recv_buffer[:lb].rstrip()
                        recv_buffer = recv_buffer[lb + 1:]
                        lb = recv_buffer.find(b'\n')
                        protocol.handle_query(line.decode("utf-8"))
                except socket.timeout:
                    on_heartbeat_connected(rpc, txmonitor, protocol)
        except (IOError, EOFError) as e:
            if isinstance(e, (EOFError, ConnectionRefusedError)):
                logger.info("Electrum wallet disconnected")
            else:
                logger.error("IOError: " + repr(e))
            try:
                if sock != None:
                    sock.close()
            except IOError:
                pass
            sock = None
            protocol.on_disconnect()
            time.sleep(0.2)