def register(plugin, tower_id, host=None, port=None): """ Registers the user to the tower. Args: plugin (:obj:`Plugin`): this plugin. tower_id (:obj:`str`): the identifier of the tower to connect to (a compressed public key). host (:obj:`str`): the ip or hostname to connect to, optional. port (:obj:`int`): the port to connect to, optional. Accepted tower_id formats: - tower_id@host:port - tower_id host port - tower_id@host (will default port to DEFAULT_PORT) - tower_id host (will default port to DEFAULT_PORT) Returns: :obj:`dict`: a dictionary containing the subscription data. """ try: tower_id, tower_netaddr = arg_parser.parse_register_arguments( tower_id, host, port, plugin.wt_client.config) # Defaulting to http hosts for now if not tower_netaddr.startswith("http"): tower_netaddr = "http://" + tower_netaddr # Send request to the server. register_endpoint = f"{tower_netaddr}/register" data = {"public_key": plugin.wt_client.user_id} plugin.log(f"Registering in the Eye of Satoshi (tower_id={tower_id})") response = process_post_response( post_request(data, register_endpoint, tower_id)) plugin.log( f"Registration succeeded. Available slots: {response.get('available_slots')}" ) # Save data tower_info = TowerInfo(tower_netaddr, response.get("available_slots")) plugin.wt_client.lock.acquire() plugin.wt_client.towers[tower_id] = tower_info.get_summary() plugin.wt_client.db_manager.store_tower_record(tower_id, tower_info) plugin.wt_client.lock.release() return response except (InvalidParameter, TowerConnectionError, TowerResponseError) as e: plugin.log(str(e), level="warn") return e.to_json()
def update_tower_state(self, tower_id, tower_update): """ Updates the state of a tower both in memory and disk. Access if restricted thought a lock to prevent race conditions. Args: tower_id (:obj:`str`): the identifier of the tower to be updated. tower_update (:obj:`dict`): a dictionary containing the data to be added / removed. """ self.lock.acquire() tower_info = TowerInfo.from_dict(self.db_manager.load_tower_record(tower_id)) if "status" in tower_update: tower_info.status = tower_update.get("status") if "appointment" in tower_update: locator, signature = tower_update.get("appointment") tower_info.appointments[locator] = signature tower_info.available_slots = tower_update.get("available_slots") if "pending_appointment" in tower_update: data, action = tower_update.get("pending_appointment") if action == "add": tower_info.pending_appointments.append(list(data)) else: tower_info.pending_appointments.remove(list(data)) if "invalid_appointment" in tower_update: tower_info.invalid_appointments.append(list(tower_update.get("invalid_appointment"))) if "misbehaving_proof" in tower_update: tower_info.misbehaving_proof = tower_update.get("misbehaving_proof") self.towers[tower_id] = tower_info.get_summary() self.db_manager.store_tower_record(tower_id, tower_info) self.lock.release()
def get_tower_info(plugin, tower_id): """ Gets information about a given tower. Data comes from disk (DB), so all stored data is provided. Args: plugin (:obj:`Plugin`): this plugin. tower_id: (:obj:`str`): the identifier of the queried tower. Returns: :obj:`dict`: a dictionary containing all data about the queried tower. """ tower_info = TowerInfo.from_dict( plugin.wt_client.db_manager.load_tower_record(tower_id)) pending_appointments = [{ "appointment": appointment, "signature": signature } for appointment, signature in tower_info.pending_appointments] invalid_appointments = [{ "appointment": appointment, "tower_signature": signature } for appointment, signature in tower_info.invalid_appointments] tower_info.pending_appointments = pending_appointments tower_info.invalid_appointments = invalid_appointments return {"id": tower_id, **tower_info.to_dict()}
def __init__(self, sk, user_id, config): self.sk = sk self.user_id = user_id self.towers = {} self.db_manager = TowersDBM(config.get("TOWERS_DB"), plugin) self.retrier = Retrier(config.get("MAX_RETRIES"), Queue()) self.config = config self.lock = Lock() # Populate the towers dict with data from the db for tower_id, tower_info in self.db_manager.load_all_tower_records().items(): self.towers[tower_id] = TowerInfo.from_dict(tower_info).get_summary() Thread(target=self.retrier.manage_retry, args=[plugin], daemon=True).start()
def register(plugin, tower_id, host=None, port=None): """ Registers the user to the tower. Args: plugin (:obj:`Plugin`): this plugin. tower_id (:obj:`str`): the identifier of the tower to connect to (a compressed public key). host (:obj:`str`): the ip or hostname to connect to, optional. port (:obj:`int`): the port to connect to, optional. Accepted tower_id formats: - tower_id@host:port - tower_id host port - tower_id@host (will default port to DEFAULT_PORT) - tower_id host (will default port to DEFAULT_PORT) Returns: :obj:`dict`: a dictionary containing the subscription data. """ try: tower_id, tower_netaddr = arg_parser.parse_register_arguments(tower_id, host, port, plugin.wt_client.config) # Defaulting to http hosts for now if not tower_netaddr.startswith("http"): tower_netaddr = "http://" + tower_netaddr # Send request to the server. register_endpoint = f"{tower_netaddr}/register" data = {"public_key": plugin.wt_client.user_id} plugin.log(f"Registering in the Eye of Satoshi (tower_id={tower_id})") response = process_post_response(post_request(data, register_endpoint, tower_id)) available_slots = response.get("available_slots") subscription_expiry = response.get("subscription_expiry") tower_signature = response.get("subscription_signature") if available_slots is None or not isinstance(available_slots, int): raise TowerResponseError(f"available_slots is missing or of wrong type ({available_slots})") if subscription_expiry is None or not isinstance(subscription_expiry, int): raise TowerResponseError(f"subscription_expiry is missing or of wrong type ({subscription_expiry})") if tower_signature is None or not isinstance(tower_signature, str): raise TowerResponseError(f"signature is missing or of wrong type ({tower_signature})") # Check tower signature registration_receipt = receipts.create_registration_receipt( plugin.wt_client.user_id, available_slots, subscription_expiry ) Cryptographer.recover_pk(registration_receipt, tower_signature) plugin.log(f"Registration succeeded. Available slots: {available_slots}") # Save data tower_info = TowerInfo(tower_netaddr, available_slots) plugin.wt_client.lock.acquire() plugin.wt_client.towers[tower_id] = tower_info.get_summary() plugin.wt_client.db_manager.store_tower_record(tower_id, tower_info) plugin.wt_client.lock.release() return response except (InvalidParameter, TowerConnectionError, TowerResponseError, SignatureError) as e: plugin.log(str(e), level="warn") return e.to_json()