Esempio n. 1
0
    def __cache_data_block__(cls, contract_id, raw_data, data_dir="./data"):
        """
        save a data block into the local cache

        :param contract_id str: contract identifier, base64 encoded
        :param raw_data str: base64 encoded string
        """

        contract_id = ContractState.safe_filename(contract_id)
        state_hash = ContractState.compute_hash(raw_data, encoding='b64')
        state_hash = ContractState.safe_filename(state_hash)

        cache_dir = os.path.join(data_dir, cls.__path__, contract_id)
        filename = putils.build_file_name(state_hash, cache_dir, '.ctx')
        if not os.path.exists(os.path.dirname(filename)):
            os.makedirs(os.path.dirname(filename))

        try:
            logger.debug('save state block to file %s', filename)
            with open(filename, 'w') as statefile:
                statefile.write(raw_data)
                # json.dump(, statefile)
        except Exception as e:
            logger.info('failed to save state; %s', str(e))
            raise Exception('unable to cache state {}'.format(filename))
Esempio n. 2
0
    def __read_data_block_from_cache__(cls,
                                       contract_id,
                                       state_hash,
                                       data_dir="./data"):
        """
        read a data block from the local cache

        :param contract_id str: contract identifier, base64 encoded
        :param state_hash str: b64 encoded string
        """

        contract_id = ContractState.safe_filename(contract_id)
        state_hash = ContractState.safe_filename(state_hash)

        cache_dir = os.path.join(data_dir, cls.__path__, contract_id)
        filename = putils.build_file_name(state_hash, cache_dir,
                                          cls.__extension__)

        try:
            logger.debug('read state block from file %s', filename)
            with open(filename, "r") as statefile:
                raw_data = statefile.read()
        except FileNotFoundError as fe:
            logger.error('file not found; %s', filename)
            return None
        except Exception as e:
            logger.info('error reading state; %s', str(e))
            raise Exception(
                'failed to read state from cache; {}'.format(contract_id))

        return raw_data
Esempio n. 3
0
    def __cache_block_from_eservice__(cls, eservice, contract_id, state_hash, data_dir = None) :
        """
        ensure that a block is cached locally

        :param eservice EnclaveServiceClient object:
        :param contract_id str: contract identifier
        :param state_hash string: base64 encoded hash of the block
        """

        # check to see if the eservice already has the block
        logger.debug('ensure block %s is stored in the local cache', state_hash)

        # first see if the block is already in the cache
        safe_contract_id = ContractState.safe_filename(contract_id)
        safe_state_hash = ContractState.safe_filename(state_hash)

        filename = putils.build_file_name(safe_state_hash, data_dir, cls.__path__, cls.__extension__)
        if os.path.isfile(filename) :
            return

        # it is not in the cache so grab it from the eservice
        raw_data = eservice.block_store_get(state_hash)
        if raw_data :
            # since we don't really trust the eservice, make sure that the
            # block it sent us is really the one that we were supposed to get
            if ContractState.compute_hash(raw_data, encoding='b64') != state_hash :
                raise Exception('invalid block returned from eservice')

            ContractState.__cache_data_block__(contract_id, raw_data, data_dir)

        logger.debug('sent block %s to eservice', state_hash)
