def __init__(self, debug_on, dbg_dump_to_logger=True):
     self.connect = PdoTpConnectHelper()
     self._debug_on = debug_on
     if dbg_dump_to_logger:
         self.dbg_dump = PdoDbgDump(LOGGER)
     else:
         self.dbg_dump = PdoDbgDump()
     LOGGER.debug("Enclave namespace prefix: %s",
                  self.connect.get_enclave_prefix())
 def __init__(self, debug_on, dbg_dump_to_logger=True):
     self.connect = PdoTpConnectHelper()
     self._debug_on = debug_on
     if dbg_dump_to_logger:
         self.dbg_dump = PdoDbgDump(LOGGER)
     else:
         self.dbg_dump = PdoDbgDump()
     LOGGER.debug("CCL state namespace prefix: %s",
                  self.connect.get_ccl_state_prefix())
     LOGGER.debug("CCL information namespace prefix: %s",
                  self.connect.get_ccl_info_prefix())
     LOGGER.debug("Contract namespace prefix: %s",
                  self.connect.get_contract_prefix())
     LOGGER.debug("Enclave namespace prefix: %s",
                  self.connect.get_enclave_prefix())
class ContractEnclaveRegistryTransactionHandler(TransactionHandler):
    def __init__(self, debug_on, dbg_dump_to_logger=True):
        self.connect = PdoTpConnectHelper()
        self._debug_on = debug_on
        if dbg_dump_to_logger:
            self.dbg_dump = PdoDbgDump(LOGGER)
        else:
            self.dbg_dump = PdoDbgDump()
        LOGGER.debug("Enclave namespace prefix: %s",
                     self.connect.get_enclave_prefix())

    @property
    def family_name(self):
        family = self.connect.get_enclave_registry_family_name()
        LOGGER.debug("Enclave family name: %s", family)
        return family

    @property
    def family_versions(self):
        return ['1.0']

    @property
    def namespaces(self):
        return self.connect.get_enclave_prefix()

    def _get_enclave_state(self, context, enclave_id):
        address = self.connect.get_enclave_address(enclave_id)
        return self.connect.get_state(context, address, PdoContractEnclaveInfo)

    def _delete_enclave_state(self, context, enclave_id):
        address = self.connect.get_enclave_address(enclave_id)
        return self.connect.delete_state(context, address)

    def _set_enclave_state(self, context, enclave_id, data):
        address = self.connect.get_enclave_address(enclave_id)
        return self.connect.set_state(context, address, data)

    def _verify_registration_info(self,
                                  payload,
                                  details,
                                  public_key_hash,
                                  context):
        # TODO: Allowing no proof data should be removed in the production version
        if not details.proof_data:
            LOGGER.debug("*** Enclave proof data is empty - simulation mode")
            if not self._debug_on:
                raise InvalidTransaction(
                    'Simulation mode is not allowed when the debug support is OFF')
            return

        # Try to get the report key from the configuration setting.
        # If it is not there, fail verification.
        try:
            report_public_key_pem = self.connect.get_report_public_key(context)
        except KeyError:
            raise \
                ValueError(
                    'Failed to get report public key configuration setting {}'.format(
                        self.connect.get_report_public_key_setting_name()))

        # Retrieve the valid enclave measurement values, converting the comma-
        # delimited list. If it is not there, fail verification.
        try:
            valid_measurements = self.connect.get_valid_measurements(context)
        except KeyError:
            raise \
                ValueError(
                    'Failed to get enclave measurements setting {}'.format(
                        self.connect.get_valid_measurements_setting_name()))

        # Retrieve the valid enclave basename value. If it is not there,
        # fail verification.
        try:
            valid_basenames = self.connect.get_valid_basenames(context)
        except KeyError:
            raise \
                ValueError(
                    'Failed to get enclave basenames setting {}'.format(
                        self.connect.get_valid_basenames_setting_name()))

        verify_enclave_registration_info(self.connect,
                                         payload,
                                         details,
                                         public_key_hash,
                                         context,
                                         report_public_key_pem,
                                         valid_measurements,
                                         valid_basenames)

    # def check_address(context, address, key, register_new):
    def check_address(self, context, key, register_new):
        try:
            state = self._get_enclave_state(context, key)
            if register_new:
                if state.verifying_key:
                    raise InvalidTransaction(
                        'Contract enclave already exist with signing_key {}'\
                        .format(key))
                else:
                    return state
            else:
                if not state.verifying_key:
                    raise InvalidTransaction(
                        'Enclave does not exist: {0}'.format(key))
                else:
                    return state
        except InternalError:
            if not register_new:
                raise InvalidTransaction(
                    'Enclave does not exist: {0}'.format(key))
            else:
                return PdoContractEnclaveInfo()

    def apply(self, transaction, context):
        txn_header = transaction.header
        txn_signer_public_key = txn_header.signer_public_key

        payload = PdoContractEnclaveTransaction()
        payload.ParseFromString(transaction.payload)

        self.dbg_dump.dump_contract_enclave_transaction(payload)
        info = self.check_address(context,
                                  payload.verifying_key,
                                  payload.verb == 'register')

        if payload.verb == 'register':
            public_key_hash = hashlib.sha256(txn_signer_public_key.encode()).hexdigest()
            details = PdoContractEnclaveRegister()
            details.ParseFromString(payload.transaction_details)

            try:
                self._verify_registration_info(payload,
                                               details,
                                               public_key_hash,
                                               context)
            except ValueError as error:
                 raise InvalidTransaction\
                     ('Invalid Signup Info: {}'.format(error))

            info.verifying_key = payload.verifying_key
            info.encryption_key = details.encryption_key
            info.last_registration_block_context = \
                details.registration_block_context
            info.owner_id = txn_signer_public_key
            info.registration_transaction_id = transaction.signature

            self.dbg_dump.dump_contract_enclave_state(info, "Setting new PdoContractEnclaveInfo")
            self._set_enclave_state(context,
                                    payload.verifying_key,
                                    info.SerializeToString())

        elif payload.verb == 'delete' or payload.verb == 'update':
            self.dbg_dump.dump_contract_enclave_state(info, "Received PdoContractEnclaveInfo")

            if payload.verb == 'delete':
                if not self._debug_on:
                    raise InvalidTransaction('Delete is not allowed, debug support is OFF')
                LOGGER.info("Deleting PdoContractEnclaveInfo %s", payload.verifying_key)
                self._delete_enclave_state(context, payload.verifying_key)

            else:
                # Check the contract enclave owner matches transaction signer.
                if info.owner_id != txn_signer_public_key:
                    raise InvalidTransaction(
                        'Owner signature mismatch signer {}, owner {}'
                            .format(info.verifying_key, txn_signer_public_key))

                details = PdoContractEnclaveUpdate()
                details.ParseFromString(payload.transaction_details)
                info.last_registration_block_context = \
                    details.registration_block_context

                self.dbg_dump.dump_contract_enclave_state(info, "Updating existing PdoContractEnclaveInfo")
                self._set_enclave_state(context,
                                        payload.verifying_key,
                                        info.SerializeToString())

        else:
            raise InvalidTransaction('Invalid transaction action {}'
                                     .format(payload.verb))
