Exemplo n.º 1
0
def parse_query_parameters(params: Dict[str, str]) -> Dict[str, Any]:
    query_params: Dict[str, Any] = {}
    if not params.get("q"):
        raise exceptions.ValidationException(
            "User must specify a redisearch query string.")
    query_params["q"] = params["q"]
    if params.get("transaction_type"):
        query_params["transaction_type"] = params["transaction_type"]
    query_params["id_only"] = params.get(
        "id_only") and params["id_only"].lower() != "false" or False
    query_params["verbatim"] = params.get(
        "verbatim") and params["verbatim"].lower() != "false" or False
    if params.get("sort_by"):
        query_params["sort_by"] = params["sort_by"]
        query_params["sort_asc"] = params.get(
            "sort_asc") and params["sort_asc"].lower() != "false"
        if query_params[
                "sort_asc"] is None:  # the above line resolves to None if the get fails
            query_params["sort_asc"] = True
    try:
        query_params["limit"] = int(
            params["limit"]) if params.get("limit") else 10
        query_params["offset"] = int(
            params["offset"]) if params.get("offset") else 0
    except ValueError:
        raise exceptions.ValidationException(
            "Limit and offset must be integer values.")

    return query_params
Exemplo n.º 2
0
def public_blockchain_transaction_v1() -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    data = flask.request.json

    if not data.get("network"):
        raise exceptions.ValidationException("Invalid parameter: network")
    try:
        if data["network"] in ["BTC_MAINNET", "BTC_TESTNET3"]:
            _validate_bitcoin_transaction_v1(data.get("transaction"))
        elif data["network"] in [
                "ETH_MAINNET", "ETH_ROPSTEN", "ETC_MAINNET", "ETC_MORDEN"
        ]:
            _validate_ethereum_transaction_v1(data.get("transaction"))
        else:
            raise exceptions.ValidationException(
                "User input did not match JSON schema")
    except fastjsonschema.JsonSchemaException:
        raise exceptions.ValidationException(
            "User input did not match JSON schema")

    return helpers.flask_http_response(
        200,
        interchain.legacy_sign_blockchain_transaction_v1(
            data["network"], data["transaction"]))
Exemplo n.º 3
0
 def validate_schedule(self) -> None:
     if self.cron and self.seconds:
         raise exceptions.ValidationException("can only have one of 'seconds' or 'cron'")
     if self.cron:
         try:
             CronTrigger.from_crontab(self.cron)
         except ValueError:
             raise exceptions.ValidationException("The provided cron string is invalid")
Exemplo n.º 4
0
def update_api_key_v1(key_id: str) -> Tuple[str, int, Dict[str, str]]:
    if not key_id:
        raise exceptions.ValidationException("Invalid parameter: key_id")

    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    body = flask.request.json

    try:
        _validate_api_key_update_v1(body)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    api_keys.update_api_key_v1(key_id, body["nickname"])
    return helpers.flask_http_response(200, helpers.format_success(True))
