Exemple #1
0
    res = rpc.get('getblockcount')
    if 'output' in res and 'result' in res['output']:
        height = res['output']['result'] - int(depth)
    else:
        return None
    res = rpc.get('getblockhash', [height])
    out = {}
    if 'output' in res and 'result' in res['output']:
        out['hash'] = res['output']['result']
        res = rpc.get('getblockheader', [out['hash']])
        out['time'] = res['output']['result']['time']
        out['height'] = height
    return out


if __name__ == '__main__':
    if DEBUG:
        app.debug = True

    rpc = RPC(RPCUSER, RPCPASS, SERVER, RPCPORT)
    try:
        rpc.get('getblockcount')
        core_enabled = CORE_ENABLED
    except:
        core_enabled = False

    print("Core enabled: " + str(core_enabled))

    app.run(host='0.0.0.0', port=(os.environ.get('SERVER_PORT', SERVER_PORT)))
    #app.run(host='127.0.0.1', port=SERVER_PORT)
Exemple #2
0
async def connect_client(request):
    game_state = request.app['game_state']

    # make a unique id for this connection's IP address
    connection_ids = request.app['connection_ids']
    connection_ids[request.remote] += 1
    connection_id = connection_ids[request.remote]

    ws = web.WebSocketResponse(
        heartbeat=1.0,
    )
    rpc = RPC(ws, game_state)

    def log(msg, *args, **kwargs):
        log_prefix = f'[{request.remote}#{connection_id}]'
        if rpc.player_id is not None:
            log_prefix += f' [{rpc.player_id}'
            if rpc.player is not None:
                log_prefix += f' ({rpc.player.name})'
            log_prefix += ']'
        print(f'{log_prefix} {msg}', *args, **kwargs)

    log('connecting')
    # upgrade the HTTP request to a WebSocket connection
    await ws.prepare(request)

    log('connected')
    # tell the game state about the new connection
    await game_state.connect(rpc)

    try:
        # loop through all messages receieved over connection
        async for msg in rpc.ws:
            if msg.type == aiohttp.WSMsgType.TEXT:
                # load message as JSON
                try:
                    msg = json.loads(msg.data)
                except json.JSONDecodeError as e:
                    log('message error:', e)
                    continue

                try:
                    # find a method on the RPC type matching the `type` field
                    msg_type = msg.pop('type')
                    if msg_type is None or msg_type.startswith('_') or not hasattr(RPC, msg_type):
                        raise ClientError(f'unknown message type {msg_type}')
                    cmd = getattr(rpc, msg_type)

                    # TODO: type check arguments

                    log(
                        msg_type +
                        '(' +
                        ', '.join(
                            key + '=' + repr(value)
                            for key, value in msg.items()
                        ) +
                        ')',
                    )

                    # use inspect module to get argument names of method
                    required_args = [
                        p.name
                        for p in inspect.signature(cmd).parameters.values()
                        if p.default is inspect.Parameter.empty
                    ]
                    # find which args are missing in WS message
                    missing_args = [
                        arg
                        for arg in required_args
                        if arg not in msg
                    ]
                    if missing_args:
                        raise ClientError(f'missing arguments to {msg_type}: {", ".join(missing_args)}')

                    game_state.message = ''
                    # call the method with the message as kwargs
                    cmd(**msg)

                    # mark the game state as changed so it will update the connections
                    game_state.mark_dirty()
                except ClientError as e:
                    log('client error:', e)
                    # tell the client that it did something wrong
                    await rpc.ws.send_json({
                        'type': 'error',
                        'error': e.message,
                    })
                except:
                    log('error handling message:')
                    traceback.print_exc()

            elif msg.type == aiohttp.WSMsgType.ERROR:
                log('connection closed with exception:', rpc.ws.exception())
    finally:
        # loop ended, client must have disconnected or an error occurred
        log('disconnected')
        # tell the game state that this connection is disconnecting
        await game_state.disconnect(rpc)
        # mark the game state as changed so it can update the remaining connections about the disconnected one
        game_state.mark_dirty()

    return rpc.ws
