Пример #1
0
def worker(*, uid: int, endpoint: str):
    ctx = zmq.Context()
    dispatcher = RPCDispatcher()

    client = RPCClient(
        JSONRPCProtocol(),
        ZmqClientTransport.create(ctx, endpoint),
    )
    proxy = client.get_proxy()

    @dispatcher.public
    def do_task():
        from time import sleep

        for i in range(5):
            proxy.notify(f"{uid} y{i} ")
            sleep(0.1)

        return f"OK {uid}"

    @dispatcher.public
    def exit():
        proxy.exit(uid)

    transport = ZmqServerTransport.create(
        ctx, endpoint.replace(".manager", f".{uid}"))
    rpc_server = RPCServer(transport, JSONRPCProtocol(), dispatcher)
    rpc_server.trace = partial(print, file=sys.stderr)
    rpc_server.serve_forever()
Пример #2
0
    def __init__(self,
                 host,
                 port,
                 privkey,
                 nonce_update_interval=5.0,
                 nonce_offset=0):
        endpoint = 'http://{}:{}'.format(host, port)
        session = requests.Session()
        adapter = requests.adapters.HTTPAdapter(pool_maxsize=50)
        session.mount(endpoint, adapter)

        self.transport = HttpPostClientTransport(
            endpoint,
            post_method=session.post,
            headers={'content-type': 'application/json'},
        )

        self.port = port
        self.privkey = privkey
        self.protocol = JSONRPCProtocol()
        self.sender = privatekey_to_address(privkey)
        # Needs to be initialized to None in the beginning since JSONRPCClient
        # gets constructed before the RaidenService Object.
        self.stop_event = None

        self.nonce_last_update = 0
        self.nonce_current_value = None
        self.nonce_lock = Semaphore()
        self.nonce_update_interval = nonce_update_interval
        self.nonce_offset = nonce_offset
Пример #3
0
    def __init__(self,
                 host,
                 port,
                 privkey,
                 nonce_update_interval=5.0,
                 nonce_offset=0):
        endpoint = 'http://{}:{}'.format(host, port)
        session = requests.Session()
        adapter = requests.adapters.HTTPAdapter(pool_maxsize=50)
        session.mount(endpoint, adapter)

        self.transport = HttpPostClientTransport(
            endpoint,
            post_method=session.post,
            headers={'content-type': 'application/json'},
        )

        self.port = port
        self.privkey = privkey
        self.protocol = JSONRPCProtocol()
        self.sender = privatekey_to_address(privkey)

        self.nonce_last_update = 0
        self.nonce_current_value = None
        self.nonce_lock = Semaphore()
        self.nonce_update_interval = nonce_update_interval
        self.nonce_offset = nonce_offset
Пример #4
0
def client(*, endpoint: str, callback_endpoint: str):
    ctx = zmq.Context()

    dispatcher = RPCDispatcher()

    @dispatcher.public
    def notify(s: str):
        print("** {s} **")

    callback_server = RPCServer(
        ZmqServerTransport.create(ctx, callback_endpoint), JSONRPCProtocol(),
        dispatcher)
    callback_server.trace = print
    threading.Thread(target=callback_server.serve_forever, daemon=True).start()

    rpc_client = RPCClient(JSONRPCProtocol(),
                           ZmqClientTransport.create(ctx, endpoint))
    remote_server = rpc_client.get_proxy()

    for i in range(7):
        result = remote_server.act(i, "Hello, World!")
        print("Server answered:", result)

    result = remote_server.shutdown()
    print("Send shutdown:", result)
Пример #5
0
    def __init__(self, function_lists, is_id_valid):
        self._rpc_dispatcher = RPCDispatcher()
        self._rpc_protocol = JSONRPCProtocol()
        self._is_id_valid = is_id_valid

        for f in function_lists:
            self._rpc_dispatcher.add_method(f)

        logger.info("RPC service initialized")
Пример #6
0
 def __init__(
     self,
     transport: Callable[[bytes, Optional[float]], Awaitable[bytes]],
     app: BaseApplication,
     exception_mapping_callback: Optional[Callable[
         [Optional[int], Optional[str], Optional[Any]], None]] = None,
 ):
     self._app = app
     self._proto = JSONRPCProtocol()
     self._transport = transport
     self._exception_mapping_callback = exception_mapping_callback
Пример #7
0
    def __init__(self,
                 host: str,
                 port: int,
                 privkey: bytes,
                 gasprice: int = None,
                 nonce_update_interval: float = 5.0,
                 nonce_offset: int = 0):

        if privkey is None or len(privkey) != 32:
            raise ValueError('Invalid private key')

        endpoint = 'http://{}:{}'.format(host, port)
        self.session = requests.Session()
        adapter = requests.adapters.HTTPAdapter(pool_maxsize=50)
        self.session.mount(endpoint, adapter)

        self.transport = HttpPostClientTransport(
            endpoint,
            post_method=self.session.post,
            headers={'content-type': 'application/json'},
        )

        self.port = port
        self.privkey = privkey
        self.protocol = JSONRPCProtocol()
        self.sender = privatekey_to_address(privkey)
        # Needs to be initialized to None in the beginning since JSONRPCClient
        # gets constructed before the RaidenService Object.
        self.stop_event = None

        self.nonce_last_update = 0
        self.nonce_available_value = None
        self.nonce_lock = Semaphore()
        self.nonce_update_interval = nonce_update_interval
        self.nonce_offset = nonce_offset
        self.given_gas_price = gasprice

        cache = cachetools.TTLCache(
            maxsize=1,
            ttl=RPC_CACHE_TTL,
        )
        cache_wrapper = cachetools.cached(cache=cache)
        self.gaslimit = cache_wrapper(self._gaslimit)
        cache = cachetools.TTLCache(
            maxsize=1,
            ttl=RPC_CACHE_TTL,
        )
        cache_wrapper = cachetools.cached(cache=cache)
        self.gasprice = cache_wrapper(self._gasprice)