Exemplo n.º 5
0
def process_receipt_v1(block_dto: Dict[str, Any]) -> None:
    if not block_dto:
        raise exceptions.ValidationException("block_dto missing")
    _log.info(
        f"[RECEIPT] Got receipt from L{block_dto['header']['level']}: {block_dto}"
    )
    block_model = cast("model.BlockModel",
                       None)  # This will always get defined, or it will raise
    level_received_from: int = block_dto["header"]["level"]
    if level_received_from == 2:
        block_model = l2_block_model.new_from_at_rest(block_dto)
    elif level_received_from == 3:
        block_model = l3_block_model.new_from_at_rest(block_dto)
    elif level_received_from == 4:
        block_model = l4_block_model.new_from_at_rest(block_dto)
    elif level_received_from == 5:
        block_model = l5_block_model.new_from_at_rest(block_dto)
    else:
        raise exceptions.InvalidNodeLevel("Unsupported level receipt")

    _log.info(f"Block model {block_model.__dict__}")
    l1_block_id_set = block_model.get_associated_l1_block_id()

    _log.info(
        f"Processing receipt for blocks {l1_block_id_set} from L{level_received_from}"
    )
    for l1_block_id in l1_block_id_set:
        # Check that the chain which sent this receipt is in our claims, and that this L1 block is accepting receipts for this level
        validations = matchmaking.get_claim_check(
            l1_block_id)["validations"][f"l{level_received_from}"]
        if (
                block_model.dc_id in validations
        ) and broadcast_functions.is_block_accepting_verifications_from_level(
                l1_block_id, level_received_from):
            _log.info(
                f"Verified that block {l1_block_id} was sent. Inserting receipt"
            )
            storage_location = broadcast_functions.verification_storage_location(
                l1_block_id, level_received_from, block_model.dc_id)
            storage.put_object_as_json(storage_location,
                                       block_model.export_as_at_rest())
            # Set new receipt for matchmaking claim check
            try:
                block_id = block_model.block_id
                proof = block_model.proof
                dc_id = block_model.dc_id
                matchmaking.add_receipt(l1_block_id, level_received_from,
                                        dc_id, block_id, proof)
            except Exception:
                _log.exception("matchmaking add_receipt failed!")
            # Update the broadcast system about this receipt
            broadcast_functions.set_receieved_verification_for_block_from_chain_sync(
                l1_block_id, level_received_from, block_model.dc_id)
        else:
            _log.warning(
                f"Chain {block_model.dc_id} (level {level_received_from}) returned a receipt that wasn't expected (possibly expired?) for block {l1_block_id}. Rejecting receipt"  # noqa: B950
            )
            raise exceptions.NotAcceptingVerifications(
                f"Not accepting verifications for block {l1_block_id} from {block_model.dc_id}"
            )
def delete_transaction_type_v1(txn_type: str,
                               **kwargs) -> Tuple[str, int, Dict[str, str]]:
    if not txn_type:
        raise exceptions.ValidationException("Invalid parameter: txn_type")

    transaction_types.delete_transaction_type_v1(txn_type)
    return helpers.flask_http_response(200, helpers.format_success(True))
def get_transaction_type_v1(txn_type: str,
                            **kwargs) -> Tuple[str, int, Dict[str, str]]:
    if not txn_type:
        raise exceptions.ValidationException("Invalid parameter: txn_type")

    return helpers.flask_http_response(
        200, transaction_types.get_transaction_type_v1(txn_type))
Exemplo n.º 8
0
def delete_api_key_v1(key_id: str,
                      **kwargs) -> Tuple[str, int, Dict[str, str]]:
    if not key_id:
        raise exceptions.ValidationException("Invalid parameter: key_id")

    api_keys.delete_api_key_v1(key_id=key_id)
    return helpers.flask_http_response(200, helpers.format_success(True))
Exemplo n.º 9
0
def update_transaction_type_v1(txn_type: str) -> Tuple[str, int, Dict[str, str]]:
    if not txn_type:
        raise exceptions.ValidationException("Invalid parameter: txn_type")

    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    content = flask.request.json

    try:
        _validate_update_txn_type_v1(content)
    except fastjsonschema.JsonSchemaException:
        raise exceptions.ValidationException("User input did not match JSON schema")

    transaction_types.update_transaction_type_v1(txn_type, content["custom_indexes"])
    return helpers.flask_http_response(200, helpers.format_success(True))
Exemplo n.º 10
0
def query_transaction_v1() -> Tuple[str, int, Dict[str, str]]:
    params = helpers.parse_query_parameters(flask.request.args.to_dict())
    if params.get("transaction_type"):
        should_parse = flask.request.headers.get("Parse-Payload") != "false"
        return helpers.flask_http_response(
            200, transactions.query_transactions_v1(params, should_parse))
    raise exceptions.ValidationException(
        "User input must specify transaction type to query")
Exemplo n.º 11
0
 def validate_secret_names(self) -> None:
     if self.secrets is None:
         return
     regex = "[a-zA-Z][a-zA-Z0-9-]{0,16}"
     pattern = re.compile(regex)
     for secret in self.secrets:
         if not pattern.fullmatch(secret):
             raise exceptions.ValidationException(f"secret names must match regex {regex}")
Exemplo n.º 12
0
def update_api_key_v1(key_id: str,
                      **kwargs) -> Tuple[str, int, Dict[str, str]]:
    if not key_id:
        raise exceptions.ValidationException("Invalid parameter: key_id")

    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    body = flask.request.json

    try:
        _validate_api_key_update_v1(body)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    return helpers.flask_http_response(
        200,
        api_keys.update_api_key_v1(key_id, body.get("nickname"),
                                   body.get("permissions_document")))