Beispiel #4
0
class ContractRegistryTransactionHandler(TransactionHandler):
    def __init__(self, debug_on, dbg_dump_to_logger=True):
        self.connect = PdoTpConnectHelper()
        self._debug_on = debug_on
        if dbg_dump_to_logger:
            self.dbg_dump = PdoDbgDump(LOGGER)
        else:
            self.dbg_dump = PdoDbgDump()
        LOGGER.debug("Contract namespace prefix: %s",
                     self.connect.get_contract_prefix())

    @property
    def family_name(self):
        family = self.connect.get_contract_registry_family_name()
        LOGGER.debug("Contract family name: %s", family)
        return family

    @property
    def family_versions(self):
        return ['1.0']

    @property
    def namespaces(self):
        return self.connect.get_contract_prefix()

    def _get_enclave_state(self, context, enclave_id):
        address = self.connect.get_enclave_address(enclave_id)
        return self.connect.get_state(context, address, PdoContractEnclaveInfo)

    def _set_contract_state(self, context, contract_id, data):
        address = self.connect.get_contract_address(contract_id)
        self.connect.set_state(context, address, data)

    def _delete_contract_state(self, context, contract_id):
        address = self.connect.get_contract_address(contract_id)
        self.connect.delete_state(context, address)

    def _get_contract_state(self, context, contract_id):
        address = self.connect.get_contract_address(contract_id)
        return self.connect.get_state(context, address, PdoContractInfo)

    def check_address(self, context, contract_id, register_new):
        LOGGER.debug("check_address.address of: %s", contract_id)

        try:
            state = self._get_contract_state(context, contract_id)

            if register_new:
                if state.contract_id:
                    raise InvalidTransaction(
                        'Contract already exists with signing_key {}'\
                        .format(contract_id))
                else:
                    return state
            else:
                if not state.contract_id:
                    raise InvalidTransaction(
                        'Contract does not exist: {0}'.format(contract_id))
                else:
                    return state
        except InternalError as error:
            if not register_new:
                raise InvalidTransaction(
                    'Contract does not exist: {0}'.format(contract_id))
            else:
                return PdoContractInfo()

    @staticmethod
    def _verify_register(reg_info, txn_signer_public_key):
        if not reg_info.contract_code_hash:
            raise InvalidTransaction('Contract code hash is empty')

        if len(reg_info.provisioning_service_ids) == 0:
            raise InvalidTransaction('No provisioning service specified')

        for provisioning_service_id in reg_info.provisioning_service_ids:
            if not provisioning_service_id:
                raise InvalidTransaction('Empty provisioning service id')

        if not verify_contract_register_signature(reg_info,
                                                  txn_signer_public_key):
            raise InvalidTransaction('Contract register signature is invalid')

    def _verify_enclave_info(self, context, contract_info, enclave_info):
        # enclave_info.contract_enclave_id is not empty
        if not enclave_info.contract_enclave_id:
            raise InvalidTransaction('Empty contract_enclave_id')

        contract_enclave_info = \
            self._get_enclave_state(context, enclave_info.contract_enclave_id)

        # enclave_info.contract_enclave_id is already in the state list
        for c in contract_info.enclaves_info:
            if enclave_info.contract_enclave_id == c.contract_enclave_id:
                raise InvalidTransaction(
                    'Contract enclave id is already in the state list')

        # enclave_info.encrypted_contract_state_encryption_key not empty
        if not enclave_info.encrypted_contract_state_encryption_key:
            raise InvalidTransaction(
                'Empty encrypted_contract_state_encryption_key')

        # enclave_info.enclave_signature is not empty
        if not enclave_info.enclave_signature:
            raise InvalidTransaction('Empty enclave_signature')

        # enclave_info.enclaves_map is not empty
        if len(enclave_info.enclaves_map) == 0:
            raise InvalidTransaction('Empty enclaves_map')

        for m in enclave_info.enclaves_map:
            #  m.provisioning_service_public_key is not empty
            if not m.provisioning_service_public_key:
                raise InvalidTransaction(
                    'Empty provisioning_service_public_key')
            # m.provisioning_service_public_key exists in contract_info
            if not m.provisioning_service_public_key\
                   in contract_info.provisioning_service_ids:
                raise InvalidTransaction(
                    'Provisioning service id {} not in contract'.format(
                        m.provisioning_service_public_key))
            # m.provisioning_contract_state_secret
            if not m.provisioning_contract_state_secret:
                raise InvalidTransaction(
                    'Empty provisioning_contract_state_secret')

        if not contract_enclave_info.verifying_key:
            raise InvalidTransaction('Unregisteted enclave with id {}'.format(
                enclave_info.contract_enclave_id))

        # verify signature
        if not verify_add_enclave_to_contract_signature(
                enclave_info, contract_info):
            raise InvalidTransaction('Enclave signature is invalid')

    def apply(self, transaction, context):
        txn_header = transaction.header
        txn_signer_public_key = txn_header.signer_public_key

        payload = PdoContractTransaction()
        payload.ParseFromString(transaction.payload)
        if payload.verb == 'register':
            sig_unxelified = binascii.unhexlify(transaction.signature)
            digest = hashlib.sha256(sig_unxelified).digest()
            sig_base64 = base64.b64encode(digest)
            contract_id = sig_base64.decode("utf-8", "ignore")
        else:
            contract_id = payload.contract_id

        self.dbg_dump.dump_contract_transaction(payload)

        info = self.check_address(context, contract_id,
                                  payload.verb == 'register')

        if payload.verb != 'register':
            self.dbg_dump.dump_contract_state(info, "Received PdoContractInfo")

        if payload.verb == 'register':
            details = PdoContractRegister()
            details.ParseFromString(payload.transaction_details)

            self._verify_register(details, txn_signer_public_key)

            info.contract_id = contract_id
            info.contract_code_hash = details.contract_code_hash
            info.pdo_contract_creator_pem_key = details.pdo_contract_creator_pem_key
            for id in details.provisioning_service_ids:
                info.provisioning_service_ids.append(id)

            self.dbg_dump.dump_contract_state(info,
                                              "Setting new PdoContractInfo")
            self._set_contract_state(context, contract_id,
                                     info.SerializeToString())
            LOGGER.info("Contract %s was added to the registry.",
                        payload.contract_id)

        elif payload.verb == 'delete':
            if not self._debug_on:
                raise InvalidTransaction(
                    'Delete is not allowed, debug support is OFF')

            LOGGER.info("Contract %s was deleted", payload.contract_id)
            self._delete_contract_state(context, contract_id)

        elif payload.verb == 'add-enclaves':
            details = PdoContractAddEnclaves()
            details.ParseFromString(payload.transaction_details)

            if not verify_add_enclave_to_contract_pdo_signature(
                    details, info, txn_signer_public_key):
                raise InvalidTransaction(
                    'Overall PDO signature for add enclaves transaction is invalid'
                )

            for enclave_info in details.enclaves_info:
                self._verify_enclave_info(context, info, enclave_info)

            for ei in details.enclaves_info:
                enclave_info = info.enclaves_info.add()
                enclave_info.CopyFrom(ei)

            self.dbg_dump.dump_contract_state(
                info, "PdoContractInfo After adding enclave(s)")
            self._set_contract_state(context, contract_id,
                                     info.SerializeToString())
            LOGGER.info("Enclaves were added to contract %s.",
                        payload.contract_id)

        elif payload.verb == 'remove-enclaves':
            details = PdoContractRemoveEnclaves()
            details.ParseFromString(payload.transaction_details)

            for id in details.contract_enclave_ids:
                for ei in info.enclaves_info:
                    if ei.contract_enclave_id == id:
                        info.enclaves_info.remove(ei)
                        break

            self.dbg_dump.dump_contract_state(
                info, "PdoContractInfo after removing enclave(s)")
            self._set_contract_state(context, contract_id,
                                     info.SerializeToString())
            LOGGER.info("Enclaves were removed from contract %s.",
                        payload.contract_id)

        else:
            raise InvalidTransaction('Invalid transaction action {}'.format(
                payload.verb))
