예제 #1
0
def command_create(state, bindings, pargs):
    """controller command to create a contract
    """
    interp = os.environ.get("PDO_INTERPRETER", "gipsy")

    parser = argparse.ArgumentParser(prog='create')
    parser.add_argument('-c',
                        '--contract-class',
                        help='Name of the contract class',
                        required=True,
                        type=str)
    parser.add_argument(
        '-i',
        '--interpreter',
        help='Name of the interpreter used to evaluate the contract',
        default=interp)
    parser.add_argument('-s',
                        '--contract-source',
                        help='File that contains contract source code',
                        required=True,
                        type=str)
    parser.add_argument('-p',
                        '--pservice-group',
                        help='Name of the provisioning service group to use',
                        default="default")
    parser.add_argument('-e',
                        '--eservice-group',
                        help='Name of the enclave service group to use',
                        default="default")
    parser.add_argument('-f',
                        '--save-file',
                        help='File where contract data is stored',
                        type=str)
    parser.add_argument('--symbol', help='binding symbol for result', type=str)
    options = parser.parse_args(pargs)

    contract_class = options.contract_class
    contract_source = options.contract_source

    # ---------- load the invoker's keys ----------
    try:
        keyfile = state.get(['Key', 'FileName'])
        keypath = state.get(['Key', 'SearchPath'])
        client_keys = ServiceKeys.read_from_file(keyfile, keypath)
    except Exception as e:
        raise Exception('unable to load client keys; {0}'.format(str(e)))

    # ---------- read the contract source code ----------
    try:
        source_path = state.get(['Contract', 'SourceSearchPath'])
        contract_code = ContractCode.create_from_file(
            contract_class,
            contract_source,
            source_path,
            interpreter=options.interpreter)
    except Exception as e:
        raise Exception('unable to load contract source; {0}'.format(str(e)))

    logger.debug('Loaded contract code for %s', contract_class)

    # ---------- set up the enclave clients ----------
    eservice_clients = get_eservice_list(state, options.eservice_group)
    if len(eservice_clients) == 0:
        raise Exception('unable to locate enclave services in the group %s',
                        options.eservice_group)

    preferred_eservice_client = get_eservice(
        state, eservice_group=options.eservice_group)
    if preferred_eservice_client.interpreter != options.interpreter:
        raise Exception(
            'enclave interpreter does not match requested contract interpreter %s',
            options.interpreter)

    # ---------- set up the provisioning service clients ----------
    pservice_clients = get_pservice_list(state, options.pservice_group)
    if len(pservice_clients) == 0:
        raise Exception(
            'unable to locate provisioning services in the group %s',
            options.pservice_group)

    # ---------- register contract ----------
    data_directory = state.get(['Contract', 'DataDirectory'])
    ledger_config = state.get(['Sawtooth'])

    try:
        provisioning_service_keys = [pc.identity for pc in pservice_clients]
        contract_id = register_contract(ledger_config, client_keys,
                                        contract_code,
                                        provisioning_service_keys)

        logger.debug('Registered contract with class %s and id %s',
                     contract_class, contract_id)
        contract_state = ContractState.create_new_state(contract_id)
        contract = Contract(contract_code, contract_state, contract_id,
                            client_keys.identity)

        # must fix this later
        contract.extra_data[
            'preferred-enclave'] = preferred_eservice_client.enclave_id

        contract_file = "{0}_{1}.pdo".format(contract_class, contract.short_id)
        if options.save_file:
            contract_file = options.save_file

        contract.save_to_file(contract_file, data_dir=data_directory)

    except Exception as e:
        raise Exception('failed to register the contract; {0}'.format(str(e)))

    # provision the encryption keys to all of the enclaves
    try:
        encrypted_state_encryption_keys = __add_enclave_secrets(
            ledger_config, contract.contract_id, client_keys, eservice_clients,
            pservice_clients)

        for enclave_id in encrypted_state_encryption_keys:
            encrypted_key = encrypted_state_encryption_keys[enclave_id]
            contract.set_state_encryption_key(enclave_id, encrypted_key)

        contract.save_to_file(contract_file, data_dir=data_directory)
    except Exception as e:
        raise Exception('failed to provisioning the enclaves; {0}'.format(
            str(e)))

    # create the initial contract state
    try:
        __create_contract(ledger_config, client_keys,
                          preferred_eservice_client, eservice_clients,
                          contract)

        contract.contract_state.save_to_cache(data_dir=data_directory)
        contract.save_to_file(contract_file, data_dir=data_directory)
    except Exception as e:
        raise Exception(
            'failed to create the initial contract state; {0}'.format(str(e)))

    if contract_id and options.symbol:
        bindings.bind(options.symbol, contract_id)