Exemplo n.º 13
0
    def check_env_names(self) -> None:
        if self.env is None:
            return

        for key in self.env:
            self.env[key] = str(self.env[key])
        regex = "[a-zA-Z][a-zA-Z0-9._-]+"
        pattern = re.compile(regex)
        for env_var in self.env:
            if not pattern.fullmatch(env_var):
                raise exceptions.ValidationException(f"env names must match regex {regex}")
Exemplo n.º 14
0
def update_bitcoin_interchain_v1(name: str) -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")
    data = flask.request.json
    try:
        _validate_bitcoin_network_update_v1(data)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    return helpers.flask_http_response(
        200, interchain.update_bitcoin_interchain_v1(name, data))
Exemplo n.º 15
0
def create_binance_interchain_v1(**kwargs) -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")
    data = flask.request.json
    try:
        _validate_binance_network_create_v1(data)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    return helpers.flask_http_response(
        201, interchain.create_binance_interchain_v1(data))
Exemplo n.º 16
0
def verify_custom_indexes_options(custom_indexes: Iterable["custom_index"]) -> None:
    """Validate an array of custom index DTOs from user input (Raises on error)"""
    for index in custom_indexes:
        index_type = index.get("type")
        if index_type == "text":
            _valid_custom_text_index_options_v1(index.get("options") or {})
        elif index_type == "tag":
            _valid_custom_tag_index_options_v1(index.get("options") or {})
        elif index_type == "number":
            _valid_custom_number_index_options_v1(index.get("options") or {})
        else:
            raise exceptions.ValidationException(f"Index {index} does not contain a valid type")
Exemplo n.º 17
0
def create_api_key_v1() -> Tuple[str, int, Dict[str, str]]:
    nickname = ""
    if flask.request.is_json:
        body = flask.request.json
        try:
            _validate_api_key_creation_v1(body)
        except fastjsonschema.JsonSchemaException as e:
            raise exceptions.ValidationException(str(e))
        nickname = body.get("nickname") or ""

    return helpers.flask_http_response(201,
                                       api_keys.create_api_key_v1(nickname))
Exemplo n.º 18
0
def create_ethereum_interchain_v1() -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")
    data = flask.request.json
    try:
        _validate_ethereum_network_create_v1(data)
    except fastjsonschema.JsonSchemaException:
        raise exceptions.ValidationException(
            "User input did not match JSON schema")

    return helpers.flask_http_response(
        201, interchain.create_ethereum_interchain_v1(data))
Exemplo n.º 19
0
def create_binance_transaction_v1(name: str,
                                  **kwargs) -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")
    data = flask.request.json
    try:
        _validate_binance_transaction_v1(data)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    return helpers.flask_http_response(
        200, interchain.sign_interchain_transaction_v1("binance", name, data))
Exemplo n.º 20
0
def set_default_network_v1(**kwargs) -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")
    data = flask.request.json
    try:
        _validate_set_default_interchain_v1(data)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    return helpers.flask_http_response(
        200,
        interchain.set_default_interchain_v1(data["blockchain"], data["name"]))
Exemplo n.º 21
0
def update_contract_v1(contract_id: str) -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    update = flask.request.json

    try:
        _validate_sc_update_v1(update)
    except fastjsonschema.JsonSchemaException:
        raise exceptions.ValidationException("User input did not match JSON schema")

    return helpers.flask_http_response(202, smart_contracts.update_contract_v1(contract_id, update))
Exemplo n.º 22
0
def register_transaction_type_v1() -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    content = flask.request.json

    try:
        _validate_create_txn_type_v1(content)
    except fastjsonschema.JsonSchemaException:
        raise exceptions.ValidationException("User input did not match JSON schema")

    transaction_types.register_transaction_type_v1(content)
    return helpers.flask_http_response(200, helpers.format_success(True))
Exemplo n.º 23
0
def create_bitcoin_transaction_v1(
        name: str) -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")
    data = flask.request.json
    try:
        _validate_bitcoin_transaction_v1(data)
    except fastjsonschema.JsonSchemaException:
        raise exceptions.ValidationException(
            "User input did not match JSON schema")

    return helpers.flask_http_response(
        200, interchain.sign_interchain_transaction_v1("bitcoin", name, data))
