def normalize_and_validate_kv_pairs( params: Any, ) -> Iterable[Tuple[bytes, Optional[bytes]]]: if not params: raise RPCError("Missing parameters.") for kv_pair in params: if len(kv_pair) != 2: raise RPCError(f"Invalid kv_pair length: {len(kv_pair)}.") raw_key, raw_value = kv_pair if not is_hex(raw_key): raise RPCError( f"Key: {raw_key} is type: {type(raw_key)}. Keys must be hex-encoded strings." ) key = to_bytes(hexstr=raw_key) value: Union[bytes, None] if not raw_value: value = None elif is_integer(raw_value): value = to_bytes(raw_value) elif is_text(raw_value) and is_hex(raw_value): value = to_bytes(hexstr=raw_value) else: raise RPCError(f"Value: {raw_value} is type: {type(raw_value)}. " "Values must be hex-str, integer, or None.") yield key, value
def validate_and_extract_destination( value: Any) -> Tuple[NodeID, Optional[Endpoint]]: node_id: NodeID endpoint: Optional[Endpoint] if is_hex_node_id(value): node_id = NodeID(decode_hex(value)) endpoint = None elif value.startswith("enode://"): raw_node_id, _, raw_endpoint = value[8:].partition("@") validate_hex_node_id(raw_node_id) validate_endpoint(raw_endpoint) node_id = NodeID(decode_hex(raw_node_id)) raw_ip_address, _, raw_port = raw_endpoint.partition(":") ip_address = ipaddress.ip_address(raw_ip_address) port = int(raw_port) endpoint = Endpoint(ip_address.packed, port) elif value.startswith("enr:"): enr = ENR.from_repr(value) node_id = enr.node_id endpoint = Endpoint.from_enr(enr) else: raise RPCError(f"Unrecognized node identifier: {value}") return node_id, endpoint
async def do_call(self, params: ContentKey) -> str: content_key = params content: bytes try: content = self._network.pinned_content_storage.get_content( content_key) except ContentNotFound: pass else: return encode_hex(content) try: content = self._network.commons_content_storage.get_content( content_key) except ContentNotFound: pass else: return encode_hex(content) try: proof = await self._network.get_content(content_key) except trio.TooSlowError as err: raise RPCError( f"Timeout retrieving content: content_key={content_key.hex()}" ) from err else: return encode_hex(proof.get_content())
async def do_call(self, params: ContentKey) -> str: content_key = params try: content = self._content_storage.get_content(content_key) except ContentNotFound as err: raise RPCError(str(err)) from err else: return encode_hex(content)
def validate_and_normalize_distances(value: Any) -> Tuple[int, ...]: if _is_valid_distance(value): return (value, ) elif (is_list_like(value) and value and all(_is_valid_distance(element) for element in value)): return tuple(value) else: raise RPCError( f"Distances must be either a single integer distance or a non-empty list of " f"distances: {value}")
def extract_params( self, request: RPCRequest) -> Tuple[NodeID, Optional[Endpoint]]: try: raw_params = request["params"] except KeyError as err: raise RPCError(f"Missiing call params: {err}") if len(raw_params) != 1: raise RPCError(f"`ddht_ping` endpoint expects a single parameter: " f"Got {len(raw_params)} params: {raw_params}") value = raw_params[0] node_id: NodeID endpoint: Optional[Endpoint] if is_hex_node_id(value): node_id = NodeID(decode_hex(value)) endpoint = None elif value.startswith("enode://"): raw_node_id, _, raw_endpoint = value[8:].partition("@") validate_hex_node_id(raw_node_id) validate_endpoint(raw_endpoint) node_id = NodeID(decode_hex(raw_node_id)) raw_ip_address, _, raw_port = raw_endpoint.partition(":") ip_address = ipaddress.ip_address(raw_ip_address) port = int(raw_port) endpoint = Endpoint(ip_address.packed, port) elif value.startswith("enr:"): enr = ENR.from_repr(value) node_id = enr.node_id endpoint = Endpoint.from_enr(enr) else: raise RPCError(f"Unrecognized node identifier: {value}") return node_id, endpoint
def validate_endpoint(value: Any) -> None: if not is_endpoint(value): raise RPCError(f"Invalid Endpoint: {value}")
def validate_hex_node_id(value: Any) -> None: if not is_hex_node_id(value): raise RPCError(f"Invalid NodeID: {value}")
def validate_params_length(params: List[Any], length: int) -> None: if len(params) != length: raise RPCError( f"Endpoint expects {length} params: length={len(params)} " f"params={params}")
def validate_and_convert_hexstr(*args: Any) -> Iterable[bytes]: for value in args: try: yield to_bytes(hexstr=value) except TypeError: raise RPCError(f"Invalid hexstr parameter: {value}")
async def do_call(self, params: ContentKey) -> None: content_key = params try: self._content_storage.delete_content(content_key) except ContentNotFound as err: raise RPCError(str(err)) from err
def extract_params(self, request: RPCRequest) -> None: if request.get("params"): raise RPCError(f"Unexpected RPC params: {request['params']}") return None