Пример #8
0
    def __init__(self, ip_hostname='pulsestreamer'):
        print("Connect to Pulse Streamer via JSON-RPC.")
        print("IP / Hostname:", ip_hostname)
        url = 'http://' + ip_hostname + ':8050/json-rpc'
        try:
            self.INFINITE = -1
            self.CONSTANT_ZERO = (0, 0, 0, 0)

            if sys.version_info.major > 2:
                client = RPCClient(url)
            else:
                client = RPCClient(JSONRPCProtocol(),
                                   HttpPostClientTransport(url))

            self.proxy = client.get_proxy()
            try:
                self.proxy.getSerial()
            except:
                try:
                    self.proxy.isRunning()
                    print(
                        "Pulse Streamer class not compatible with current firmware. Please update your firmware."
                    )
                    sys.exit(1)
                except:
                    print("No Pulse Streamer found at IP/Host-address: " +
                          ip_hostname)
                    sys.exit(1)
        except:
            print("No Pulse Streamer found at IP/Host-address: " + ip_hostname)
            sys.exit(1)
Пример #9
0
def nsZRPCBringupServer(ns, path, conn, maxconn):
    name = os.path.basename(path)
    dev_path = '/dev/zrpc/{}'.format(name)
    if nsRPCisServer(ns, path) is not True:
        nsError(ns, "ZRPC service {} misconfigured".format(name))
        return False
    nsInfo(ns, "Configuring ZRPC server from {}".format(path))
    nsMkdir(ns, dev_path)
    nsMkdir(ns, "{}/root".format(dev_path))
    _to_root = nsGet(ns, "{}/jail".format(path), [])
    for j in _to_root:
        _n = os.path.basename(j)
        _dst = "{}/root/{}".format(dev_path, _n)
        nsInfo(ns, "ZRPC.JAIL({}): {}".format(name, j))
        nsLn(ns, j, _dst)

    dispatcher = RPCDispatcher()
    nsSet(ns, "{}/dispatcher".format(dev_path), dispatcher)
    for h in nsLs(ns, "{}/handlers".format(path)):
        nsInfo(ns, "Registering {}->{} ".format(name, h))
        _fun = nsGet(ns, "{}/handlers/{}".format(path, h))
        dispatcher.add_method(partial(_fun, dev_path), h)

    transport = ZmqServerTransport.create(ctx, conn)
    nsSet(ns, "{}/transport".format(dev_path), transport)
    nsSet(ns, "{}/conn".format(dev_path), conn)
    rpc_server = RPCServerGreenlets(transport, JSONRPCProtocol(), dispatcher)
    nsSet(ns, "{}/rpc", rpc_server)
    nsDaemon(ns, "{}:ZRPC".format(name), rpc_server.serve_forever, _raw=True)
    nsInfo(ns, "ZRPC server {} is up".format(name))
    return True
Пример #10
0
    def authenticate(self):
        """
        Performs authentication actions
        Patches `tinyrpc` to remove minor incompatibilities due to JSON-RPC
        protocol version differences. This is performed once.
        Initializes the RPCClient and RPCProxy instances that
        are used to make the requests to Lime.
        :return: None
        """
        logger.info("Authenticating LimeAPI client")
        if not LimeAPI._rpc_protocol_patched:
            LimeAPI.patch_json_rpc_protocol()
            LimeAPI._rpc_protocol_patched = True
        self.rpc_client = RPCClient(
            JSONRPCProtocol(),
            HttpPostClientTransport(endpoint=self.remote_api_url,
                                    headers=self.headers),
        )

        self.rpc_proxy = self.rpc_client.get_proxy()
        self.session_key = self.rpc_proxy.get_session_key(
            username=self.username, password=self.password)
        if not self._validate_session_key():
            raise Exception(f"Failed to validate session key: url={self.url} "
                            f"session_key={self.session_key}")
        self._authenticated = True
        logger.info(f"Acquired session key: {self.session_key}")
Пример #11
0
def test_argument_error(dispatch, invoke_with):
    method, args, kwargs, result = invoke_with

    protocol = JSONRPCProtocol()

    @dispatch.public
    def fn_a(a, b):
        return a - b

    @dispatch.public
    def fn_b(*a):
        return a[0] - a[1]

    @dispatch.public
    def fn_c(**a):
        return a['a'] - a['b']

    mock_request = Mock(RPCRequest)
    mock_request.args = args
    mock_request.kwargs = kwargs
    mock_request.method = method
    dispatch._dispatch(mock_request)
    if inspect.isclass(result) and issubclass(result, Exception):
        assert type(mock_request.error_respond.call_args[0][0]) == result
    else:
        mock_request.respond.assert_called_with(result)
Пример #12
0
    def __init__(
            self,
            host: str,
            port: int,
            privkey: bytes,
            nonce_update_interval: float = 5.0,
            nonce_offset: int = 0):

        endpoint = 'http://{}:{}'.format(host, port)
        session = requests.Session()
        adapter = requests.adapters.HTTPAdapter(pool_maxsize=50)
        session.mount(endpoint, adapter)

        self.transport = HttpPostClientTransport(
            endpoint,
            post_method=session.post,
            headers={'content-type': 'application/json'},
        )

        self.port = port
        self.privkey = privkey
        self.protocol = JSONRPCProtocol()
        self.sender = privatekey_to_address(privkey)
        # Needs to be initialized to None in the beginning since JSONRPCClient
        # gets constructed before the RaidenService Object.
        self.stop_event = None

        self.nonce_last_update = 0
        self.nonce_current_value = None
        self.nonce_lock = Semaphore()
        self.nonce_update_interval = nonce_update_interval
        self.nonce_offset = nonce_offset