Exemplo n.º 24
0
def post_transaction_v1(**kwargs) -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    txn = flask.request.json

    try:
        _validate_txn_create_v1(txn)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    return helpers.flask_http_response(
        201, transactions.submit_transaction_v1(txn, flask.request.headers.get("X-Callback-URL"), api_key=kwargs["used_auth_key"])
    )
Exemplo n.º 25
0
def post_contract_v1() -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    contract = flask.request.json

    try:
        _validate_sc_create_v1(contract)
        if contract.get("custom_indexes"):
            helpers.verify_custom_indexes_options(contract.get("custom_indexes"))
    except fastjsonschema.JsonSchemaException:
        raise exceptions.ValidationException("User input did not match JSON schema")

    return helpers.flask_http_response(202, smart_contracts.create_contract_v1(contract))
Exemplo n.º 26
0
def enqueue_v1() -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    content = flask.request.json
    deadline = int(cast(str, flask.request.headers.get(
        "deadline"))) if flask.request.headers.get("deadline") else 30

    try:
        _validate_broadcast_schema_v1(content)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    dragonnet.enqueue_item_for_verification_v1(content, deadline)
    return helpers.flask_http_response(200, helpers.format_success(True))
Exemplo n.º 27
0
def register_transaction_type_v1(**kwargs) -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    content = flask.request.json

    try:
        _validate_create_txn_type_v1(content)
        if content.get("custom_indexes"):
            helpers.verify_custom_indexes_options(content["custom_indexes"])
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    transaction_types.register_transaction_type_v1(content)
    return helpers.flask_http_response(200, helpers.format_success(True))
Exemplo n.º 28
0
def query_transactions_v1(params: Dict[str, Any],
                          parse: bool = True) -> "RSearch":
    """invoke queries on redisearch indexes
    Args:
        params: Dictionary of redisearch query options
        parse: If true, parse the transaction payload before returning
    Returns:
        {"results": [], "total": total} storage objects matching search query
    """
    if not params.get("transaction_type"):
        raise exceptions.ValidationException(
            "transaction_type must be supplied for transaction queries")
    try:
        query_result = redisearch.search(
            index=params["transaction_type"],
            query_str=params["q"],
            only_id=params.get("id_only"),
            verbatim=params.get("verbatim"),
            offset=params.get("offset"),
            limit=params.get("limit"),
            sort_by=params.get("sort_by"),
            sort_asc=params.get("sort_asc"),
        )
    except redis.exceptions.ResponseError as e:
        error_str = str(e)
        # Detect if this is a syntax error; if so, throw it back as a 400 with the message
        if error_str.startswith("Syntax error"):
            raise exceptions.BadRequest(error_str)
        # If unknown index, user provided a bad transaction type
        elif error_str == "Unknown Index name":
            raise exceptions.BadRequest("Invalid transaction type")
        else:
            raise
    result: "RSearch" = {"total": query_result.total, "results": []}
    if params.get("id_only"):
        result["results"] = [x.id for x in query_result.docs]
    else:
        transactions = []
        for doc in query_result.docs:
            block_id = doc.block_id
            transaction_id = doc.id
            retrieved_txn = storage.select_transaction(block_id,
                                                       transaction_id)
            if parse:
                retrieved_txn["payload"] = json.loads(retrieved_txn["payload"])
            transactions.append(retrieved_txn)
        result["results"] = transactions
    return result
Exemplo n.º 29
0
def dragonnet_auth_v1() -> Tuple[str, int, Dict[str, str]]:
    """
    Create a new DragonNet interchain communication key pair with the requester (unauthenticated by design)
    """
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    body = flask.request.json

    try:
        _validate_interchain_auth_v1(body)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    dragonnet.register_interchain_auth_v1(body)
    return helpers.flask_http_response(201, helpers.format_success(True))
Exemplo n.º 30
0
def post_transaction_v1() -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    txn = flask.request.json

    try:
        _validate_txn_create_v1(txn)
    except fastjsonschema.JsonSchemaException:
        raise exceptions.ValidationException(
            "User input did not match JSON schema")

    return helpers.flask_http_response(
        201,
        transactions.submit_transaction_v1(
            txn, flask.request.headers.get("X-Callback-URL")))