Esempio n. 4
0
    def read_from_file(cls, ledger_config, basename, data_dir='./data'):
        filename = putils.build_file_name(basename, data_dir, '.pdo')
        logger.debug('load contract information from %s', filename)
        if os.path.exists(filename) is not True:
            raise FileNotFoundError(errno.ENOENT,
                                    "contract data file does not exist",
                                    filename)

        try:
            with open(filename, "r") as contract_file:
                contract_info = json.load(contract_file)
        except Exception as e:
            logger.warn('load contract information file failed; %s', str(e))
            raise Exception("invalid contract file; {}".format(filename))

        try:
            code_info = contract_info['contract_code']
            code = ContractCode(code_info['Code'], code_info['Name'],
                                code_info['Nonce'])
        except KeyError as ke:
            logger.error('invalid contract data file; missing %s', str(ke))
            raise Exception("invalid contract file; {}".format(filename))
        except Exception as e:
            logger.error('error occurred retreiving contract code; %s', str(e))
            raise Exception("invalid contract file; {}".format(filename))

        ## need to handle the case where the contract has been registered
        ## but the initial state has not been committed

        try:
            contract_id = contract_info['contract_id']
            current_state_hash = ContractState.get_current_state_hash(
                ledger_config, contract_id)
        except Exception as e:
            logger.error('error occurred retreiving contract state hash; %s',
                         str(e))
            raise Exception('invalid contract file; {}'.format(filename))

        try:
            state = ContractState.read_from_cache(contract_id,
                                                  current_state_hash,
                                                  data_dir=data_dir)
            if state is None:
                state = ContractState.get_from_ledger(ledger_config,
                                                      contract_id,
                                                      current_state_hash)
                state.save_to_cache(data_dir=data_dir)
        except Exception as e:
            logger.error('error occurred retreiving contract state; %s',
                         str(e))
            raise Exception("invalid contract file; {}".format(filename))

        obj = cls(code, state, contract_info['contract_id'],
                  contract_info['creator_id'])
        for enclave in contract_info['enclaves_info']:
            obj.set_state_encryption_key(
                enclave['contract_enclave_id'],
                enclave['encrypted_contract_state_encryption_key'])

        return obj
Esempio n. 5
0
    def save_to_file(self, basename, data_dir="./data"):
        serialized = dict()
        serialized['contract_id'] = self.contract_id
        serialized['creator_id'] = self.creator_id
        serialized['contract_code'] = self.contract_code.serialize()

        # this encoding is rather verbose, but mirrors the one that the ledger
        # currently uses
        enclaves_info = []
        for (enclave_id, encrypted_key) in self.enclave_map.items():
            enclave_info = {}
            enclave_info['contract_enclave_id'] = enclave_id
            enclave_info[
                'encrypted_contract_state_encryption_key'] = encrypted_key
            enclaves_info.append(enclave_info)

        serialized['enclaves_info'] = enclaves_info

        filename = putils.build_file_name(basename, data_dir, '.pdo')
        try:
            with open(filename, "w") as contract_file:
                json.dump(serialized, contract_file)
        except Exception as e:
            logger.warn('failed to save contract information; %s', str(e))
            raise Exception(
                'unable to write contract data file {}'.format(filename))
Esempio n. 6
0
    def read_from_file(cls,
                       basename,
                       data_dir=None,
                       txn_keys=None,
                       block_store=None):
        """read_from_file -- read enclave data from a file and initialize a new
        Enclave object with the resulting data.

        :param file_name:  string, name of the file
        :param search_path: list of strings, directories to search for the data file
        :param txn_keys: object of type TransactionKeys
        """

        if txn_keys is None:
            txn_keys = keys.TransactionKeys()

        filename = putils.build_file_name(basename,
                                          data_dir=data_dir,
                                          extension='.enc')
        if os.path.exists(filename) is not True:
            raise FileNotFoundError(errno.ENOENT,
                                    "enclave information file does not exist",
                                    filename)

        logger.debug('load enclave information from %s', filename)
        with open(filename, "r") as enclave_file:
            enclave_info = json.load(enclave_file)

        try:
            assert 'nonce' in enclave_info
            assert 'sealed_data' in enclave_info
            assert 'interpreter' in enclave_info
            assert 'verifying_key' in enclave_info
            assert 'encryption_key' in enclave_info
            assert 'proof_data' in enclave_info
            assert 'enclave_id' in enclave_info
        except KeyError as ke:
            raise Exception('enclave data missing key {0}'.format(str(ke)))
        except:
            raise Exception('invalid enclave data file {0}'.format(filename))

        try:
            public_enclave_data = pdo_enclave.get_enclave_public_info(
                enclave_info['sealed_data'])
            assert public_enclave_data and len(public_enclave_data) == 2
            assert enclave_info['verifying_key'] == public_enclave_data[
                'verifying_key']
            assert enclave_info['encryption_key'] == public_enclave_data[
                'encryption_key']
        except:
            raise Exception(
                'sealed storage does not match enclave data file; {}'.format(
                    filename))

        return cls(enclave_info, txn_keys, block_store)