Пример #13
0
 def __init__(self, ws):
     self.ws = ws
     self.queue = hub.Queue()
     super(WebSocketRPCClient, self).__init__(
         JSONRPCProtocol(),
         WebSocketClientTransport(ws, self.queue),
     )
Пример #14
0
class RPCSocketHandler(WebSocketHandler):
    '''
    This is **not** a singleton. There is an instance for every client.
    '''

    protocol = JSONRPCProtocol()  # one instance is enough.

    # this needs to be implemented by a subclass. Dict: method_string -->
    # Procedure(method_callback)
    procedures = None

    def on_message(self, message):
        json_request = self.protocol.parse_request(message)
        # procedures (dict: sting --> method) must be implemented in a
        # subclass!
        callback = self.procedures.get(json_request.method)
        if callback is None:
            response = json_request.error_respond('Method %r not implemented' %
                                                  json_request.method)
            self.write_message(response.serialize())
            return
        try:
            result = callback(json_request)
        except Exception as exc:
            logger.error(exc, exc_info=True)
            response = json_request.error_respond(repr(exc))
            self.write_message(response.serialize())
            return

        return self.return_result(result, json_request)

    def return_result(self, result, json_request):
        response = json_request.respond(result)
        self.write_message(response.serialize())
Пример #15
0
def test_async_argument_error(async_dispatch, invoke_with, event_loop):
    method, args, kwargs, result = invoke_with

    protocol = JSONRPCProtocol()

    @async_dispatch.public
    async def fn_a(a, b):
        return a - b

    @async_dispatch.public
    async def fn_b(*a):
        return a[0] - a[1]

    @async_dispatch.public
    async def fn_c(**a):
        return a['a'] - a['b']

    mock_request = Mock(RPCRequest)
    mock_request.args = args
    mock_request.kwargs = kwargs
    mock_request.method = method
    event_loop.run_until_complete(async_dispatch._dispatch(mock_request))
    if inspect.isclass(result) and issubclass(result, Exception):
        assert type(mock_request.error_respond.call_args[0][0]) is result
    else:
        mock_request.respond.assert_called_with(result)
Пример #16
0
def test_static_method_argument_error(dispatch, invoke_with):
    method, args, kwargs, result = invoke_with

    protocol = JSONRPCProtocol()

    class Test:
        c = 0

        @staticmethod
        @public
        def fn_a(a, b):
            return a - b

        @staticmethod
        @public
        def fn_b(*a):
            return a[0] - a[1]

        @staticmethod
        @public
        def fn_c(**a):
            return a['a'] - a['b']

    test = Test()
    dispatch.register_instance(test)
    mock_request = Mock(RPCRequest)
    mock_request.args = args
    mock_request.kwargs = kwargs
    mock_request.method = method
    dispatch._dispatch(mock_request, getattr(protocol, '_caller', None))
    if inspect.isclass(result) and issubclass(result, Exception):
        assert type(mock_request.error_respond.call_args[0][0]) == result
    else:
        mock_request.respond.assert_called_with(result)
Пример #17
0
def test_async_class_method_argument_error(async_dispatch, invoke_with,
                                           event_loop):
    method, args, kwargs, result = invoke_with

    protocol = JSONRPCProtocol()

    class Test:
        c = 0

        @classmethod
        @public
        async def fn_a(cls, a, b):
            return a - b - cls.c

        @classmethod
        @public
        async def fn_b(cls, *a):
            return a[0] - a[1] - cls.c

        @classmethod
        @public
        async def fn_c(cls, **a):
            return a['a'] - a['b'] - cls.c

    test = Test()
    async_dispatch.register_instance(test)
    mock_request = Mock(RPCRequest)
    mock_request.args = args
    mock_request.kwargs = kwargs
    mock_request.method = method
    event_loop.run_until_complete(async_dispatch._dispatch(mock_request))
    if inspect.isclass(result) and issubclass(result, Exception):
        assert type(mock_request.error_respond.call_args[0][0]) == result
    else:
        mock_request.respond.assert_called_with(result)
Пример #18
0
 def login(self, username, password):
     self.rpc_client = RPCClient(
         JSONRPCProtocol(),
         HttpWebSocketClientTransport('ws://localhost:9001/api/ws'))
     self.loginManager = self.rpc_client.get_proxy("login.")
     hashed_password = hashlib.sha256(password).hexdigest()
     return self.loginManager.authenticate(username=username,
                                           password=hashed_password)
Пример #19
0
 def __init__(self, ws, rpc_callback):
     dispatcher = RPCDispatcher()
     dispatcher.register_instance(rpc_callback)
     super(WebSocketRPCServer, self).__init__(
         WebSocketServerTransport(ws),
         JSONRPCProtocol(),
         dispatcher,
     )
Пример #20
0
 def __init__(self, node_url=None):
     rpc_client = RPCClient(
         JSONRPCProtocol(),
         HttpPostClientTransport(
             node_url or os.getenv("RADIX_NODE_URL") or DEFAULT_NODE_URL
         ),
     )
     self._rpc_proxy = rpc_client.get_proxy(prefix=RPC_METHOD_PREFIX)