예제 #2
0
def LocalMain(commands, config):
    # ---------- load the contract ----------
    try:
        ledger_config = config['Sawtooth']
        contract_config = config['Contract']
        service_config = config['Service']
        key_config = config['Key']
    except KeyError as ke:
        logger.error('missing configuration section %s', str(ke))
        sys.exit(-1)

    # ---------- load the invoker's keys ----------
    try:
        keyfile = key_config['FileName']
        keypath = key_config['SearchPath']
        client_keys = ServiceKeys.read_from_file(keyfile, keypath)
    except KeyError as ke:
        logger.error('missing configuration parameter %s', str(ke))
        sys.exit(-1)
    except Exception as e:
        logger.error('unable to load client keys; %s', str(e))
        sys.exit(-1)

    # ---------- read the contract source code ----------
    try:
        contract_name = contract_config['Name']
        data_directory = contract_config['DataDirectory']
        save_file = contract_config['SaveFile']
        source_file = contract_config['SourceFile']
        source_path = contract_config['SourceSearchPath']
        contract_code = ContractCode.create_from_scheme_file(
            contract_name, source_file, source_path)
    except KeyError as ke:
        logger.error('missing configuration parameter %s', str(ke))
        sys.exit(-1)
    except Exception as e:
        logger.error('unable to load contract source; %s', str(e))
        sys.exit(-1)

    logger.info('Loaded contract data for %s', contract_name)

    # ---------- set up the enclave clients ----------
    try:
        enclaveclients = []
        for url in service_config['EnclaveServiceURLs']:
            enclaveclients.append(EnclaveServiceClient(url))
    except Exception as e:
        logger.error('unable to setup enclave services; %s', str(e))
        sys.exit(-1)

    # ---------- set up the provisioning service clients ----------
    # This is a dictionary of provisioning service public key : client pairs
    try:
        provclients = []
        for url in service_config['ProvisioningServiceURLs']:
            provclients.append(ProvisioningServiceClient(url))
    except Exception as e:
        logger.error('unable to setup provisioning services; %s', str(e))
        sys.exit(-1)

    logger.debug("All enclaveclients: %s", enclaveclients)
    logger.debug("All provclients: %s", provclients)

    # process the commands to create & register the contract
    if 'register' in commands:
        try:
            provisioning_service_keys = [pc.identity for pc in provclients]
            contract_id = register_contract(ledger_config, client_keys,
                                            contract_code,
                                            provisioning_service_keys)

            logger.info('Registered contract %s with id %s', contract_name,
                        contract_id)
            contract_state = ContractState.create_new_state(contract_id)
            contract = Contract(contract_code, contract_state, contract_id,
                                client_keys.identity)
            contract.save_to_file(save_file, data_dir=data_directory)
        except Exception as e:
            logger.error('failed to register the contract; %s', str(e))
            sys.exit(-1)
    else:
        # need to read the contract from the contract file
        contract = Contract.read_from_file(ledger_config, contract_name,
                                           data_directory)

    if 'addenclave' in commands:
        encrypted_state_encryption_keys = AddEnclaveSecrets(
            ledger_config, contract.contract_id, client_keys, enclaveclients,
            provclients)

        for enclave_id in encrypted_state_encryption_keys:
            encrypted_key = encrypted_state_encryption_keys[enclave_id]
            contract.set_state_encryption_key(enclave_id, encrypted_key)

        contract.save_to_file(save_file, data_dir=data_directory)
        logger.info(
            'Successfully added enclave secrets to ledger for contract %s',
            contract_code.name)

    if 'create' in commands:
        CreateContract(ledger_config, client_keys, enclaveclients, contract)

        contract.contract_state.save_to_cache(data_dir=data_directory)
        contract.save_to_file(save_file, data_dir=data_directory)

    print('export CONTRACTID={0}'.format(contract.contract_id))