Exemple #3
0
def stereo_to_xyz(img1_name, img2_name, predictor):
    # read rgb images as pan
    img1 = cv2.imread(img1_name, 0)
    img2 = cv2.imread(img2_name, 0)

    # read rgb images
    rgb_img1 = tifffile.imread(img1_name)
    rgb_img2 = tifffile.imread(img2_name)

    # get RPC metadata for both images
    rpc1 = RPC(img1_name)
    rpc2 = RPC(img2_name)

    # find corresponding points
    rows = img1.shape[0]
    cols = img1.shape[1]
    F, pts1, pts2 = match_rpc(rpc1, rpc2, rows, cols)

    # transpose the point matrices
    x1 = pts1.T
    x2 = pts2.T

    # set camera matrix to identity and distortion to zero
    d = None
    K = np.identity(3)

    # rectify the images
    rimg1, rimg2, rms, max_error, lH, rH, max_yparallax = rectify_images(
        img1, x1, img2, x2, K, d, F, shearing=False)
    print('F Matrix Residual RMS Error = ', rms, ' pixels')
    print('F Matrix Residual Max Error = ', max_error, ' pixels')

    # skip this pair if residual error is too large
    # this is not a good indicator of failure
    if rms > 1.0:
        return None, None, None, None, None

    # skip this pair if max y parallax is too large
    if max_yparallax > 2.0:
        return None, None, None, None, None

    # crop down to the center half of the images
    rows = img1.shape[0]
    cols = img1.shape[1]
    row_offset = int(rows / 4)
    col_offset = int(cols / 4)

    # rectify the RGB versions of the images and crop to center
    rgb_rimg1, rgb_rimg2, rgb_rms, rgb_max_error = rectify_images_rgb(
        rgb_img1, x1, rgb_img2, x2, K, d, F, shearing=False)
    rimg1 = rgb_rimg1[row_offset:rows - row_offset,
                      col_offset:cols - col_offset, :]
    rimg2 = rgb_rimg2[row_offset:rows - row_offset,
                      col_offset:cols - col_offset, :]

    # run DenseMapNet to get stereo disparities
    # and run IC-Net to get semantic labels
    if USE_SGM:
        disparity = sgbm(rimg1, rimg2)
    else:
        disparity = predictor.predict_stereo(rimg1, rimg2)
    #        disparity = predictor.predict_stereo_wls(rimg1, rimg2)
    seg_rimg1 = predictor.predict_semantics(rimg1)

    # check for invalid disparity predictions
    rows = rimg1.shape[0]
    cols = rimg1.shape[1]
    valid = np.ones((rows, cols), dtype=bool)
    valid[disparity < -DMAX_SEARCH] = 0
    valid[disparity > DMAX_SEARCH] = 0
    disparity[disparity < -DMAX_SEARCH] = -DMAX_SEARCH
    disparity[disparity > DMAX_SEARCH] = DMAX_SEARCH

    print('Min disparity found: ', disparity.min())
    print('Max disparity found: ', disparity.max())

    # create a grayscale disparity image
    disparity_image = (disparity + DMAX_SEARCH) / (DMAX_SEARCH * 2.0)
    disparity_image[disparity_image < 0.0] = 0.0
    disparity_image = img_as_ubyte(disparity_image)

    # create a color segmentation image
    cls_image = category_to_color(seg_rimg1)

    # get left epipolar image coordinates and right coordinates from disparities
    # add offsets from image cropping back to image coordinates
    # convert coordinates to original images using homographies from rectification
    rows = rimg1.shape[0]
    cols = rimg1.shape[1]
    left_rows, left_cols = np.mgrid[row_offset:rows + row_offset,
                                    col_offset:cols + col_offset]
    right_cols = deepcopy(left_cols) - disparity
    right_rows = deepcopy(left_rows)

    #    valid[right_cols < 0] = 0
    #    valid[right_cols > cols-1] = 0
    valid[right_cols < col_offset] = 0
    valid[right_cols > cols + col_offset - 1] = 0

    # left_rows = left_rows[:,DMAX_SEARCH:cols-DMAX_SEARCH]
    # left_cols = left_cols[:,DMAX_SEARCH:cols-DMAX_SEARCH]
    # right_rows = right_rows[:,DMAX_SEARCH:cols-DMAX_SEARCH]
    # right_cols = right_cols[:,DMAX_SEARCH:cols-DMAX_SEARCH]
    left_rows = left_rows.ravel()
    left_cols = left_cols.ravel()
    right_rows = right_rows.ravel()
    right_cols = right_cols.ravel()
    num = len(left_cols)
    print('left cols = ', num)
    uv1 = np.array((left_cols, left_rows, np.ones(num)))
    print(uv1.shape)
    print(rH.shape)
    xyw = np.matmul(np.linalg.inv(rH), uv1)
    left_cols = xyw[0] / xyw[2]
    left_rows = xyw[1] / xyw[2]
    uv2 = np.array((right_cols, right_rows, np.ones(num)))
    xyw = np.matmul(np.linalg.inv(lH), uv2)
    right_cols = xyw[0] / xyw[2]
    right_rows = xyw[1] / xyw[2]

    # get left segmentation labels for valid disparities
    # left_seg = seg_rimg1[:,DMAX_SEARCH:cols-DMAX_SEARCH]
    left_seg = seg_rimg1
    print('left_seg shape = ', left_seg.shape)
    left_seg = left_seg.ravel()

    # crop and ravel valid point list
    print('valid shape = ', valid.shape)
    # valid = valid[:,DMAX_SEARCH:cols-DMAX_SEARCH]
    valid = valid.ravel()
    print('valid shape = ', valid.shape)

    # approximate RPCs with local 3x4 matrices
    # use center coordinate of one of the images for reference
    clat, clon, zc = rpc1.approximate_wgs84()
    xc, yc, zone_number, zone_letter = wgs84_to_utm(clat, clon)
    R1, rms1, ic1, jc1 = rpc1.to_matrix(clat, clon, zc)
    R2, rms2, ic2, jc2 = rpc2.to_matrix(clat, clon, zc)

    # triangulate to compute XYZ coordinates for each pixel
    print('Triangulating...')
    points1 = np.array((left_cols - ic1, left_rows - jc1))
    points2 = np.array((right_cols - ic2, right_rows - jc2))
    xyz = cv2.triangulatePoints(R1, R2, points1, points2)
    xyz /= xyz[3]
    xyz = xyz[0:3, valid]
    xyz[0, :] += xc
    xyz[1, :] += yc
    xyz[2, :] += zc
    xyz = np.transpose(xyz)
    print(zone_number, zone_letter)

    # add cls to the xyz array
    xyzc = np.zeros((xyz.shape[0], xyz.shape[1] + 1))
    xyzc[:, 0:3] = xyz
    left_seg = left_seg[valid]
    xyzc[:, 3] = left_seg
    return xyzc, rimg1, rimg2, disparity_image, cls_image
