def register_transaction_type_v1(transaction_type_structure: Dict[str, Any]) -> None: """ Takes in a transaction type structure and attempts to register """ model = transaction_type_model.new_from_user_input(transaction_type_structure) try: transaction_type_dao.get_registered_transaction_type(cast(str, model.txn_type)) # This will be a string after creation except exceptions.NotFound: pass else: _log.error("Transaction type is already registered") raise exceptions.TransactionTypeConflict(f"A transaction type of {model.txn_type} is already registered") _log.debug("Uploading new type to datastore") transaction_type_dao.store_registered_transaction_type(model)
def test_get_registered_transaction_type_succeeds(self, storage_get_mock): instance = transaction_type_dao.get_registered_transaction_type( "test_type") storage_get_mock.assert_called_once_with( "TRANSACTION_TYPES/TYPES/test_type") self.assertIsInstance(instance, transaction_type_model.TransactionTypeModel)
def enqueue_l1(transaction: dict) -> None: txn_type_string = transaction["header"]["txn_type"] invocation_attempt = not transaction["header"].get( "invoker" ) # This transaction is an invocation attempt if there is no invoker try: transaction_type = transaction_type_dao.get_registered_transaction_type( txn_type_string) except exceptions.NotFound: _log.error("Invalid transaction type") raise exceptions.InvalidTransactionType( f"Transaction of type {txn_type_string} does not exist") # Enqueue to transaction queue enqueue_generic(transaction, queue=INCOMING_TX_KEY, deadline=0) # Attempt contract invocation if necessary if transaction_type.contract_id and invocation_attempt: _log.info( "Checking if smart contract is associated with this txn_type") contract = smart_contract_dao.get_contract_by_id( transaction_type.contract_id ) # Explicitly checked for existence above contract_active = contract.status["state"] in ["active", "updating"] _log.info(f"Contract found: {contract}") if contract_active: transaction["payload"] = json.loads( transaction["payload"] ) # We must parse the stringied payload of the SC invocation before sending invocation_request = contract.export_as_invoke_request(transaction) enqueue_generic(invocation_request, queue=CONTRACT_INVOKE_MQ_KEY, deadline=0)
def enqueue_l1_pipeline(pipeline: "Pipeline", transaction: Dict[str, Any]) -> "Pipeline": txn_type_string = transaction["header"]["txn_type"] invocation_attempt = not transaction["header"].get("invoker") # This transaction is an invocation attempt if there is no invoker try: transaction_type = transaction_type_dao.get_registered_transaction_type(txn_type_string) except exceptions.NotFound: _log.error("Invalid transaction type") raise exceptions.InvalidTransactionType(f"Transaction of type {txn_type_string} does not exist") pipeline.lpush(INCOMING_TX_KEY, json.dumps(transaction, separators=(",", ":"))) pipeline.sadd(TEMPORARY_TX_KEY, transaction["header"]["txn_id"]) # Attempt contract invocation if necessary if transaction_type.contract_id and invocation_attempt: _log.info("Checking if smart contract is associated with this txn_type") contract = smart_contract_dao.get_contract_by_id(transaction_type.contract_id) # Explicitly checked for existence above contract_active = contract.status["state"] in ["active", "updating"] _log.info(f"Contract found: {contract}") if contract_active: transaction["payload"] = json.loads(transaction["payload"]) # We must parse the stringied payload of the SC invocation before sending invocation_request = contract.export_as_invoke_request(transaction) pipeline.lpush(CONTRACT_INVOKE_MQ_KEY, json.dumps(invocation_request, separators=(",", ":"))) return pipeline
def update_transaction_type_v1(transaction_type: str, custom_indexes: List["custom_index"]) -> None: """ Updates existing transaction types custom indexing """ model = transaction_type_dao.get_registered_transaction_type(transaction_type) model.custom_indexes = custom_indexes transaction_type_dao.store_registered_transaction_type(model)
def register_transaction_type_v1( transaction_type_structure: Dict[str, Any]) -> None: """ Takes in a transaction type structure and attempts to register """ model = transaction_type_model.new_from_user_input( transaction_type_structure) try: transaction_type_dao.get_registered_transaction_type(model.txn_type) except exceptions.NotFound: pass else: _log.error("Transaction type is already registered") raise exceptions.TransactionTypeConflict( f"A transaction type of {model.txn_type} is already registered") _log.debug("Queuing transaction type for creation") transaction_type_dao.create_new_transaction_type(model)
def create_contract_v1(body: dict) -> dict: """Deploy a new contract on the chain Args: body: The parsed body, supplied by user. This is used to create a data model Returns: DTO of the contract at rest which is being created """ # Before anything else, check to see if this chain has too many contracts if redisearch.get_document_count( redisearch.Indexes.smartcontract.value) >= MAX_CONTRACT_LIMIT: raise exceptions.ContractLimitExceeded(MAX_CONTRACT_LIMIT) # Create model and validate fields _log.info(f"Creating data model for {body['txn_type']}") contract = smart_contract_model.new_contract_from_user(body) # Check that this transaction type isn't already taken try: transaction_type_dao.get_registered_transaction_type(contract.txn_type) raise exceptions.TransactionTypeConflict( f"Transaction type {contract.txn_type} already registered") except exceptions.NotFound: pass # Start build task job_processor.begin_task( contract, task_type=smart_contract_model.ContractActions.CREATE) try: # Register new transaction type for smart contract _log.info("Registering new smart contract transaction type") smart_contract_dao.add_smart_contract_index(contract) transaction_type_dao.register_smart_contract_transaction_type( contract, body.get("custom_indexes")) return contract.export_as_at_rest() except Exception: # Try to cleanup if contract doesn't create successfully _log.exception( "Error creating contract index or transaction type. Reverting") job_processor.begin_task( contract, task_type=smart_contract_model.ContractActions.DELETE) raise
def delete_transaction_type_v1(transaction_type: str) -> None: """ Takes in a transaction type Checks if the transaction type is of smart contract Deletes type """ try: existing_type_structure = transaction_type_dao.get_registered_transaction_type(transaction_type) if existing_type_structure is None: raise exceptions.NotFound(transaction_type) if existing_type_structure.contract_id: raise exceptions.ActionForbidden("Cannot delete smart contract transaction type") transaction_type_dao.remove_existing_transaction_type(transaction_type) except exceptions.NotFound: pass
def delete_transaction_type_v1(transaction_type: str) -> None: """ Takes in a transaction type Checks if the transaction type is of smart contract Deletes type """ try: existing_txn_type = transaction_type_dao.get_registered_transaction_type( transaction_type) # If txn type is a smart contract that exists, don't allow it to be deleted if existing_txn_type.contract_id and smart_contract_dao.contract_does_exist( existing_txn_type.contract_id): raise exceptions.ActionForbidden( "Cannot delete smart contract transaction type") transaction_type_dao.remove_existing_transaction_type(transaction_type) except exceptions.NotFound: return