Пример #1
0
    def evaluate(self) :
        """
        evaluate the request using the enclave service
        """
        encrypted_session_key = self.__encrypt_session_key()

        # Encrypt the request
        serialized_byte_array = crypto.string_to_byte_array(self.__serialize_for_encryption())
        encrypted_request_raw = crypto.SKENC_EncryptMessage(self.session_key, serialized_byte_array)
        encrypted_request = crypto.byte_array_to_base64(encrypted_request_raw)

        try :
            self.contract_state.push_state_to_eservice(self.enclave_service)

            encoded_encrypted_response = self.enclave_service.send_to_contract(encrypted_session_key, encrypted_request)
            logger.debug("raw response from enclave: %s", encoded_encrypted_response)

        except Exception as e:
            logger.warn('contract invocation failed; %s', str(e))
            raise InvocationException('contract invocation failed') from e

        try :
            decrypted_response = self.__decrypt_response(encoded_encrypted_response)
            response_string = crypto.byte_array_to_string(decrypted_response)
            response_parsed = json.loads(response_string[0:-1])

            logger.debug("parsed response: %s", response_parsed)

            contract_response = ContractResponse(self, response_parsed)
        except Exception as e:
            logger.warn('contract response is invalid; %s', str(e))
            raise InvocationException('contract response is invalid') from e

        return contract_response
Пример #2
0
    def evaluate(self):
        encrypted_session_key = self.__encrypt_session_key()
        encrypted_request = self.__encrypt_request()

        try:
            encoded_encrypted_response = self.enclave_service.send_to_contract(
                encrypted_session_key, encrypted_request)
            assert encoded_encrypted_response

            logger.debug("raw response from enclave: %s",
                         encoded_encrypted_response)
        except:
            logger.exception('contract invocation failed')
            raise

        try:
            decrypted_response = self.__decrypt_response(
                encoded_encrypted_response)
            response_string = crypto.byte_array_to_string(decrypted_response)
            response_parsed = json.loads(response_string[0:-1])

            logger.debug("parsed response: %s", response_parsed)

            contract_response = ContractResponse(self, response_parsed)
        except:
            logger.exception('contract response is invalid')
            raise

        return contract_response
Пример #3
0
def LocalMain(config):
    shell = ContractController(config)

    # if there is a script file, process it; the interactive
    # shell will start unless there is an explicit exit in the script
    script_file = config.get("ScriptFile")
    if script_file:
        logger.info("Processing script file %s", str(script_file))
        if not ContractController.ProcessScript(shell, script_file):
            ContractResponse.exit_commit_workers()
            sys.exit(shell.exit_code)

    shell.cmdloop()
    print("")

    ContractResponse.exit_commit_workers()
    sys.exit(shell.exit_code)
Пример #4
0
    def evaluate(self):
        encrypted_session_key = self.__encrypt_session_key()

        # Encrypt the request
        serialized_byte_array = crypto.string_to_byte_array(
            self.__serialize_for_encryption())
        encrypted_request_raw = crypto.SKENC_EncryptMessage(
            self.session_key, serialized_byte_array)
        encrypted_request = crypto.byte_array_to_base64(encrypted_request_raw)

        try:
            # Check and conditionally put the encrypted state into the block store if it is non-empty
            state_hash_b64 = self.contract_state.getStateHash(encoding='b64')
            if state_hash_b64:
                block_store_len = self.enclave_service.block_store_head(
                    state_hash_b64)
                if block_store_len <= 0:
                    # This block wasn't present in the block store of this enclave service - need to send it
                    logger.debug(
                        "Block store did not contain block '%s' - sending it",
                        state_hash_b64)

                    ret = self.enclave_service.block_store_put(
                        state_hash_b64, self.contract_state.encrypted_state)
                    if ret != True:
                        logger.exception("block_store_put failed for key %s",
                                         state_hash_b64)
                        raise

            encoded_encrypted_response = self.enclave_service.send_to_contract(
                encrypted_session_key, encrypted_request)
            if encoded_encrypted_response == None:
                logger.exception(
                    "send_to_contract failed but no exception was thrown")
                raise

            logger.debug("raw response from enclave: %s",
                         encoded_encrypted_response)
        except:
            logger.exception('contract invocation failed')
            raise

        try:
            decrypted_response = self.__decrypt_response(
                encoded_encrypted_response)
            response_string = crypto.byte_array_to_string(decrypted_response)
            response_parsed = json.loads(response_string[0:-1])

            logger.debug("parsed response: %s", response_parsed)

            contract_response = ContractResponse(self, response_parsed)
        except Exception as e:
            logger.exception('contract response is invalid: ' + str(e))
            raise

        return contract_response