Exemple #4
0
    sys.exit(0)

price_prefix = 'coingecko:nano' if not banano_mode else 'coingecko:banano'

# Environment configuration

rpc_url = os.getenv('RPC_URL', 'http://[::1]:7076')
work_url = os.getenv('WORK_URL', None)
fcm_api_key = os.getenv('FCM_API_KEY', None)
fcm_sender_id = os.getenv('FCM_SENDER_ID', None)
debug_mode = True if int(os.getenv('DEBUG', 1)) != 0 else False

# Objects

loop = asyncio.get_event_loop()
rpc = RPC(rpc_url, banano_mode, work_url=work_url, price_prefix=price_prefix)
util = Util(banano_mode)

# all currency conversions that are available
currency_list = [
    "BTC", "ARS", "AUD", "BRL", "CAD", "CHF", "CLP", "CNY", "CZK", "DKK",
    "EUR", "GBP", "HKD", "HUF", "IDR", "ILS", "INR", "JPY", "KRW", "MXN",
    "MYR", "NOK", "NZD", "PHP", "PKR", "PLN", "RUB", "SEK", "SGD", "THB",
    "TRY", "TWD", "USD", "VES", "ZAR", "SAR", "AED", "KWD"
]


# Push notifications
async def delete_fcm_token_for_account(account: str, token: str,
                                       r: web.Request):
    await r.app['rdata'].delete(token)
Exemple #5
0
import pickle
from rpc import RPC, ORDER

connection = pika.BlockingConnection(
    pika.ConnectionParameters(host='localhost'))
channel = connection.channel()

# create anonymous queue
result = channel.queue_declare(exclusive=True)
callback_queue = result.method.queue


def callback(ch, method, properties, body):
    if method.routing_key == 'orders':
        print("Got my order {}".format(pickle.load(body)))


channel.basic_consume(callback, queue=callback_queue, no_ack=True)