예제 #3
0
def CreateAndRegisterContract(config, enclave, contract_creator_keys):
    global txn_dependencies

    data_dir = config['PDO']['DataPath']

    ledger_config = config.get('Sawtooth')
    contract_creator_id = contract_creator_keys.identity

    contract_name = config['contract']
    contract_code = contract_helper.ContractCode.create_from_scheme_file(
        contract_name, search_path=[".", "..", "contracts"])

    # create the provisioning servers
    if use_pservice:
        pservice_urls = config.get("pservice-urls")
        provisioning_services = list(
            map(lambda url: pservice_helper.ProvisioningServiceClient(url),
                pservice_urls))
    else:
        provisioning_services = secret_helper.create_provisioning_services(
            config['secrets'])
    provisioning_service_keys = list(
        map(lambda svc: svc.identity, provisioning_services))

    try:
        if use_ledger:
            contract_id = contract_helper.register_contract(
                ledger_config, contract_creator_keys, contract_code,
                provisioning_service_keys)
            logger.info('contract registration successful; %s', contract_id)
        else:
            contract_id = crypto.byte_array_to_base64(
                crypto.compute_message_hash(crypto.random_bit_string(256)))
            logger.info('no ledger config; skipping contract registration')
    except Exception as e:
        logger.error('failed to register the contract; %s', str(e))
        sys.exit(-1)

    contract_state = contract_helper.ContractState.create_new_state(
        contract_id)
    contract = contract_helper.Contract(contract_code, contract_state,
                                        contract_id, contract_creator_id)

    # --------------------------------------------------
    logger.info('create the provisioning secrets')
    # --------------------------------------------------
    if use_pservice:
        secret_list = []
        for pservice in provisioning_services:
            logger.debug('ask pservice %s to generate a secret for %s',
                         pservice.ServiceURL, contract_id)
            message = enclave.enclave_id + contract_id
            signature = contract_creator_keys.sign(message, encoding='hex')
            secret = pservice.get_secret(enclave.enclave_id, contract_id,
                                         contract_creator_keys.verifying_key,
                                         signature)
            if secret is None:
                logger.error('failed to create secret for %s',
                             pservice.ServiceURL)
                sys.exit(-1)
            secret_list.append(secret)
    else:
        secret_list = secret_helper.create_secrets_for_services(
            provisioning_services, enclave.enclave_keys, contract_id,
            contract_creator_id)

    logger.debug('secrets: %s', secret_list)

    try:
        secretinfo = enclave.verify_secrets(contract_id, contract_creator_id,
                                            secret_list)
        assert secretinfo

        encrypted_state_encryption_key = secretinfo[
            'encrypted_state_encryption_key']
        signature = secretinfo['signature']

    except Exception as e:
        logger.error('failed to create the state encryption key; %s', str(e))
        sys.exit(-1)

    try:
        if not secrets.verify_state_encryption_key_signature(
                encrypted_state_encryption_key, secret_list, contract_id,
                contract_creator_id, signature, enclave.enclave_keys):
            raise RuntimeError('signature verification failed')
    except Exception as e:
        logger.error('failed to verify the state encryption key; %s', str(e))
        sys.exit(-1)

    logger.info('encrypted state encryption key: %s',
                encrypted_state_encryption_key)

    # --------------------------------------------------
    logger.info('add the provisioned enclave to the contract')
    # --------------------------------------------------
    try:
        if use_ledger:
            txnid = contract_helper.add_enclave_to_contract(
                ledger_config,
                contract_creator_keys,
                contract_id,
                enclave.enclave_id,
                secret_list,
                encrypted_state_encryption_key,
                signature,
                transaction_dependency_list=txn_dependencies)
            txn_dependencies = [txnid]

            logger.info('contract state encryption key added to contract')
        else:
            logger.info(
                'no ledger config; skipping state encryption key registration')
    except Exception as e:
        logger.error('failed to add state encryption key; %s', str(e))
        sys.exit(-1)

    contract.set_state_encryption_key(enclave.enclave_id,
                                      encrypted_state_encryption_key)
    contract.save_to_file(contract_name, data_dir=data_dir)

    # --------------------------------------------------
    logger.info('create the initial contract state')
    # --------------------------------------------------
    try:
        initialize_request = contract.create_initialize_request(
            contract_creator_keys, enclave)
        initialize_response = initialize_request.evaluate()
        contract.set_state(initialize_response.encrypted_state)

    except Exception as e:
        logger.error('failed to create the initial state; %s', str(e))
        sys.exit(-1)

    logger.info('enclave created initial state')

    # --------------------------------------------------
    logger.info('save the initial state in the ledger')
    # --------------------------------------------------
    try:
        if use_ledger:
            logger.info("sending to ledger")
            # note that we will wait for commit of the transaction before
            # continuing; this is not necessary in general (if there is
            # confidence the transaction will succeed) but is useful for
            # testing
            txnid = initialize_response.submit_initialize_transaction(
                ledger_config,
                wait=30,
                transaction_dependency_list=txn_dependencies)
            txn_dependencies = [txnid]
        else:
            logger.info('no ledger config; skipping iniatialize state save')
    except Exception as e:
        logger.error('failed to save the initial state; %s', str(e))
        sys.exit(-1)

    contract.contract_state.save_to_cache(data_dir=data_dir)

    return contract