Esempio n. 7
0
    def __cache_filename__(cls, contract_id, state_hash, data_dir):
        """
        state_hash = base64 encoded

        """
        contract_id = ContractState.safe_filename(contract_id)
        state_hash = ContractState.safe_filename(state_hash)

        subdirectory = os.path.join(cls.__path__, contract_id, state_hash[0:2])
        return putils.build_file_name(state_hash, data_dir, subdirectory,
                                      cls.__extension__)
Esempio n. 8
0
    def save_to_file(self, basename, data_dir = None) :
        enclave_info = dict()
        enclave_info['nonce'] = self.nonce
        enclave_info['sealed_data'] = self.sealed_data
        enclave_info['verifying_key'] = self.verifying_key
        enclave_info['encryption_key'] = self.encryption_key
        enclave_info['proof_data'] = self.proof_data
        enclave_info['enclave_id'] = self.enclave_id

        filename = putils.build_file_name(basename, data_dir=data_dir, extension='.enc')
        logger.debug('save enclave data to %s', filename)
        with open(filename, "w") as file :
            json.dump(enclave_info, file)
Esempio n. 9
0
    def save_to_cache(self, data_dir="./data"):
        contract_id = ContractState.safe_filename(self.contract_id)
        state_hash = ContractState.compute_hash(self.encrypted_state,
                                                encoding='hex')

        cache_dir = os.path.join(data_dir, self.__path__, contract_id)
        filename = putils.build_file_name(state_hash, cache_dir, '.ctx')
        if not os.path.exists(os.path.dirname(filename)):
            os.makedirs(os.path.dirname(filename))

        try:
            logger.debug('save contract state to file %s', filename)
            with open(filename, 'w') as statefile:
                json.dump(self.serialize(), statefile)
        except Exception as e:
            logger.info('failed to save state; %s', str(e))
            raise Exception('unable to cache state {}'.format(filename))
Esempio n. 10
0
    def create_from_scheme_file(cls,
                                name,
                                source_name=None,
                                search_path=['.', '..', './contracts']):
        """Create a code object from a Gipsy source file

        :param name str: the name of the scheme contract class
        :param source_name str: the name of the source file
        :param search_path list of str: directories to search for the source file
        """
        if source_name is None:
            source_name = name
        basename = putils.build_file_name(source_name, extension='.scm')
        filename = putils.find_file_in_path(basename, search_path)
        with open(filename, "r") as cfile:
            code = cfile.read()

        return cls(code, name)
Esempio n. 11
0
    def read_from_cache(cls, contract_id, state_hash, data_dir="./data"):
        contract_id = ContractState.safe_filename(contract_id)
        state_hash = ContractState.safe_filename(state_hash)

        cache_dir = os.path.join(data_dir, cls.__path__, contract_id)
        filename = putils.build_file_name(state_hash, cache_dir,
                                          cls.__extension__)

        try:
            logger.debug('load contract state from file %s', filename)
            with open(filename, "r") as statefile:
                state_info = json.load(statefile)
        except FileNotFoundError as fe:
            return None
        except Exception as e:
            logger.info('error reading state; %s', str(e))
            raise Exception(
                'failed to read state from cache; {}'.format(contract_id))

        return cls(state_info['ContractID'], state_info.get('EncryptedState'))