Пример #5
0
def ErrorShutdown():
    """
    Perform a clean shutdown after an error
    """
    try:
        if block_store is not None:
            block_store.close()
    except Exception as e:
        logger.exception('failed to close block_store')

    try:
        enclave_helper.shutdown_enclave()
    except Exception as e:
        logger.exception('shutdown failed')

    # Send termination signal to commit tasks
    ContractResponse.exit_commit_workers()

    sys.exit(-1)
Пример #6
0
    def evaluate(self) :
        """
        evaluate the request using the enclave service
        """

        assert self.operation == 'update'

        # Encrypt the request
        serialized_byte_array = crypto.string_to_byte_array(self.__serialize_for_encryption())
        encrypted_request = bytes(crypto.SKENC_EncryptMessage(self.session_key, serialized_byte_array))
        encrypted_key = bytes(self.enclave_keys.encrypt(self.session_key))

        try :
            self.contract_state.push_state_to_eservice(self.enclave_service)
            encrypted_response = self.enclave_service.send_to_contract(encrypted_key, encrypted_request)

        except Exception as e:
            logger.warn('contract invocation failed; %s', str(e))
            raise InvocationException('contract invocation failed') from e

        try :
            decrypted_response = crypto.SKENC_DecryptMessage(self.session_key, encrypted_response)
        except Exception as e:
            logger.exception('failed to decrypt response; %s', encrypted_response)
            raise InvocationException('contract response cannot be decrypted')

        try :
            response_string = crypto.byte_array_to_string(decrypted_response)
            response_parsed = json.loads(response_string[0:-1])

            logger.debug("parsed response: %s", response_parsed)

        except Exception as e:
            logger.exception('contract response is invalid; %s', str(e))
            raise InvocationException('failed to parse contract response') from e

        # if response_parsed['Status'] is False :
        #   raise InvocationException(response_parsed['InvocationResponse'])

        try :
            if response_parsed['Status'] and response_parsed['StateChanged'] :
                contract_response = UpdateStateResponse(self, response_parsed)
            else :
                contract_response = ContractResponse(self, response_parsed)
        except Exception as e:
            logger.exception('contract response is invalid; %s', str(e))
            raise InvocationException('contract response is invalid') from e

        return contract_response
Пример #7
0
def RunService():
    @defer.inlineCallbacks
    def shutdown_twisted():
        logger.info("Stopping Twisted")
        yield reactor.callFromThread(reactor.stop)

    reactor.addSystemEventTrigger('before', 'shutdown', shutdown_twisted)

    atexit.register(lambda: ContractResponse.exit_commit_workers())

    try:
        reactor.run()
    except ReactorNotRunning:
        logger.warn('shutdown')
    except:
        logger.warn('shutdown')

    sys.exit(0)