Пример #21
0
 def __init__(self, obj, one_way=False):
     url = obj.env['device_manager.settings']._get_param(
                                                 'mqtt_rpc_bridge_url')
     logger.debug('HTTP bridge url {}'.format(url))
     rpc_client = RPCClient(
         JSONRPCProtocol(),
         HttpPostClientTransport(url)
     )
     self.proxy = rpc_client.get_proxy(one_way=one_way)
Пример #22
0
    def __init__(self, mqtt_url=None, client_uid=None, loop=None, config=None):
        if not loop:
            loop = asyncio.get_event_loop()
        self.loop = loop
        self.protocol = JSONRPCProtocol()
        self.dispatcher = dispatcher
        self.mqtt_url = mqtt_url if mqtt_url else MQTT_URL
        self.mqtt_reply_timeout = MQTT_REPLY_TIMEOUT
        self.client_uid = client_uid if client_uid else CLIENT_UID
        super(MQTTRPC, self).__init__(client_id=self.client_uid,
                                      loop=loop,
                                      config=config)
        for signame in ('SIGINT', 'SIGTERM'):
            self.loop.add_signal_handler(
                getattr(signal, signame),
                lambda: asyncio.ensure_future(self.stop()))

        logger.info('Client {} initialized'.format(self.client_uid))
Пример #23
0
def worker():
    rpc_server = RPCServer(
        SubprocessServerTransport(
            input_port=sys.stdin.buffer, output_port=sys.stdout.buffer
        ),
        JSONRPCProtocol(),
        dispatcher,
    )
    rpc_server.trace = partial(print, file=sys.stderr)
    rpc_server.serve_forever()
Пример #24
0
def WebSocketRPCHandler(trustlines: TrustlinesRelay):

    dispatcher = RPCDispatcher()
    dispatcher.add_method(partial(subscribe, trustlines), "subscribe")

    protocol = JSONRPCProtocol()

    def handle(ws):
        app = RPCWebSocketApplication(protocol, dispatcher, ws)
        app.handle()

    return handle
Пример #25
0
    def __init__(self, rest_url=None):

        self.dispatcher = RESTDispatcher(rest_url)

        # TinyRPC WSGI App
        self.transport = WsgiServerTransport(queue_class=gevent.queue.Queue)
        self.wsgi_app = self.transport.handle

        # TinyRPC RPC Server
        self.rpc_server = RPCServerGreenlets(self.transport, JSONRPCProtocol(),
                                             self.dispatcher)
        gevent.spawn(self.rpc_server.serve_forever)
Пример #26
0
def MessagingWebSocketRPCHandler(trustlines: TrustlinesRelay):

    dispatcher = RPCDispatcher()
    dispatcher.add_method(partial(messaging_subscribe, trustlines), "listen")
    dispatcher.add_method(partial(get_missed_messages, trustlines), "getMissedMessages")

    protocol = JSONRPCProtocol()

    def handle(ws):
        app = RPCWebSocketApplication(protocol, dispatcher, ws)
        app.handle()

    return handle
Пример #27
0
    def __init__(self, app):
        log.debug('initializing JSONRPCServer')
        BaseService.__init__(self, app)
        self.app = app
        self.dispatcher = RPCDispatcher()
        transport = WsgiServerTransport(queue_class=gevent.queue.Queue)

        # start wsgi server as a background-greenlet
        self.wsgi_server = gevent.wsgi.WSGIServer(('127.0.0.1', 5000),
                                                  transport.handle)

        self.rpc_server = RPCServerGreenlets(transport, JSONRPCProtocol(),
                                             self.dispatcher)
Пример #28
0
def connectHandler(cmd, handler):
    dispatcher = RPCDispatcher()
    print("cmd: {}".format(" ".join(cmd)))
    # line buffered
    p = subprocess.Popen(cmd,
                         bufsize=1,
                         universal_newlines=True,
                         stdin=subprocess.PIPE,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)
    transport = PipeTransport(p.stdout, p.stdin)
    rpc_server = RPCServer(transport, JSONRPCProtocol(), dispatcher)
    dispatcher.register_instance(handler, '')
    return (rpc_server, p)
Пример #29
0
def worker():
    ctx = zmq.Context()
    rpc_client = RPCClient(
        JSONRPCProtocol(),
        ZmqClientTransport.create(ctx, "tcp://127.0.0.1:5002"))
    proxy = rpc_client.get_proxy()

    for message in iter(partial(recv, port=sys.stdin), ""):
        proxy.post(f"hello {message}")
        import time

        time.sleep(0.4)
    sys.stdout.write("")
    sys.stdout.close()
Пример #30
0
def gevent_main(wotabag, dispatcher, sdp_transport):
    """Secondary thread for gevent event loop.

    Needed so that it does not conflict with dbus/glib event loop.

    """
    logger = logging.getLogger('wotabag')
    ble_rpc_server = WotabagRPCServerGreenlets(
        sdp_transport,
        JSONRPCProtocol(),
        dispatcher
    )

    # Configure WSGI (HTTP) RPC server
    wsgi_transport = WsgiServerTransport(queue_class=gevent.queue.Queue)
    wsgi_server = WSGIServer((wotabag.rpc_host, wotabag.rpc_port), wsgi_transport.handle)
    gevent.spawn(wsgi_server.serve_forever)
    wsgi_rpc_server = WotabagRPCServerGreenlets(
        wsgi_transport,
        JSONRPCProtocol(),
        dispatcher
    )

    try:
        greenlets = []
        logger.info("Running RPC server at {}:{}".format(wotabag.rpc_host, wotabag.rpc_port))
        greenlets.append(wsgi_rpc_server.start())
        greenlets.append(ble_rpc_server.start())
        gevent.sleep(0)
        server_done.wait()
    except Exception as e:
        logger.exception(e)
        raise e
    finally:
        gevent.joinall(greenlets)
        logger.info("RPC server finished")