예제 #4
0
def CreateAndRegisterContract(config, enclaves, contract_creator_keys):
    global txn_dependencies

    data_dir = config['Contract']['DataDirectory']

    ledger_config = config.get('Sawtooth')
    contract_creator_id = contract_creator_keys.identity

    try:
        contract_class = config['Contract']['Name']
        contract_source = config['Contract']['SourceFile']
        source_path = config['Contract']['SourceSearchPath']
        interpreter = config['Contract']['Interpreter']
        contract_code = contract_helper.ContractCode.create_from_file(
            contract_class,
            contract_source,
            source_path,
            interpreter=interpreter)
    except Exception as e:
        raise Exception('unable to load contract source; {0}'.format(str(e)))

    # create the provisioning servers
    if use_pservice:
        try:
            pservice_urls = config['Service']['ProvisioningServiceURLs']
            provisioning_services = list(
                map(lambda url: pservice_helper.ProvisioningServiceClient(url),
                    pservice_urls))
        except Exception as e:
            logger.error('failed to connect to provisioning service; %s',
                         str(e))
            ErrorShutdown()
    else:
        provisioning_services = secret_helper.create_provisioning_services(
            config['secrets'])
    provisioning_service_keys = list(
        map(lambda svc: svc.identity, provisioning_services))

    try:
        if use_ledger:
            contract_id = contract_helper.register_contract(
                ledger_config, contract_creator_keys, contract_code,
                provisioning_service_keys)
            logger.info('contract registration successful; %s', contract_id)
        else:
            contract_id = crypto.byte_array_to_base64(
                crypto.compute_message_hash(crypto.random_bit_string(256)))
            logger.debug('no ledger config; skipping contract registration')
    except Exception as e:
        logger.error('failed to register the contract; %s', str(e))
        ErrorShutdown()

    contract_state = contract_helper.ContractState.create_new_state(
        contract_id)
    contract = contract_helper.Contract(contract_code, contract_state,
                                        contract_id, contract_creator_id)

    # --------------------------------------------------
    logger.info('create the provisioning secrets')
    # --------------------------------------------------
    encrypted_state_encryption_keys = AddEnclaveSecrets(
        ledger_config, contract.contract_id, contract_creator_keys, enclaves,
        provisioning_services)

    for enclave_id in encrypted_state_encryption_keys:
        encrypted_key = encrypted_state_encryption_keys[enclave_id]
        contract.set_state_encryption_key(enclave_id, encrypted_key)

    #add replication information to contract
    AddReplicationParamsToContract(config, enclaves, contract)

    # 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]

    # save the contract info as a pdo file
    contract_save_file = '_' + contract.short_id + '.pdo'
    contract.save_to_file(contract_save_file, data_dir=data_dir)

    # --------------------------------------------------
    logger.info('create the initial contract state')
    # --------------------------------------------------
    try:
        initialize_request = contract.create_initialize_request(
            contract_creator_keys, enclave_to_use)
        initialize_response = initialize_request.evaluate()
        if initialize_response.status is False:
            logger.error('contract initialization failed: %s',
                         initialize_response.invocation_response)
            ErrorShutdown()

        contract.set_state(initialize_response.raw_state)

    except Exception as e:
        logger.error('failed to create the initial state; %s', str(e))
        ErrorShutdown()

    logger.info('Created initial state')

    # submit the commit task: (a commit task replicates change-set and submits the corresponding transaction)
    try:
        initialize_response.commit_asynchronously(ledger_config)
    except Exception as e:
        logger.exception(
            'failed to asynchronously start replication and transaction submission:'
            + str(e))
        ErrorShutdown()

    # wait for the commit to finish.
    try:
        txn_id = initialize_response.wait_for_commit()
        if use_ledger and txn_id is None:
            logger.error("Did not receive txn id for the initial commit")
            ErrorShutdown()
    except Exception as e:
        logger.error(str(e))
        ErrorShutdown()

    contract.contract_state.save_to_cache(data_dir=data_dir)

    return contract
