Пример #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)
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)