Пример #31
0
    def __init__(self,
                 transport,
                 publisher=None,
                 ctx=None,
                 protocol=None,
                 dispatcher=None):

        self.ctx = ctx if ctx else zmq.Context().instance()
        self.protocol = protocol if protocol else JSONRPCProtocol()
        self.dispatcher = dispatcher if dispatcher else RPCDispatcher()
        self.publisher = publisher if publisher else NoOpPublisher()
        if isinstance(transport, dict):
            # dictionary:
            if 'receiver' in transport and 'replier' in transport:
                self.endpoints = transport
            else:
                msg = 'endpoint dictionary {} should contains receiver and replier'
                raise Exception(msg.format(transport))
            self.endpoint = self.endpoints['receiver']
        elif isinstance(transport, basestring):
            # only 1 endpoint is provided; create endpoint for replier by adding port by 10000
            pattern = '(tcp://)?((?P<ip>[0-9.*]+):)?(?P<port>[0-9]+)'
            re_groups = re.match(pattern, transport.strip())
            if not re_groups:
                raise Exception(
                    'Invalid transport format {}; '
                    'expecting tcp://IP:PORT or IP:PORT'.format(transport))
            replier_port = int(re_groups.group('port')) + 10000
            ip = re_groups.group('ip') if re_groups.group('ip') else '*'
            receiver_endpoint = 'tcp://{}:{}'.format(ip, replier_port)
            replier_endpoint = 'tcp://{}:{}'.format(ip, replier_port)
            self.endpoints = {
                'receiver': transport,
                'replier': replier_endpoint
            }
            self.endpoint = self.endpoints['receiver']

        else:
            # existing transport instance
            self.endpoint = transport

        logger_name = self.endpoint.replace('://', '')
        logger_name = logger_name.replace(':', '_')
        logger_name = logger_name.replace('tcp', '')
        self.logger = RPCLogger(logger_name)

        self.init_server(self.endpoints, self.logger)
        self.server_mode = 'normal'