def command_create(state, bindings, pargs):
    """controller command to create a contract
    """
    default_interpreter = state.get(['Contract', 'Interpreter'])
    default_replicas = state.get(['Replication', 'NumProvableReplicas'], 2)
    default_duration = state.get(['Replication', 'Duration'], 120)

    parser = argparse.ArgumentParser(prog='create')
    parser.add_argument('-c',
                        '--contract-class',
                        help='Name of the contract class',
                        required=False,
                        type=str)
    parser.add_argument('-e',
                        '--eservice-group',
                        help='Name of the enclave service group to use',
                        default="default")
    parser.add_argument('-f',
                        '--save-file',
                        help='File where contract data is stored',
                        type=str)
    parser.add_argument('-i',
                        '--interpreter',
                        help='Interpreter used to evaluate the contract',
                        default=default_interpreter)
    parser.add_argument('-p',
                        '--pservice-group',
                        help='Name of the provisioning service group to use',
                        default="default")
    parser.add_argument('-s',
                        '--contract-source',
                        help='File that contains contract source code',
                        required=True,
                        type=str)

    parser.add_argument('--symbol', help='binding symbol for result', type=str)
    parser.add_argument('--state-replicas',
                        help='Number of authoritative replicas of the state',
                        default=default_replicas)
    parser.add_argument('--state-duration',
                        help='Duration required for state replicas',
                        default=default_duration)
    parser.add_argument(
        '--extra-data',
        help='Simple string that can save extra data with the contract file',
        type=str)

    options = parser.parse_args(pargs)

    contract_class = options.contract_class
    contract_source = options.contract_source

    # ---------- load the invoker's keys ----------
    try:
        keyfile = state.private_key_file
        keypath = state.get(['Key', 'SearchPath'])
        client_keys = ServiceKeys.read_from_file(keyfile, keypath)
    except Exception as e:
        raise Exception('unable to load client keys; {0}'.format(str(e)))

    # ---------- read the contract source code ----------
    try:
        source_path = state.get(['Contract', 'SourceSearchPath'])
        contract_code = ContractCode.create_from_file(
            contract_class,
            contract_source,
            source_path,
            interpreter=options.interpreter)
    except Exception as e:
        raise Exception('unable to load contract source; {0}'.format(str(e)))

    logger.debug('Loaded contract code for %s', contract_class)

    # ---------- set up the enclave clients ----------
    eservice_clients = get_eservice_list(state, options.eservice_group)
    if len(eservice_clients) == 0:
        raise Exception('unable to locate enclave services in the group %s',
                        options.eservice_group)

    preferred_eservice_client = get_eservice(
        state, eservice_group=options.eservice_group)
    if preferred_eservice_client.interpreter != options.interpreter:
        raise Exception(
            'enclave interpreter does not match requested contract interpreter %s',
            options.interpreter)

    # ---------- set up the provisioning service clients ----------
    pservice_clients = get_pservice_list(state, options.pservice_group)
    if len(pservice_clients) == 0:
        raise Exception(
            'unable to locate provisioning services in the group %s',
            options.pservice_group)

    # ---------- register contract ----------
    data_directory = state.get(['Contract', 'DataDirectory'])
    ledger_config = state.get(['Ledger'])

    try:
        extra_params = {
            'num_provable_replicas': options.state_replicas,
            'availability_duration': options.state_duration,
        }

        if options.extra_data:
            extra_params['extra_data'] = options.extra_data

        provisioning_service_keys = [pc.identity for pc in pservice_clients]
        contract_id = register_contract(ledger_config, client_keys,
                                        contract_code,
                                        provisioning_service_keys)

        logger.debug('Registered contract with class %s and id %s',
                     contract_class, contract_id)
        contract_state = ContractState.create_new_state(contract_id)
        contract = Contract(contract_code, contract_state, contract_id,
                            client_keys.identity, **extra_params)

        # must fix this later
        contract.extra_data[
            'preferred-enclave'] = preferred_eservice_client.enclave_id

        contract_file = "{0}_{1}.pdo".format(contract_class, contract.short_id)
        if options.save_file:
            contract_file = options.save_file

        contract.save_to_file(contract_file, data_dir=data_directory)

    except Exception as e:
        raise Exception('failed to register the contract; {0}'.format(str(e)))

    # provision the encryption keys to all of the enclaves
    try:
        encrypted_state_encryption_keys = __add_enclave_secrets(
            ledger_config, contract.contract_id, client_keys, eservice_clients,
            pservice_clients)

        for enclave_id in encrypted_state_encryption_keys:
            encrypted_key = encrypted_state_encryption_keys[enclave_id]
            contract.set_state_encryption_key(enclave_id, encrypted_key)

        contract.save_to_file(contract_file, data_dir=data_directory)
    except Exception as e:
        raise Exception('failed to provisioning the enclaves; {0}'.format(
            str(e)))

    # create the initial contract state
    try:
        __create_contract(ledger_config, client_keys,
                          preferred_eservice_client, eservice_clients,
                          contract)

        contract.save_to_file(contract_file, data_dir=data_directory)
    except Exception as e:
        raise Exception(
            'failed to create the initial contract state; {0}'.format(str(e)))

    if contract_id and options.symbol:
        bindings.bind(options.symbol, contract_id)