Esempio n. 12
0
    def save_to_file(self, basename, data_dir=None):
        serialized = dict()
        serialized['extra_data'] = self.extra_data
        serialized['contract_id'] = self.contract_id
        serialized['creator_id'] = self.creator_id
        serialized['contract_code'] = self.contract_code.serialize()

        # this encoding is rather verbose, but mirrors the one that the ledger
        # currently uses
        enclaves_info = []
        for (enclave_id, encrypted_key) in self.enclave_map.items():
            enclave_info = {}
            enclave_info['contract_enclave_id'] = enclave_id
            enclave_info[
                'encrypted_contract_state_encryption_key'] = encrypted_key
            enclaves_info.append(enclave_info)

        serialized['enclaves_info'] = enclaves_info

        # add replication params
        serialized['num_provable_replicas'] = self.replication_params[
            'num_provable_replicas']
        serialized['availability_duration'] = self.replication_params[
            'availability_duration']

        filename = putils.build_file_name(basename, data_dir, self.__path__,
                                          self.__extension__)

        try:
            if not os.path.exists(os.path.dirname(filename)):
                os.makedirs(os.path.dirname(filename))

            with open(filename, "w") as contract_file:
                json.dump(serialized, contract_file)
        except Exception as e:
            logger.warn('failed to save contract information; %s', str(e))
            raise Exception(
                'unable to write contract data file {}'.format(filename))
Esempio n. 13
0
    def read_from_file(cls, ledger_config, basename, data_dir=None):
        filename = putils.build_file_name(basename, data_dir, cls.__path__,
                                          cls.__extension__)
        logger.debug('load contract information from %s', filename)
        if os.path.exists(filename) is not True:
            raise FileNotFoundError(errno.ENOENT,
                                    "contract data file does not exist",
                                    filename)

        try:
            with open(filename, "r") as contract_file:
                contract_info = json.load(contract_file)
        except Exception as e:
            logger.warn('load contract information file failed; %s', str(e))
            raise Exception("invalid contract file; {}".format(filename))

        try:
            code_info = contract_info['contract_code']
            comp_report = None
            if not code_info['CompilationReport'].get(
                    'CompilerVerifyingKey') is None:
                comp_report = ContractCompilationReport.init_from_dict(
                    code_info['CompilationReport'])
            code = ContractCode(code_info['Code'],
                                code_info['Name'],
                                code_info['Nonce'],
                                compilation_report=comp_report)
        except KeyError as ke:
            logger.error('invalid contract data file; missing %s', str(ke))
            raise Exception("invalid contract file; {}".format(filename))
        except Exception as e:
            logger.error('error occurred retreiving contract code; %s', str(e))
            raise Exception("invalid contract file; {}".format(filename))

        ## need to handle the case where the contract has been registered
        ## but the initial state has not been committed

        try:
            contract_id = contract_info['contract_id']
            current_state_hash = ContractState.get_current_state_hash(
                ledger_config, contract_id)
        except Exception as e:
            logger.error('error occurred retreiving contract state hash; %s',
                         str(e))
            raise Exception('invalid contract file; {}'.format(filename))

        try:
            state = ContractState.read_from_cache(contract_id,
                                                  current_state_hash,
                                                  data_dir=data_dir)
            if state is None:
                state = ContractState.get_from_ledger(ledger_config,
                                                      contract_id,
                                                      current_state_hash)
                state.save_to_cache(data_dir=data_dir)
        except Exception as e:
            logger.error('error occurred retreiving contract state; %s',
                         str(e))
            raise Exception("invalid contract file; {}".format(filename))

        extra_data = contract_info.get('extra_data', {})
        obj = cls(code,
                  state,
                  contract_info['contract_id'],
                  contract_info['creator_id'],
                  extra_data=extra_data)
        for enclave in contract_info['enclaves_info']:
            obj.set_state_encryption_key(
                enclave['contract_enclave_id'],
                enclave['encrypted_contract_state_encryption_key'])

        obj.set_replication_parameters(contract_info['num_provable_replicas'],
                                       contract_info['availability_duration'])

        return obj