class TestDeleteTransactionType(unittest.TestCase):
    @patch(
        "dragonchain.webserver.lib.transaction_types.transaction_type_dao.get_registered_transaction_type",
        return_value=transaction_type_model.TransactionTypeModel(
            contract_id="my-id"),
    )
    @patch("dragonchain.lib.dao.smart_contract_dao.contract_does_exist")
    def test_delete_if_txn_type_has_contract_id(
            self, dao_get_registered_txn_type_mock, mock_contract_does_exist):
        self.assertRaises(exceptions.ActionForbidden,
                          transaction_types.delete_transaction_type_v1,
                          "exists_but_contract")
        mock_contract_does_exist.assert_called_once()

    @patch(
        "dragonchain.webserver.lib.transaction_types.transaction_type_dao.remove_existing_transaction_type"
    )
    @patch(
        "dragonchain.webserver.lib.transaction_types.transaction_type_dao.get_registered_transaction_type",
        return_value=transaction_type_model.TransactionTypeModel(
            txn_type="random", contract_id=""),
    )
    def test_delete_txn_type_succeeds(self, mock_get_registered_type,
                                      dao_remove_txn_type_mock):
        transaction_types.delete_transaction_type_v1("random")
        mock_get_registered_type.assert_called_once_with("random")
Exemple #2
0
def get_registered_transaction_types_or_default(
    transaction_types: List[str]
) -> Dict[str, transaction_type_model.TransactionTypeModel]:
    """Bulk get of registered transaction types
       Note: If a transaction type is not found, it is sent back as a TransactionTypeModel with default values
    Args:
        transaction_types: a list of transaction types to fetch models for
    Returns:
        dictionary with key being txn_type and value being of type TransactionTypeModel
    """
    transaction_type_object: Dict[
        str, transaction_type_model.TransactionTypeModel] = {}
    for txn_type in transaction_types:
        if txn_type not in transaction_type_object and not txn_type.startswith(
                "-SYSTEM"):
            try:
                transaction_type_object[
                    txn_type] = get_registered_transaction_type(txn_type)
            except exceptions.NotFound:
                # Use a 'default' TransactionTypeModel if we couldn't find an existing matching txn_type
                transaction_type_object[
                    txn_type] = transaction_type_model.TransactionTypeModel(
                        txn_type=txn_type,
                        custom_indexes=[],
                        contract_id=False)
    return transaction_type_object
def _generate_transaction_indexes() -> None:  # noqa: C901
    # -- CREATE INDEXES FOR TRANSACTIONS --
    client = _get_redisearch_index_client(Indexes.transaction.value)
    try:
        client.create_index([redisearch.TagField("block_id")])  # Used for reverse-lookup of transactions by id (with no txn_type)
    except redis.exceptions.ResponseError as e:
        if not str(e).startswith("Index already exists"):  # We don't care if index already exists
            raise
    try:
        create_transaction_index(namespace.Namespaces.Contract.value, force=False)  # Create the reserved txn type index
    except redis.exceptions.ResponseError as e:
        if not str(e).startswith("Index already exists"):  # We don't care if index already exists
            raise
    txn_types_to_watch = {namespace.Namespaces.Contract.value: 1}  # Will be use when going through all stored transactions
    txn_type_models = {
        namespace.Namespaces.Contract.value: transaction_type_model.TransactionTypeModel(namespace.Namespaces.Contract.value, active_since_block="1")
    }
    for txn_type in transaction_type_dao.list_registered_transaction_types():
        txn_type_model = transaction_type_model.new_from_at_rest(txn_type)
        txn_type_models[txn_type_model.txn_type] = txn_type_model
        _log.info(f"Adding index for {txn_type_model.txn_type}")
        try:
            create_transaction_index(txn_type_model.txn_type, txn_type_model.custom_indexes, force=False)
        except redis.exceptions.ResponseError as e:
            if not str(e).startswith("Index already exists"):  # We don't care if index already exists
                raise
        txn_types_to_watch[txn_type_model.txn_type] = int(txn_type_model.active_since_block)

    # -- LIST AND INDEX ACTUAL TRANSACTIONS FROM STORAGE
    _log.info("Listing all full transactions")
    transaction_blocks = storage.list_objects("TRANSACTION/")
    for txn_path in transaction_blocks:
        # do a check to see if this block's transactions were already marked as indexed
        if not client.redis.sismember(TXN_MIGRATION_KEY, txn_path):
            _log.info(f"Indexing transactions for {txn_path}")
            for txn in storage.get(txn_path).split(b"\n"):
                if txn:
                    txn_model = transaction_model.new_from_at_rest_full(json.loads(txn)["txn"])
                    # Add general transaction index
                    put_document(Indexes.transaction.value, f"txn-{txn_model.txn_id}", {"block_id": txn_model.block_id}, upsert=True)
                    watch_block = txn_types_to_watch.get(txn_model.txn_type)
                    # Extract custom indexes if necessary
                    if watch_block and int(txn_model.block_id) >= watch_block:
                        txn_model.extract_custom_indexes(txn_type_models[txn_model.txn_type])
                        put_document(txn_model.txn_type, txn_model.txn_id, txn_model.export_as_search_index(), upsert=True)
            client.redis.sadd(TXN_MIGRATION_KEY, txn_path)
        else:
            _log.info(f"Skipping already indexed transaction {txn_path}")
Exemple #4
0
def _generate_transaction_indexes_from_scratch() -> None:
    client = _get_redisearch_index_client(Indexes.transaction.value)
    # TODO: replace after redisearch is fixed
    client.create_index([
        TagField("block_id")
    ])  # Used for reverse-lookup of transactions by id (with no txn_type)
    force_create_transaction_index(namespace.Namespaces.Contract.value
                                   )  # Create the reserved txn type index
    txn_types_to_watch = {
        namespace.Namespaces.Contract.value: 1
    }  # Will be use when going through all stored transactions
    txn_type_models = {
        namespace.Namespaces.Contract.value:
        transaction_type_model.TransactionTypeModel(
            namespace.Namespaces.Contract.value, active_since_block="1")
    }
    for txn_type in transaction_type_dao.list_registered_transaction_types():
        txn_type_model = transaction_type_model.new_from_at_rest(txn_type)
        txn_type_models[txn_type_model.txn_type] = txn_type_model
        _log.info(f"Adding index for {txn_type_model.txn_type}")
        force_create_transaction_index(txn_type_model.txn_type,
                                       txn_type_model.custom_indexes)
        txn_types_to_watch[txn_type_model.txn_type] = int(
            txn_type_model.active_since_block)
    _log.info("Listing all full transactions")
    transaction_blocks = storage.list_objects("TRANSACTION/")
    for txn_path in transaction_blocks:
        _log.info(f"Indexing transactions for {txn_path}")
        for txn in storage.get(txn_path).split(b"\n"):
            if txn:
                txn_model = transaction_model.new_from_at_rest_full(
                    json.loads(txn)["txn"])
                # Add general transaction index
                put_document(Indexes.transaction.value,
                             f"txn-{txn_model.txn_id}",
                             {"block_id": txn_model.block_id},
                             upsert=True)
                watch_block = txn_types_to_watch.get(txn_model.txn_type)
                # Extract custom indexes if necessary
                if watch_block and int(txn_model.block_id) >= watch_block:
                    txn_model.extract_custom_indexes(
                        txn_type_models[txn_model.txn_type])
                    put_document(txn_model.txn_type,
                                 txn_model.txn_id,
                                 txn_model.export_as_search_index(),
                                 upsert=True)