예제 #6
0
def CreateAndRegisterContract(config, contract_info, creator_keys):
    ledger_config = config.get('Sawtooth')
    contract_config = config.get('Contract')

    contract_creator_id = creator_keys.identity

    contract_name = contract_info['Name']
    source_file = contract_info['Source']
    search_path = contract_config['SourceSearchPath']
    contract_code = ContractCode.create_from_scheme_file(
        contract_name, source_file, search_path=search_path)

    # --------------------------------------------------
    logger.info('register the contract')
    # --------------------------------------------------
    pservice_urls = contract_info.get("ProvisioningServices")
    provisioning_services = list(
        map(lambda url: ProvisioningServiceClient(url), pservice_urls))
    provisioning_service_keys = list(
        map(lambda svc: svc.identity, provisioning_services))

    contract_id = register_contract(ledger_config, creator_keys, contract_code,
                                    provisioning_service_keys)
    logger.info('registered the contract as %s', contract_id)

    contract_state = ContractState.create_new_state(contract_id)
    contract = Contract(contract_code, contract_state, contract_id,
                        contract_creator_id)

    # --------------------------------------------------
    logger.info('provision enclaves')
    # --------------------------------------------------
    eservice_urls = contract_info.get("EnclaveServices")
    enclave_services = list(
        map(lambda url: GetEnclaveServiceByURL(url), eservice_urls))

    for eservice in enclave_services:
        secret_list = []
        for pservice in provisioning_services:
            message = pcrypto.string_to_byte_array(eservice.enclave_id +
                                                   contract_id)
            signature = creator_keys.sign(message)
            secret = pservice.get_secret(eservice.enclave_id, contract_id,
                                         creator_keys.verifying_key, signature)
            secret_list.append(secret)

        secretinfo = eservice.verify_secrets(contract_id, contract_creator_id,
                                             secret_list)
        encrypted_state_encryption_key = secretinfo[
            'encrypted_state_encryption_key']
        signature = secretinfo['signature']

        txnid = add_enclave_to_contract(ledger_config, creator_keys,
                                        contract_id, eservice.enclave_id,
                                        secret_list,
                                        encrypted_state_encryption_key,
                                        signature)

        contract.set_state_encryption_key(eservice.enclave_id,
                                          encrypted_state_encryption_key)

    # --------------------------------------------------
    logger.info('create the initial contract state')
    # --------------------------------------------------
    eservice = random.choice(enclave_services)
    initialize_request = contract.create_initialize_request(
        creator_keys, eservice)
    initialize_response = initialize_request.evaluate()
    if initialize_response.status is False:
        emessage = initialize_response.result
        logger.warn('initialization for contract %s failed; %s', contract_name,
                    emessage)
        raise Exception('initialization failed; {}'.format(emessage))

    contract.set_state(initialize_response.encrypted_state)

    logger.info('initial state created')

    # --------------------------------------------------
    logger.info('save the initial state in the ledger')
    # --------------------------------------------------
    txnid = initialize_response.submit_initialize_transaction(ledger_config,
                                                              wait=30)

    return contract