channel.basic_publish(exchange='',
                      routing_key='orders',
                      properties=pika.BasicProperties(reply_to=callback_queue,
                                                      correlation_id=str(
                                                          uuid.uuid1())),
                      body=pickle.dumps(RPC(ORDER, {'hamburger': 2})))
print("Order placed")

channel.start_consuming()

connection.close()
from rpc import RPC

if __name__ == '__main__':
    rpc = RPC()
    rpc.start_server()
def save_block_info(provider, live, blockindex, unconf):
    data = {}

    # obtain data to process
    if live or unconf:
        raw = ''
        if provider == 'blockchaininfo':
            if blockindex != "last":
                url = "https://blockchain.info/block-height/" + str(
                    blockindex) + "?format=json"
            elif unconf:
                url = "https://blockchain.info/unconfirmed-transactions?format=json&offset="
            else:
                url = "https://blockchain.info/latestblock"

            if not unconf:
                response = urllib.urlopen(url)
                raw = response.read()
                parsed = json.loads(raw)
            else:
                txs = []
                response = urllib.urlopen(
                    "https://blockchain.info/q/unconfirmedcount")
                unconf_count = int(response.read())
                for i in range(unconf_count, 0, -50):
                    response = urllib.urlopen(url + str(i))
                    raw = response.read()
                    parsed = json.loads(raw)
                    txs = txs + parsed['txs']

            if blockindex != "last" or unconf:
                if not unconf:
                    height = parsed['blocks'][0]['height']
                    block_hash = parsed['blocks'][0]['hash']
                    data = parsed['blocks'][0]
                else:
                    height = "unconf"
                    block_hash = "unconf"
                    data = {}
                    data['tx'] = txs

            else:
                height = parsed['height']
                block_hash = parsed['hash']
                url = "https://blockchain.info/rawblock/" + parsed['hash']

                response = urllib.urlopen(url)
                raw = response.read()
                parsed = json.loads(raw)

                data = parsed

            f = open(
                "blocks/" + str(height) + "-" + provider + "-" + block_hash +
                ".txt", "w")
            f.write(json.dumps(raw))
            f.close()
        else:
            from rpc import RPC
            rpc = RPC(RPCUSER, RPCPASS, SERVER, RPCPORT)
            block_hash = best_block_hash = rpc.get(
                'getbestblockhash')['output']['result']
            block = rpc.get('getblock', [block_hash])['output']['result']
            height = block['height']

            if blockindex == 'unprocessed':
                con = mysql.connector.connect(user=MYSQL_USER,
                                              password=MYSQL_PASSWORD,
                                              database=MYSQL_DATABASE)
                cur = con.cursor()
                while 1:
                    cur.execute('select * from block where height = %s' %
                                height)
                    if cur.fetchall():
                        height = height - 1
                    else:
                        break

                block_hash = rpc.get('getblockhash',
                                     [height])['output']['result']

                con.close()
            else:
                height = blockindex
                block_hash = rpc.get('getblockhash',
                                     [int(blockindex)])['output']['result']

            block = rpc.get('getblock', [block_hash])['output']['result']
            height = block['height']
            block_hash = block['hash']
            block_time = block['time']
            data['tx'] = []
            tx_cache = {}
            for txid in block['tx']:
                rawtx = rpc.get('getrawtransaction',
                                [txid])['output']['result']
                tx = rpc.get('decoderawtransaction',
                             [rawtx])['output']['result']
                if txid not in tx_cache:
                    tx_cache[txid] = tx

            for txid in block['tx']:
                rpc = RPC(RPCUSER, RPCPASS, SERVER, RPCPORT)
                tx = tx_cache[txid]
                for inp in tx['vin']:
                    if 'txid' not in inp:
                        continue
                    if inp['txid'] not in tx_cache:
                        rawtx = rpc.get('getrawtransaction',
                                        [inp['txid']])['output']['result']
                        inptx = rpc.get('decoderawtransaction',
                                        [rawtx])['output']['result']
                        tx_cache[inp['txid']] = inptx
                    else:
                        inptx = tx_cache[inp['txid']]
                    #TODO: deal with nonstandard transaction inputs whose transactions don't seem to have enough outputs
                    if inp['vout'] < len(inptx['vout']):
                        inp['value'] = inptx['vout'][inp['vout']]['value']
                data['tx'].append(tx)

    else:
        if provider == 'blockchaininfo':
            the_file = '000000000000000016bae92da911065f77e52e65c7c5d164ee12b57247176ab0.json'
        else:
            the_file = 'last'

        with open(the_file) as data_file:
            data = json.load(data_file)

    normalized_data = {'tx': []}
    for tx in data['tx']:
        normalized_data['tx'].append(read_transaction(tx, provider))

    stats = process_block(normalized_data, provider)

    con = mysql.connector.connect(user=MYSQL_USER,
                                  password=MYSQL_PASSWORD,
                                  database=MYSQL_DATABASE)
    cur = con.cursor()
    insertstmt = (
        "insert into block (created, time, height, hash) values (now(), FROM_UNIXTIME(%s), '%s', '%s')"
        % (block_time, height, block_hash))
    cur.execute(insertstmt)

    for key in stats.keys():
        val = stats[key]
        if isinstance(val, dict) and 'count' in val:
            val = val['count']
        cur.execute(
            "insert into block_info (created, time, height, hash, metric, value) values (now(), FROM_UNIXTIME(%s), '%s', '%s', '%s', '%s')"
            % (block_time, height, block_hash, key, val))

    con.commit()
    con.close()

    print json.dumps(stats)
    return height, block_hash