Пример #8
0
def UpdateTheContract(config, enclaves, contract, contract_invoker_keys):
    commit_dependenices = []
    last_response_committed = None

    ledger_config = config.get('Sawtooth')
    contract_invoker_id = contract_invoker_keys.identity

    # Decide if the contract use a fixed enclave or a randomized one for each update.
    if use_eservice and config['Service']['Randomize_Eservice']:
        enclave_to_use = 'random'
    else:
        enclave_to_use = enclaves[0]

    start_time = time.time()
    total_tests = 0
    total_failed = 0

    test_list = []
    test_file = config['expressions']
    with open(test_file, "r") as efile:
        if test_file.endswith('.exp'):
            fieldnames = ['expression', 'expected', 'invert']
            reader = csv.DictReader(filter(lambda row: row[0] != '#', efile),
                                    fieldnames,
                                    quoting=csv.QUOTE_NONE,
                                    escapechar='\\',
                                    skipinitialspace=True)

            test_list = list(reader)

        elif test_file.endswith('.json'):
            # there is currently no support to set these values outside of the
            # configuration file and that is not going to change soon
            test_max_level = config.get('Test', {}).get('MaxLevel', 0)

            reader = json.load(efile)
            for test in reader:
                if test.get('test-level', 0) > test_max_level:
                    continue

                method = test['MethodName']
                pparms = test.get('PositionalParameters', [])
                kparms = test.get('KeywordParameters', {})
                test['expression'] = contract_helper.invocation_request(
                    method, *pparms, **kparms)
                test_list.append(test)
        else:
            logger.error('unknown test file format; %s', test_file)
            ErrorShutdown()

    for test in test_list:
        expression = test['expression']

        if test.get('description'):
            logger.log(
                plogger.HIGHLIGHT,
                "TEST[{0}] : {1}".format(total_tests,
                                         test['description'].format(**test)))

        try:
            total_tests += 1
            update_request = contract.create_update_request(
                contract_invoker_keys, expression, enclave_to_use)
            update_response = update_request.evaluate()

            raw_result = str(update_response.invocation_response)
            result = raw_result[:15]
            if len(raw_result) >= 15:
                result += "..."

            unpacked_response = contract_helper.invocation_response(raw_result)
            if update_response.status is False:
                logger.info('failed: {0} --> {1}'.format(expression, result))
                if test.get('invert') is None or test.get('invert') != 'fail':
                    total_failed += 1
                    logger.warn('inverted test failed: %s instead of %s',
                                result, test['expected'])

                elif test.get('expected') and not re.match(
                        test.get('expected'), raw_result):
                    total_failed += 1
                    logger.warn('test failed: %s instead of %s', result,
                                test['expected'])

                continue

            logger.info('{0} --> {1}'.format(expression, result))

            if test.get('expected') and not re.match(test.get('expected'),
                                                     raw_result):
                total_failed += 1
                logger.warn('test failed: %s instead of %s', result,
                            test['expected'])

        except Exception as e:
            logger.error('enclave failed to evaluate expression; %s', str(e))
            ErrorShutdown()

        # if this operation did not change state then there is nothing to commit
        if update_response.state_changed:
            # asynchronously submit the commit task: (a commit task replicates
            # change-set and submits the corresponding transaction)
            try:
                logger.info(
                    "asynchronously replicate change set and submit transaction in the background"
                )
                update_response.commit_asynchronously(ledger_config)
                last_response_committed = update_response
            except Exception as e:
                logger.error('failed to submit commit: %s', str(e))
                ErrorShutdown()

            logger.debug('update state')
            contract.set_state(update_response.raw_state)

    if total_failed > 0:
        logger.warn('failed %d of %d tests', total_failed, total_tests)
        ErrorShutdown()

    # wait for the last commit to finish.
    if last_response_committed is not None:
        try:
            txn_id = last_response_committed.wait_for_commit()
            if use_ledger and txn_id is None:
                logger.error("Did not receive txn id for the final commit")
                ErrorShutdown()
        except Exception as e:
            logger.error("Error while waiting for final commit: %s", str(e))
            ErrorShutdown()

    logger.info('completed in %s', time.time() - start_time)
    logger.info('passed %d of %d tests', total_tests - total_failed,
                total_tests)

    #shutdown commit workers
    ContractResponse.exit_commit_workers()
Пример #9
0
def UpdateTheContract(config, contract, enclaves, contract_invoker_keys) :

    ledger_config = config.get('Sawtooth')
    contract_invoker_id = contract_invoker_keys.identity
    last_response_committed = None

    # Decide if the contract use a fixed enclave or a randomized one for each update.
    if use_eservice and config['Service']['Randomize_Eservice']:
        enclave_to_use = 'random'
    else:
        enclave_to_use = enclaves[0]

    start_time = time.time()
    for x in range(config['iterations']) :
        if tamper_block_order :
            # in this evaluation we tamper with the state, so it should fail with a bad authenticator error
            logger.info('the following evaluation should fail with a bad authenticator error')
            temp_saved_state_hash = contract.contract_state.get_state_hash(encoding='b64')
            test_state.TamperWithStateBlockOrder(contract.contract_state)

        try :
            expression = contract_helper.invocation_request('inc_value')
            update_request = contract.create_update_request(contract_invoker_keys, expression, enclave_to_use)
            update_response = update_request.evaluate()

            if update_response.status is False :
                logger.info('failed: {0} --> {1}'.format(expression, update_response.invocation_response))
                continue

            logger.info('{0} --> {1}'.format(expression, update_response.invocation_response))

        except Exception as e:
            logger.error('enclave failed to evaluate expression; %s', str(e))
            ErrorShutdown()

        # if this operation did not change state then there is nothing to commit
        if update_response.state_changed :
            # asynchronously submit the commit task: (a commit task replicates change-set and submits the corresponding transaction)
            try:
                update_response.commit_asynchronously(ledger_config)
                last_response_committed = update_response
            except Exception as e:
                logger.error('failed to submit commit: %s', str(e))
                ErrorShutdown()

            logger.debug('update state')
            contract.set_state(update_response.raw_state)

    # wait for the last commit to finish.
    if last_response_committed is not None:
        try:
            txn_id = last_response_committed.wait_for_commit()
            if use_ledger and txn_id is None:
                logger.error("Did not receive txn id for the last response committed")
                ErrorShutdown()
        except Exception as e:
            logger.error("Error while waiting for the last response committed: %s", str(e))
            ErrorShutdown()

    logger.info("All commits completed")
    logger.info('completed in %s', time.time() - start_time)

    # shutdown commit workers
    ContractResponse.exit_commit_workers()