예제 #7
0
def command_create(state, bindings, pargs) :
    """controller command to create a contract
    """

    parser = argparse.ArgumentParser(prog='create')
    parser.add_argument('-c', '--contract-class', help='Name of the contract class', required = True, type=str)
    parser.add_argument('-s', '--contract-source', help='File that contains contract source code', required=True, type=str)
    parser.add_argument('-f', '--save-file', help='File where contract data is stored', type=str)
    options = parser.parse_args(pargs)

    contract_class = options.contract_class
    contract_source = options.contract_source

    contract_file = "{0}.pdo".format(contract_class)
    if options.save_file :
        contract_file = options.save_file

    # ---------- load the invoker's keys ----------
    try :
        keyfile = state.get(['Key', 'FileName'])
        keypath = state.get(['Key', 'SearchPath'])
        client_keys = ServiceKeys.read_from_file(keyfile, keypath)
    except Exception as e :
        raise Exception('unable to load client keys; {0}'.format(str(e)))

    # ---------- read the contract source code ----------
    try :
        source_path = state.get(['Contract', 'SourceSearchPath'])
        contract_code = ContractCode.create_from_scheme_file(contract_class, contract_source, source_path)
    except Exception as e :
        raise Exception('unable to load contract source; {0}'.format(str(e)))

    logger.info('Loaded contract code for %s', contract_class)

    # ---------- set up the enclave clients ----------
    try :
        eservice_urls = state.get(['Service', 'EnclaveServiceURLs'], [])
        if len(eservice_urls) == 0 :
            raise Exception('no enclave services specified')

        enclaveclients = []
        for url in eservice_urls :
            enclaveclients.append(EnclaveServiceClient(url))
    except Exception as e :
        raise Exception('unable to contact enclave services; {0}'.format(str(e)))

    # ---------- set up the provisioning service clients ----------
    # This is a dictionary of provisioning service public key : client pairs
    try :
        pservice_urls = state.get(['Service', 'ProvisioningServiceURLs'])
        if len(pservice_urls) == 0 :
            raise Exception('no provisioning services specified')

        provclients = []
        for url in pservice_urls :
            provclients.append(ProvisioningServiceClient(url))
    except Exception as e :
        raise Exception('unable to contact provisioning services; {0}'.format(str(e)))

    # ---------- register contract ----------
    data_directory = state.get(['Contract', 'DataDirectory'])
    ledger_config = state.get(['Sawtooth'])

    try :
        provisioning_service_keys = [pc.identity for pc in provclients]
        contract_id = register_contract(
            ledger_config, client_keys, contract_code, provisioning_service_keys)

        logger.info('Registered contract with class %s and id %s', contract_class, contract_id)
        contract_state = ContractState.create_new_state(contract_id)
        contract = Contract(contract_code, contract_state, contract_id, client_keys.identity)
        contract.save_to_file(contract_file, data_dir=data_directory)
    except Exception as e :
        raise Exception('failed to register the contract; {0}'.format(str(e)))

    # provision the encryption keys to all of the enclaves
    try :
        encrypted_state_encryption_keys = __add_enclave_secrets(
            ledger_config, contract.contract_id, client_keys, enclaveclients, provclients)

        for enclave_id in encrypted_state_encryption_keys :
            encrypted_key = encrypted_state_encryption_keys[enclave_id]
            contract.set_state_encryption_key(enclave_id, encrypted_key)

        contract.save_to_file(contract_file, data_dir=data_directory)
    except Exception as e :
        raise Exception('failed to provisioning the enclaves; {0}'.format(str(e)))

    # create the initial contract state
    try :
        __create_contract(ledger_config, client_keys, enclaveclients, contract)

        contract.contract_state.save_to_cache(data_dir = data_directory)
        contract.save_to_file(contract_file, data_dir=data_directory)
    except Exception as e :
        raise Exception('failed to create the initial contract state; {0}'.format(str(e)))