Exemple #8
0
from rpc import RPC

    
if __name__ == '__main__':
    client = RPC()
    client.ask_node(rpc_port=8000,function='test')
Exemple #9
0
def query_bitcoin():
    if not core_enabled:
        body = json.dumps({
            "result": "error",
            "message": "Bitcoin Core not enabled for this server"
        })
        return (body, 200, {
            'Content-length': len(body),
            'Content-type': 'application/json',
        })

    rpc = RPC(RPCUSER, RPCPASS, SERVER, RPCPORT)
    # to begin, get hash, block height, and time for latest, then n-blocks-ago, or for a block hash
    owner = request.args.get('owner')
    string = request.args.get('query')

    sales = db.session.query(Sale).filter(Sale.owner == owner).count()
    res = []
    out = {}
    if sales == 0:
        body = json.dumps({
            "result": "error",
            "message": "Account required to make queries"
        })
        return (body, 200, {
            'Content-length': len(body),
            'Content-type': 'application/json',
        })
    elif string == 'getbydepth':
        depth = request.args.get('depth')
        res = rpc.get('getblockcount')
        if 'output' in res and 'result' in res['output']:
            height = res['output']['result'] - int(depth)
    elif string == 'getbyheight':
        height = request.args.get('height')
    elif string == 'getbyhash':
        res = rpc.get('getblockheader', [request.args.get('hash')])
        height = res['output']['result']['height']
    elif string == 'sendrawtransaction':
        tx = request.args.get('tx')
        res = rpc.get('sendrawtransaction', [str(tx)])
        if 'output' in res and 'result' in res['output']:
            out['txid'] = res['output']['result']
            body = json.dumps(out)
            return (body, 200, {
                'Content-length': len(body),
                'Content-type': 'application/json',
            })

    res = rpc.get('getblockhash', [int(height)])
    out['height'] = height
    if 'output' in res and 'result' in res['output']:
        out['hash'] = res['output']['result']
        res = rpc.get('getblockheader', [str(out['hash'])])
        out['time'] = res['output']['result']['time']
        out['height'] = height
        body = json.dumps(out)
    else:
        body = json.dumps({
            "result": "error",
            "message": "Invalid depth or RPC error"
        })
    return (body, 200, {
        'Content-length': len(body),
        'Content-type': 'application/json',
    })
    sys.exit(0)

price_prefix = 'coingecko:spectresecuritycoin'

# Environment configuration

rpc_url = os.getenv('RPC_URL', 'http://[::1]:13337')
work_url = os.getenv('WORK_URL', None)
fcm_api_key = os.getenv('FCM_API_KEY', None)
fcm_sender_id = os.getenv('FCM_SENDER_ID', None)
debug_mode = True if int(os.getenv('DEBUG', 1)) != 0 else False

# Objects

loop = asyncio.get_event_loop()
rpc = RPC(rpc_url, work_url=work_url, price_prefix=price_prefix)