Пример #32
0
class JSONRPCClient:
    """ Ethereum JSON RPC client.

    Args:
        host: Ethereum node host address.
        port: Ethereum node port number.
        privkey: Local user private key, used to sign transactions.
        nonce_update_interval: Update the account nonce every
            `nonce_update_interval` seconds.
        nonce_offset: Network's default base nonce number.
    """

    def __init__(
            self,
            host: str,
            port: int,
            privkey: bytes,
            nonce_update_interval: float = 5.0,
            nonce_offset: int = 0):

        endpoint = 'http://{}:{}'.format(host, port)
        session = requests.Session()
        adapter = requests.adapters.HTTPAdapter(pool_maxsize=50)
        session.mount(endpoint, adapter)

        self.transport = HttpPostClientTransport(
            endpoint,
            post_method=session.post,
            headers={'content-type': 'application/json'},
        )

        self.port = port
        self.privkey = privkey
        self.protocol = JSONRPCProtocol()
        self.sender = privatekey_to_address(privkey)
        # Needs to be initialized to None in the beginning since JSONRPCClient
        # gets constructed before the RaidenService Object.
        self.stop_event = None

        self.nonce_last_update = 0
        self.nonce_current_value = None
        self.nonce_lock = Semaphore()
        self.nonce_update_interval = nonce_update_interval
        self.nonce_offset = nonce_offset

    def __repr__(self):
        return '<JSONRPCClient @%d>' % self.port

    def block_number(self):
        """ Return the most recent block. """
        return quantity_decoder(self.call('eth_blockNumber'))

    def nonce(self, address):
        if len(address) == 40:
            address = unhexlify(address)

        with self.nonce_lock:
            initialized = self.nonce_current_value is not None
            query_time = now()

            if self.nonce_last_update > query_time:
                # Python's 2.7 time is not monotonic and it's affected by clock
                # resets, force an update.
                self.nonce_update_interval = query_time - self.nonce_update_interval
                needs_update = True

            else:
                last_update_interval = query_time - self.nonce_last_update
                needs_update = last_update_interval > self.nonce_update_interval

            if initialized and not needs_update:
                self.nonce_current_value += 1
                return self.nonce_current_value

            pending_transactions_hex = self.call(
                'eth_getTransactionCount',
                address_encoder(address),
                'pending',
            )
            pending_transactions = quantity_decoder(pending_transactions_hex)
            nonce = pending_transactions + self.nonce_offset

            # we may have hammered the server and not all tx are
            # registered as `pending` yet
            if initialized:
                while nonce < self.nonce_current_value:
                    log.debug(
                        'nonce on server too low; retrying',
                        server=nonce,
                        local=self.nonce_current_value,
                    )

                    query_time = now()
                    pending_transactions_hex = self.call(
                        'eth_getTransactionCount',
                        address_encoder(address),
                        'pending',
                    )
                    pending_transactions = quantity_decoder(pending_transactions_hex)
                    nonce = pending_transactions + self.nonce_offset

            self.nonce_current_value = nonce
            self.nonce_last_update = query_time

            return self.nonce_current_value

    def inject_stop_event(self, event):
        self.stop_event = event

    def balance(self, account: address):
        """ Return the balance of the account of given address. """
        res = self.call('eth_getBalance', address_encoder(account), 'pending')
        return quantity_decoder(res)

    def gaslimit(self) -> int:
        last_block = self.call('eth_getBlockByNumber', 'latest', True)
        gas_limit = quantity_decoder(last_block['gasLimit'])
        return gas_limit

    def new_contract_proxy(self, contract_interface, contract_address: address):
        """ Return a proxy for interacting with a smart contract.

        Args:
            contract_interface: The contract interface as defined by the json.
            address: The contract's address.
        """
        return ContractProxy(
            self.sender,
            contract_interface,
            contract_address,
            self.eth_call,
            self.send_transaction,
            self.eth_estimateGas,
        )

    def deploy_solidity_contract(
            self,  # pylint: disable=too-many-locals
            sender,
            contract_name,
            all_contracts,
            libraries,
            constructor_parameters,
            contract_path=None,
            timeout=None,
            gasprice=GAS_PRICE):
        """
        Deploy a solidity contract.
        Args:
            sender (address): the sender address
            contract_name (str): the name of the contract to compile
            all_contracts (dict): the json dictionary containing the result of compiling a file
            libraries (list): A list of libraries to use in deployment
            constructor_parameters (tuple): A tuple of arguments to pass to the constructor
            contract_path (str): If we are dealing with solc >= v0.4.9 then the path
                                 to the contract is a required argument to extract
                                 the contract data from the `all_contracts` dict.
            timeout (int): Amount of time to poll the chain to confirm deployment
            gasprice: The gasprice to provide for the transaction
        """

        if contract_name in all_contracts:
            contract_key = contract_name

        elif contract_path is not None:
            _, filename = os.path.split(contract_path)
            contract_key = filename + ':' + contract_name

            if contract_key not in all_contracts:
                raise ValueError('Unknown contract {}'.format(contract_name))
        else:
            raise ValueError(
                'Unknown contract {} and no contract_path given'.format(contract_name)
            )

        libraries = dict(libraries)
        contract = all_contracts[contract_key]
        contract_interface = contract['abi']
        symbols = solidity_unresolved_symbols(contract['bin_hex'])

        if symbols:
            available_symbols = list(map(solidity_library_symbol, all_contracts.keys()))

            unknown_symbols = set(symbols) - set(available_symbols)
            if unknown_symbols:
                msg = 'Cannot deploy contract, known symbols {}, unresolved symbols {}.'.format(
                    available_symbols,
                    unknown_symbols,
                )
                raise Exception(msg)

            dependencies = deploy_dependencies_symbols(all_contracts)
            deployment_order = dependencies_order_of_build(contract_key, dependencies)

            deployment_order.pop()  # remove `contract_name` from the list

            log.debug('Deploying dependencies: {}'.format(str(deployment_order)))

            for deploy_contract in deployment_order:
                dependency_contract = all_contracts[deploy_contract]

                hex_bytecode = solidity_resolve_symbols(dependency_contract['bin_hex'], libraries)
                bytecode = unhexlify(hex_bytecode)

                dependency_contract['bin_hex'] = hex_bytecode
                dependency_contract['bin'] = bytecode

                transaction_hash_hex = self.send_transaction(
                    sender,
                    to=b'',
                    data=bytecode,
                    gasprice=gasprice,
                )
                transaction_hash = unhexlify(transaction_hash_hex)

                self.poll(transaction_hash, timeout=timeout)
                receipt = self.eth_getTransactionReceipt(transaction_hash)

                contract_address = receipt['contractAddress']
                # remove the hexadecimal prefix 0x from the address
                contract_address = contract_address[2:]

                libraries[deploy_contract] = contract_address

                deployed_code = self.eth_getCode(address_decoder(contract_address))

                if len(deployed_code) == 0:
                    raise RuntimeError('Contract address has no code, check gas usage.')

            hex_bytecode = solidity_resolve_symbols(contract['bin_hex'], libraries)
            bytecode = unhexlify(hex_bytecode)

            contract['bin_hex'] = hex_bytecode
            contract['bin'] = bytecode

        if constructor_parameters:
            translator = ContractTranslator(contract_interface)
            parameters = translator.encode_constructor_arguments(constructor_parameters)
            bytecode = contract['bin'] + parameters
        else:
            bytecode = contract['bin']

        transaction_hash_hex = self.send_transaction(
            sender,
            to=b'',
            data=bytecode,
            gasprice=gasprice,
        )
        transaction_hash = unhexlify(transaction_hash_hex)

        self.poll(transaction_hash, timeout=timeout)
        receipt = self.eth_getTransactionReceipt(transaction_hash)
        contract_address = receipt['contractAddress']

        deployed_code = self.eth_getCode(address_decoder(contract_address))

        if len(deployed_code) == 0:
            raise RuntimeError(
                'Deployment of {} failed. Contract address has no code, check gas usage.'.format(
                    contract_name,
                )
            )

        return self.new_contract_proxy(
            contract_interface,
            contract_address,
        )

    def new_filter(self, fromBlock=None, toBlock=None, address=None, topics=None):
        """ Creates a filter object, based on filter options, to notify when
        the state changes (logs). To check if the state has changed, call
        eth_getFilterChanges.
        """

        json_data = {
            'fromBlock': block_tag_encoder(fromBlock or ''),
            'toBlock': block_tag_encoder(toBlock or ''),
        }

        if address is not None:
            json_data['address'] = address_encoder(address)

        if topics is not None:
            if not isinstance(topics, list):
                raise ValueError('topics must be a list')

            json_data['topics'] = [topic_encoder(topic) for topic in topics]

        filter_id = self.call('eth_newFilter', json_data)
        return quantity_decoder(filter_id)

    def filter_changes(self, fid: int) -> List:
        changes = self.call('eth_getFilterChanges', quantity_encoder(fid))

        if not changes:
            return list()

        assert isinstance(changes, list)
        decoders = {
            'blockHash': data_decoder,
            'transactionHash': data_decoder,
            'data': data_decoder,
            'address': address_decoder,
            'topics': lambda x: [topic_decoder(t) for t in x],
            'blockNumber': quantity_decoder,
            'logIndex': quantity_decoder,
            'transactionIndex': quantity_decoder
        }
        return [
            {k: decoders[k](v) for k, v in c.items() if v is not None}
            for c in changes
        ]

    @check_node_connection
    def call(self, method: str, *args):
        """ Do the request and return the result.

        Args:
            method: The RPC method.
            args: The encoded arguments expected by the method.
                - Object arguments must be supplied as a dictionary.
                - Quantity arguments must be hex encoded starting with '0x' and
                without left zeros.
                - Data arguments must be hex encoded starting with '0x'
        """
        request = self.protocol.create_request(method, args)
        reply = self.transport.send_message(request.serialize().encode())

        jsonrpc_reply = self.protocol.parse_reply(reply)
        if isinstance(jsonrpc_reply, JSONRPCSuccessResponse):
            return jsonrpc_reply.result
        elif isinstance(jsonrpc_reply, JSONRPCErrorResponse):
            raise EthNodeCommunicationError(jsonrpc_reply.error, jsonrpc_reply._jsonrpc_error_code)
        else:
            raise EthNodeCommunicationError('Unknown type of JSONRPC reply')

    def send_transaction(
            self,
            sender: address,
            to: address,
            value: int = 0,
            data: bytes = b'',
            startgas: int = 0,
            gasprice: int = GAS_PRICE,
            nonce: Optional[int] = None):
        """ Helper to send signed messages.

        This method will use the `privkey` provided in the constructor to
        locally sign the transaction. This requires an extended server
        implementation that accepts the variables v, r, and s.
        """

        if not self.privkey and not sender:
            raise ValueError('Either privkey or sender needs to be supplied.')

        if self.privkey:
            privkey_address = privatekey_to_address(self.privkey)
            sender = sender or privkey_address

            if sender != privkey_address:
                raise ValueError('sender for a different privkey.')

            if nonce is None:
                nonce = self.nonce(sender)
        else:
            if nonce is None:
                nonce = 0

        if not startgas:
            startgas = self.gaslimit() - 1

        tx = Transaction(nonce, gasprice, startgas, to=to, value=value, data=data)

        if self.privkey:
            tx.sign(self.privkey)
            result = self.call(
                'eth_sendRawTransaction',
                data_encoder(rlp.encode(tx)),
            )
            return result[2 if result.startswith('0x') else 0:]

        else:

            # rename the fields to match the eth_sendTransaction signature
            tx_dict = tx.to_dict()
            tx_dict.pop('hash')
            tx_dict['sender'] = sender
            tx_dict['gasPrice'] = tx_dict.pop('gasprice')
            tx_dict['gas'] = tx_dict.pop('startgas')

            res = self.eth_sendTransaction(**tx_dict)

        assert len(res) in (20, 32)
        return hexlify(res)

    def eth_sendTransaction(
            self,
            sender: address = b'',
            to: address = b'',
            value: int = 0,
            data: bytes = b'',
            gasPrice: int = GAS_PRICE,
            gas: int = GAS_PRICE,
            nonce: Optional[int] = None):
        """ Creates new message call transaction or a contract creation, if the
        data field contains code.

        Args:
            sender: The address the transaction is sent from.
            to: The address the transaction is directed to.
                (optional when creating new contract)
            gas: Gas provided for the transaction execution. It will
                return unused gas.
            gasPrice: gasPrice used for each unit of gas paid.
            value: Value sent with this transaction.
            data: The compiled code of a contract OR the hash of the
                invoked method signature and encoded parameters.
            nonce: This allows to overwrite your own pending transactions
                that use the same nonce.
        """

        if to == b'' and data.isalnum():
            warnings.warn(
                'Verify that the data parameter is _not_ hex encoded, if this is the case '
                'the data will be double encoded and result in unexpected '
                'behavior.'
            )

        if to == b'0' * 40:
            warnings.warn('For contract creation the empty string must be used.')

        if sender is None:
            raise ValueError('sender needs to be provided.')

        json_data = format_data_for_call(
            sender,
            to,
            value,
            data,
            gas,
            gasPrice
        )

        if nonce is not None:
            json_data['nonce'] = quantity_encoder(nonce)

        res = self.call('eth_sendTransaction', json_data)

        return data_decoder(res)

    def eth_call(
            self,
            sender: address = b'',
            to: address = b'',
            value: int = 0,
            data: bytes = b'',
            startgas: int = GAS_PRICE,
            gasprice: int = GAS_PRICE,
            block_number: Union[str, int] = 'latest'):
        """ Executes a new message call immediately without creating a
        transaction on the blockchain.

        Args:
            sender: The address the transaction is sent from.
            to: The address the transaction is directed to.
            gas: Gas provided for the transaction execution. eth_call
                consumes zero gas, but this parameter may be needed by some
                executions.
            gasPrice: gasPrice used for unit of gas paid.
            value: Integer of the value sent with this transaction.
            data: Hash of the method signature and encoded parameters.
                For details see Ethereum Contract ABI.
            block_number: Determines the state of ethereum used in the
                call.
        """

        json_data = format_data_for_call(
            sender,
            to,
            value,
            data,
            startgas,
            gasprice,
        )
        res = self.call('eth_call', json_data, block_number)

        return data_decoder(res)

    def eth_estimateGas(
            self,
            sender: address = b'',
            to: address = b'',
            value: int = 0,
            data: bytes = b'',
            startgas: int = GAS_PRICE,
            gasprice: int = GAS_PRICE) -> int:
        """ Makes a call or transaction, which won't be added to the blockchain
        and returns the used gas, which can be used for estimating the used
        gas.

        Args:
            sender: The address the transaction is sent from.
            to: The address the transaction is directed to.
            gas: Gas provided for the transaction execution. eth_call
                consumes zero gas, but this parameter may be needed by some
                executions.
            gasPrice: gasPrice used for unit of gas paid.
            value: Integer of the value sent with this transaction.
            data: Hash of the method signature and encoded parameters.
                For details see Ethereum Contract ABI.
            block_number: Determines the state of ethereum used in the
                call.
        """

        json_data = format_data_for_call(
            sender,
            to,
            value,
            data,
            startgas,
            gasprice,
        )
        try:
            res = self.call('eth_estimateGas', json_data)
        except EthNodeCommunicationError as e:
            tx_would_fail = e.error_code and e.error_code in (-32015, -32000)
            if tx_would_fail:  # -32015 is parity and -32000 is geth
                return None
            else:
                raise e

        return quantity_decoder(res)

    def eth_getTransactionReceipt(self, transaction_hash: bytes) -> Dict:
        """ Returns the receipt of a transaction by transaction hash.

        Args:
            transaction_hash: Hash of a transaction.

        Returns:
            A dict representing the transaction receipt object, or null when no
            receipt was found.
        """
        if transaction_hash.startswith(b'0x'):
            warnings.warn(
                'transaction_hash seems to be already encoded, this will'
                ' result in unexpected behavior'
            )

        if len(transaction_hash) != 32:
            raise ValueError(
                'transaction_hash length must be 32 (it might be hex encoded)'
            )

        transaction_hash = data_encoder(transaction_hash)
        return self.call('eth_getTransactionReceipt', transaction_hash)

    def eth_getCode(self, code_address: address, block: Union[int, str] = 'latest') -> bytes:
        """ Returns code at a given address.

        Args:
            code_address: An address.
            block: Integer block number, or the string 'latest',
                'earliest' or 'pending'. Default is 'latest'.
        """
        if code_address.startswith(b'0x'):
            warnings.warn(
                'address seems to be already encoded, this will result '
                'in unexpected behavior'
            )

        if len(code_address) != 20:
            raise ValueError(
                'address length must be 20 (it might be hex encoded)'
            )

        result = self.call('eth_getCode', address_encoder(code_address), block)
        return data_decoder(result)

    def eth_getTransactionByHash(self, transaction_hash: bytes):
        """ Returns the information about a transaction requested by
        transaction hash.
        """

        if transaction_hash.startswith(b'0x'):
            warnings.warn(
                'transaction_hash seems to be already encoded, this will'
                ' result in unexpected behavior'
            )

        if len(transaction_hash) != 32:
            raise ValueError(
                'transaction_hash length must be 32 (it might be hex encoded)'
            )

        transaction_hash = data_encoder(transaction_hash)
        return self.call('eth_getTransactionByHash', transaction_hash)

    def poll(
            self,
            transaction_hash: bytes,
            confirmations: Optional[int] = None,
            timeout: Optional[float] = None):
        """ Wait until the `transaction_hash` is applied or rejected.
        If timeout is None, this could wait indefinitely!

        Args:
            transaction_hash: Transaction hash that we are waiting for.
            confirmations: Number of block confirmations that we will
                wait for.
            timeout: Timeout in seconds, raise an Excpetion on timeout.
        """
        if transaction_hash.startswith(b'0x'):
            warnings.warn(
                'transaction_hash seems to be already encoded, this will'
                ' result in unexpected behavior'
            )

        if len(transaction_hash) != 32:
            raise ValueError(
                'transaction_hash length must be 32 (it might be hex encoded)'
            )

        transaction_hash = data_encoder(transaction_hash)

        deadline = None
        if timeout:
            deadline = gevent.Timeout(timeout)
            deadline.start()

        try:
            # used to check if the transaction was removed, this could happen
            # if gas price is too low:
            #
            # > Transaction (acbca3d6) below gas price (tx=1 Wei ask=18
            # > Shannon). All sequential txs from this address(7d0eae79)
            # > will be ignored
            #
            last_result = None

            while True:
                # Could return None for a short period of time, until the
                # transaction is added to the pool
                transaction = self.call('eth_getTransactionByHash', transaction_hash)

                # if the transaction was added to the pool and then removed
                if transaction is None and last_result is not None:
                    raise Exception('invalid transaction, check gas price')

                # the transaction was added to the pool and mined
                if transaction and transaction['blockNumber'] is not None:
                    break

                last_result = transaction

                gevent.sleep(.5)

            if confirmations:
                # this will wait for both APPLIED and REVERTED transactions
                transaction_block = quantity_decoder(transaction['blockNumber'])
                confirmation_block = transaction_block + confirmations

                block_number = self.block_number()

                while block_number < confirmation_block:
                    gevent.sleep(.5)
                    block_number = self.block_number()

        except gevent.Timeout:
            raise Exception('timeout when polling for transaction')

        finally:
            if deadline:
                deadline.cancel()
Пример #33
0
def provision_wap_conf():
	json_data = JSONRPCProtocol().create_request('wap_conf')
	data = json_data.serialize()
	result = send_request("localhost", 5050, data, wait_for_eof = True)
	return result