class ContractCclTransactionHandler(TransactionHandler):
    def __init__(self, debug_on, dbg_dump_to_logger=True):
        self.connect = PdoTpConnectHelper()
        self._debug_on = debug_on
        if dbg_dump_to_logger:
            self.dbg_dump = PdoDbgDump(LOGGER)
        else:
            self.dbg_dump = PdoDbgDump()
        LOGGER.debug("CCL state namespace prefix: %s",
                     self.connect.get_ccl_state_prefix())
        LOGGER.debug("CCL information namespace prefix: %s",
                     self.connect.get_ccl_info_prefix())
        LOGGER.debug("Contract namespace prefix: %s",
                     self.connect.get_contract_prefix())
        LOGGER.debug("Enclave namespace prefix: %s",
                     self.connect.get_enclave_prefix())

    @property
    def family_name(self):
        family = self.connect.get_ccl_family_name()
        LOGGER.debug("CCL family name: %s", family)
        return family

    @property
    def family_versions(self):
        return ['1.0']

    @property
    def namespaces(self):
        return [
            self.connect.get_ccl_state_prefix(),
            self.connect.get_ccl_info_prefix()
        ]

    def _set_ccl_state(self, context, ccl_state):
        self.connect.set_state(
            context,
            self.connect.get_ccl_state_address(
                ccl_state.state_update.contract_id,
                ccl_state.state_update.current_state_hash),
            ccl_state.SerializeToString())

    def _get_ccl_state(self, context, contract_id, state_hash):
        address = self.connect.get_ccl_state_address(contract_id, state_hash)
        return self.connect.get_state(context, address, CCL_ContractState)

    def _delete_ccl_state(self, context, contract_id, state_hash):
        address = self.connect.get_ccl_state_address(contract_id, state_hash)
        self.connect.delete_state(context, address)

    def _set_ccl_info(self, context, ccl_info):
        address = self.connect.get_ccl_info_address(ccl_info.contract_id)
        self.connect.set_state(context, address, ccl_info.SerializeToString())

    def _get_ccl_info(self, context, contract_id):
        address = self.connect.get_ccl_info_address(contract_id)
        result = self.connect.get_state(context, address,
                                        CCL_ContractInformation)
        return result

    def _delete_ccl_info(self, context, contract_id):
        address = self.connect.get_ccl_info_address(contract_id)
        self.connect.delete_state(context, address)

    def _get_contract_info(self, context, contract_id):
        address = self.connect.get_contract_address(contract_id)
        return self.connect.get_state(context, address, PdoContractInfo)

    def _get_enclave_info(self, context, enclave_id):
        address = self.connect.get_enclave_address(enclave_id)
        return self.connect.get_state(context, address, PdoContractEnclaveInfo)

    def _verify_common(self, context, payload, signer, initialize=False):
        # check that signer matches channel_id
        if payload.channel_id != signer:
            raise InvalidTransaction(
                "Payload channel id '{0}' doesn't match signer '{1}'".format(
                    payload.channel_id, signer))

        # check that this contract exists
        contract = self._get_contract_info(context,
                                           payload.state_update.contract_id)
        if payload.state_update.contract_id != contract.contract_id:
            raise InvalidTransaction('No contract in registry {}'.format(
                payload.state_update.contract_id))

        # check that this enclave exists
        enclave = self._get_enclave_info(context, payload.contract_enclave_id)
        if payload.contract_enclave_id != enclave.verifying_key:
            raise InvalidTransaction('Enclave does not exist for {}'.format(
                payload.contract_enclave_id))

        # check that this enclave is added to the contract
        enclave_found = False
        for e in contract.enclaves_info:
            if e.contract_enclave_id == payload.contract_enclave_id:
                enclave_found = True
                break

        if not enclave_found:
            raise InvalidTransaction(
                'Enclave {0} has not been added to contract {1}'.format(
                    payload.contract_enclave_id,
                    payload.state_update.contract_id))

        # check dependencies
        for d in payload.state_update.dependency_list:
            state = self._get_ccl_state(context, d.contract_id, d.state_hash)

            if not state.state_update.contract_id:
                raise InvalidTransaction(
                    "Dependency doesn't exist for '{0}' '{1}'".format(
                        d.contract_id, d.state_hash))

        # check enclave signature
        if not verify_ccl_transaction_signature(payload, contract):
            raise InvalidTransaction(
                'Contract CCL enclave signature is invalid')

        # verify PDO signature
        if initialize:
            if not verify_ccl_transaction_pdo_signature(payload, contract):
                raise InvalidTransaction(
                    'Contract CCL Initialize PDO signature is invalid')

    def _check_current_ccl_state_and_info(self, context, payload):
        info = self._get_ccl_info(context, payload.state_update.contract_id)
        self.dbg_dump.dump_ccl_info(info)

        if payload.verb == 'initialize':
            if info.contract_id:
                raise InvalidTransaction(
                    'CCL Contract already exists for {}'.format(
                        payload.state_update.contract_id))
        else:
            if not info.contract_id:
                raise InvalidTransaction(
                    'CCL Contract does not exist: {0}'.format(
                        payload.state_update.contract_id))
            else:
                if not info.is_active:
                    raise InvalidTransaction(
                        'CCL Contract has been terminated: {0}'.format(
                            payload.state_update.contract_id))

                state = self._get_ccl_state(context,
                                            info.current_state.contract_id,
                                            info.current_state.state_hash)
                self.dbg_dump.dump_ccl_state(state)

                if state.state_update.contract_id !=\
                        info.current_state.contract_id\
                        or\
                        state.state_update.current_state_hash != \
                        info.current_state.state_hash:
                    raise InvalidTransaction(
                        "CCL Contract state doesn't exist or invalid")

                return state

        # return new state in case of "initialize" action
        return CCL_ContractState()

    def _verify_initialize(self, context, payload, signer):
        if payload.state_update.previous_state_hash:
            raise InvalidTransaction(
                'Previous state hash must be empty on initialize')

        if len(payload.state_update.dependency_list) != 0:
            raise InvalidTransaction(
                'Dependency list must be empty on initialize')

        self._check_current_ccl_state_and_info(context, payload)
        self._verify_common(context, payload, signer, True)

    def _verify_update(self, context, payload, signer):
        state = self._check_current_ccl_state_and_info(context, payload)
        if payload.state_update.previous_state_hash !=\
                state.state_update.current_state_hash:
            raise InvalidTransaction(
                'Previous state hash in transcation {0}'\
                'mismatches current {1}'.format(
                    payload.state_update.previous_state_hash,
                    state.state_update.current_state_hash))

        self._verify_common(context, payload, signer)
        return state

    def _verify_terminate(self, context, payload, signer):
        state = self._check_current_ccl_state_and_info(context, payload)
        if payload.state_update.previous_state_hash !=\
                state.state_update.current_state_hash:
            raise InvalidTransaction(
                'Previous state hash in transcation {0}'\
                'mismatches current {1}'.format(
                    payload.state_update.previous_state_hash,
                    state.state_update.current_state_hash))

        if payload.state_update.current_state_hash:
            raise InvalidTransaction(
                'Current state hash must be empty on terminate')

        self._verify_common(context, payload, signer)
        return state

    def _complete_action(self, context, transaction, payload, contract_id):
        ccl_state = CCL_ContractState()
        ccl_info = CCL_ContractInformation()

        ccl_state.transaction_id = transaction.signature
        ccl_state.state_update.CopyFrom(payload.state_update)

        ccl_info.contract_id = \
            payload.state_update.contract_id
        ccl_info.is_active = \
            True if payload.verb != 'terminate' else False
        ccl_info.current_state.contract_id = \
            ccl_state.state_update.contract_id
        ccl_info.current_state.state_hash = \
            ccl_state.state_update.current_state_hash

        self.dbg_dump.dump_ccl_info(ccl_info)
        self.dbg_dump.dump_ccl_state(ccl_state)

        if payload.verb != 'terminate':
            self._set_ccl_state(context, ccl_state)
        else:
            ccl_info.current_state.state_hash = \
                payload.state_update.previous_state_hash

        self._set_ccl_info(context, ccl_info)

    def apply(self, transaction, context):
        txn_header = transaction.header
        txn_signer_public_key = txn_header.signer_public_key

        payload = CCL_TransactionPayload()
        payload.ParseFromString(transaction.payload)
        self.dbg_dump.dump_ccl_transaction(payload)

        if payload.verb == 'initialize':
            self._verify_initialize(context, payload, txn_signer_public_key)
            self._complete_action(context, transaction, payload,
                                  payload.state_update.contract_id)
            LOGGER.info("Contract CCL initialized for contract %s",
                        payload.state_update.contract_id)

        elif payload.verb == 'update':
            contract_id = self._verify_update(context, payload,
                                              txn_signer_public_key)
            self._complete_action(context, transaction, payload, contract_id)
            LOGGER.info("Contract CCL updated for contract %s",
                        payload.state_update.contract_id)

        elif payload.verb == 'terminate':
            contract_id = self._verify_terminate(context, payload,
                                                 txn_signer_public_key)
            self._complete_action(context, transaction, payload, contract_id)
            LOGGER.info("Contract CCL updated for contract %s",
                        payload.state_update.contract_id)

        elif payload.verb == 'delete':
            # 'delete' is useful for development/testing
            # it should be removed from the production
            # it is for debug only so no verification
            # 1) delete states listed in state_update.dependencies_list

            if not self._debug_on:
                raise InvalidTransaction(
                    'Delete is not allowed, debug support is OFF')

            for d in payload.state_update.dependency_list:
                state = self._get_ccl_state(context, d.contract_id,
                                            d.state_hash)
                if state.state_update.contract_id != d.contract_id:
                    LOGGER.info("CCL state doesn't exist for '%s':'%s'",
                                d.contract_id, d.state_hash)

                else:
                    self._delete_ccl_state(context, d.contract_id,
                                           d.state_hash)
                    LOGGER.info("CCL state deleted for '%s':'%s'",
                                d.contract_id, d.state_hash)

            # 2) if payload.state_update.contract_id != "" remove info also
            if payload.state_update.contract_id:
                info = self._get_ccl_info(context,
                                          payload.state_update.contract_id)
                if info.current_state.contract_id != \
                        payload.state_update.contract_id:
                    LOGGER.info("CCL info doesn't exist for '%s'",
                                payload.state_update.contract_id)
                else:
                    self._delete_ccl_info(context,
                                          payload.state_update.contract_id)
                    LOGGER.info("CCL info deleted for %s",
                                payload.state_update.contract_id)

        else:
            raise InvalidTransaction('Invalid transaction verb {}'.format(
                payload.verb))