# all currency conversions that are available
currency_list = ["BTC", "ARS", "AUD", "BRL", "CAD", "CHF", "CLP", "CNY", "CZK", "DKK", "EUR", "GBP", "HKD", "HUF", "IDR",
                 "ILS", "INR", "JPY", "KRW", "MXN", "MYR", "NOK", "NZD", "PHP", "PKR", "PLN", "RUB", "SEK", "SGD",
                 "THB", "TRY", "TWD", "USD", "VES", "ZAR", "SAR", "AED", "KWD"]

# Push notifications

async def delete_fcm_token_for_account(account : str, token : str, r : web.Request):
    await r.app['rfcm'].delete(token)

async def update_fcm_token_for_account(account : str, token : str, r : web.Request, v2 : bool = False):
    """Store device FCM registration tokens in redis"""
    redisInst = r.app['rfcm'] if v2 else r.app['rdata']
    await set_or_upgrade_token_account_list(account, token, r, v2=v2)
Exemple #11
0
def main():
    """
    Check if the number of churns passed in within our allowed range
    """
    if CHURNS < CHURN_LOWER:
        print("Can't churn less than {} times. Exiting...".format(CHURN_LOWER))
        sys.exit(1)
    elif CHURNS > CHURN_UPPER:
        print("Can't churn more than {} times. Exiting...".format(CHURN_UPPER))
        sys.exit(1)
    """
    Indicate whether it's a dry run
    """
    if IS_DRY_RUN:
        print()
        print("*********************************************")
        print("DRY RUN IN PROGRESS: FUNDS WILL NOT BE MOVED!")
        print("*********************************************")
    """
    Check if we need to create new accounts within the walllet
    """
    rpc = RPC()
    response = rpc.get_accounts()
    accounts = response["result"]["subaddress_accounts"]
    total_accounts = len(accounts)

    print("\nChurns: {}\tTotal accounts: {}\n".format(CHURNS, total_accounts))

    if create_accounts(CHURNS, total_accounts, rpc):
        # Re-fetch accounts
        response = rpc.get_accounts()
        accounts = response["result"]["subaddress_accounts"]
    """
    Sweep all to first account
    Grab a transaction hash, then get churn timings.
    The transaction hash is needed to get the churn times.
    """
    print("\nChurn 1")

    # Send all funds to first account
    # and grab tx_hash to get churn timings
    tx_hash = churn(accounts, 1, rpc, dry_run=IS_DRY_RUN)

    wait_times = []

    if tx_hash is not None:
        print(
            "\n\nUsing transaction hash {} to get wait times".format(tx_hash))
        wait_times = get_wait_times_from_transaction(tx_hash, rpc)
    else:
        wait_times = get_dry_run_wait_times(CHURNS, quick=IS_QUICK)

    print_wait_times(CHURNS, wait_times)
    """
    Using the generated churn times: sleep, churn, repeat
    NOTE: First sweep_all counts as a churn.
    """
    for n in range(2, CHURNS):
        # Sleep first, then churn
        current_wait_time = wait_times[n - 2]
        sleep(current_wait_time)

        # Start a new churn
        print("\n\nChurn", n)
        churn(accounts, n, rpc, dry_run=IS_DRY_RUN)
    """
    Last churn, back to account 0
    """
    # Sleep first, then do the last churn
    current_wait_time = wait_times[len(wait_times) - 1]
    sleep(current_wait_time)

    # Transfer all back to main account
    print("\n\nLast churn ({})".format(CHURNS))

    churn(accounts, 0, rpc, dry_run=IS_DRY_RUN)
    """
    Exit when done
    """
    print(
        "\n\nChurns completed successfully\n"
        "(It may take time for your balance to unlock from the last churn)\n")

    # print("Exiting...\n")
    sys.exit(0)
Exemple #12
0
def rpc(name, server):
    conf = defaults['rpc']
    conf['server'] = server

    return RPC(name, conf)
Exemple #13
0
 def kill(self):
     if self.status == "RUNNING" and self.container != None:
         self.cleanup_rpc = RPC(self.container, None,
                                ("CONTAINER_REMOTE_CLEANUP", self.work))
         self.rpcManager.send(self.cleanup_rpc)
     self.pool.activate(self)
Exemple #14
0
 def __init__(self):
     self.bitcoind_command = ['bitcoind']
     self.rpc = RPC(RPCUSER, RPCPASS, SERVER, RPCPORT)