예제 #8
0
파일: create.py 프로젝트: cmickeyb/toxaway
def Create(config, client_profile, contract_name, contract_code, eservices,
           pservices):
    """
    client_profile -- toxaway.models.profile.Profile
    contract_code -- toxaway.models.contract_code.ContractCode
    eservices -- toxaway.models.eservice.EnclaveServiceList
    pservices -- toxaway.models.pservice.ProvisioningServiceList
    """

    ledger_config = config['Sawtooth']
    contract_config = config['ContentPaths']
    state_directory = contract_config['State']

    client_keys = client_profile.keys
    provisioning_service_keys = list(pservices.identities())

    try:
        pdo_code_object = contract_code.create_pdo_contract()
    except Exception as e:
        logger.error('failed to create the contract object; %s', str(e))
        return None

    try:
        pdo_contract_id = register_contract(ledger_config, client_keys,
                                            pdo_code_object,
                                            provisioning_service_keys)

        logger.info('Registered contract %s with id %s', contract_code.name,
                    pdo_contract_id)
        pdo_contract_state = ContractState.create_new_state(pdo_contract_id)
        contract = Contract(pdo_code_object, pdo_contract_state,
                            pdo_contract_id, client_keys.identity)
    except Exception as e:
        logger.error('failed to register the contract; %s', str(e))
        return None

    logger.info('Contract created')

    enclaveclients = []
    for eservice in eservices:
        enclaveclients.append(eservice.eservice_client)

    provclients = []
    for pservice in pservices:
        provclients.append(pservice.pservice_client)

    encrypted_state_encryption_keys = AddEnclaveSecrets(
        ledger_config, pdo_contract_id, client_keys, enclaveclients,
        provclients)

    for enclave_id in encrypted_state_encryption_keys:
        encrypted_key = encrypted_state_encryption_keys[enclave_id]
        contract.set_state_encryption_key(enclave_id, encrypted_key)

    CreateContract(ledger_config, client_keys, enclaveclients, contract)

    contract.contract_state.save_to_cache(data_dir=state_directory)
    logger.info('state saved to cache')

    with tempfile.NamedTemporaryFile() as pdo_temp:
        contract.save_to_file(pdo_temp.name)
        toxaway_contract = toxaway.models.contract.Contract.import_contract(
            config, pdo_temp, contract_name)

    return toxaway_contract