Beispiel #1
0
def custom_config_filepath(custom_filepath):
    filepath = os.path.join(custom_filepath,
                            UrsulaConfiguration.generate_filename())
    return filepath
Beispiel #2
0
def worker_configuration_file_location(custom_filepath):
    _configuration_file_location = os.path.join(
        MOCK_CUSTOM_INSTALLATION_PATH, UrsulaConfiguration.generate_filename())
    return _configuration_file_location
Beispiel #3
0
def test_persistent_node_storage_integration(click_runner, custom_filepath,
                                             testerchain, blockchain_ursulas,
                                             agency_local_registry):

    alice, ursula, another_ursula, felix, staker, *all_yall = testerchain.unassigned_accounts
    filename = UrsulaConfiguration.generate_filename()
    another_ursula_configuration_file_location = os.path.join(
        custom_filepath, filename)

    init_args = (
        'ursula',
        'init',
        '--provider',
        TEST_PROVIDER_URI,
        '--worker-address',
        another_ursula,
        '--network',
        TEMPORARY_DOMAIN,
        '--rest-host',
        MOCK_IP_ADDRESS,
        '--config-root',
        custom_filepath,
        '--registry-filepath',
        agency_local_registry.filepath,
    )

    envvars = {NUCYPHER_ENVVAR_KEYRING_PASSWORD: INSECURE_DEVELOPMENT_PASSWORD}
    result = click_runner.invoke(nucypher_cli,
                                 init_args,
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0

    teacher = blockchain_ursulas.pop()
    teacher_uri = teacher.rest_information()[0].uri

    start_pytest_ursula_services(ursula=teacher)

    user_input = f'{INSECURE_DEVELOPMENT_PASSWORD}\n'

    run_args = ('ursula', 'run', '--dry-run', '--debug', '--interactive',
                '--config-file', another_ursula_configuration_file_location,
                '--teacher', teacher_uri)

    Worker.BONDING_TIMEOUT = 1
    with pytest.raises(Teacher.UnbondedWorker):
        # Worker init success, but not bonded.
        result = yield threads.deferToThread(click_runner.invoke,
                                             nucypher_cli,
                                             run_args,
                                             catch_exceptions=False,
                                             input=user_input,
                                             env=envvars)
    assert result.exit_code == 0

    # Run an Ursula amidst the other configuration files
    run_args = ('ursula', 'run', '--dry-run', '--debug', '--interactive',
                '--config-file', another_ursula_configuration_file_location)

    with pytest.raises(Teacher.UnbondedWorker):
        # Worker init success, but not bonded.
        result = yield threads.deferToThread(click_runner.invoke,
                                             nucypher_cli,
                                             run_args,
                                             catch_exceptions=False,
                                             input=user_input,
                                             env=envvars)
    assert result.exit_code == 0
def test_corrupted_configuration(click_runner, custom_filepath, testerchain,
                                 agency_local_registry):

    #
    # Setup
    #

    # Please tell me why
    if custom_filepath.exists():
        shutil.rmtree(custom_filepath, ignore_errors=True)
    assert not custom_filepath.exists()

    alice, ursula, another_ursula, felix, staker, *all_yall = testerchain.unassigned_accounts

    #
    # Chaos
    #

    init_args = (
        'ursula',
        'init',
        '--provider',
        TEST_PROVIDER_URI,
        '--worker-address',
        another_ursula,
        '--network',
        TEMPORARY_DOMAIN,
        '--rest-host',
        MOCK_IP_ADDRESS,
        '--config-root',
        custom_filepath,
    )

    # Fails because password is too short and the command uses incomplete args (needs either -F or blockchain details)
    envvars = {NUCYPHER_ENVVAR_KEYRING_PASSWORD: ''}

    with pytest.raises(NucypherKeyring.AuthenticationFailed):
        result = click_runner.invoke(nucypher_cli,
                                     init_args,
                                     catch_exceptions=False,
                                     env=envvars)
        assert result.exit_code != 0

    # Ensure there is no unintentional file creation (keys, config, etc.)
    top_level_config_root = os.listdir(custom_filepath)
    assert 'ursula.config' not in top_level_config_root  # no config file was created

    assert Path(custom_filepath).exists()
    keyring = custom_filepath / 'keyring'
    assert not keyring.exists()

    known_nodes = 'known_nodes'
    path = custom_filepath / known_nodes
    assert not path.exists()

    # Attempt installation again, with full args
    init_args = ('ursula', 'init', '--network', TEMPORARY_DOMAIN, '--provider',
                 TEST_PROVIDER_URI, '--worker-address', another_ursula,
                 '--rest-host', MOCK_IP_ADDRESS, '--registry-filepath',
                 agency_local_registry.filepath, '--config-root',
                 custom_filepath)

    envvars = {NUCYPHER_ENVVAR_KEYRING_PASSWORD: INSECURE_DEVELOPMENT_PASSWORD}
    result = click_runner.invoke(nucypher_cli,
                                 init_args,
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0

    default_filename = UrsulaConfiguration.generate_filename()

    # Ensure configuration creation
    top_level_config_root = os.listdir(custom_filepath)
    assert default_filename in top_level_config_root, "JSON configuration file was not created"
    assert len(os.listdir(
        custom_filepath / 'keyring' / 'private')) == 4  # keys were created
    for field in ['known_nodes', 'keyring', default_filename]:
        assert field in top_level_config_root

    # "Corrupt" the configuration by removing the contract registry
    os.remove(agency_local_registry.filepath)

    # Attempt destruction with invalid configuration (missing registry)
    ursula_file_location = custom_filepath / default_filename
    destruction_args = ('ursula', 'destroy', '--debug', '--config-file',
                        ursula_file_location)
    result = click_runner.invoke(nucypher_cli,
                                 destruction_args,
                                 input='Y\n',
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0

    # Ensure character destruction
    top_level_config_root = os.listdir(custom_filepath)
    assert default_filename not in top_level_config_root  # config file was destroyed
    assert len(os.listdir(
        custom_filepath / 'keyring' / 'private')) == 0  # keys were destroyed
def test_coexisting_configurations(click_runner, custom_filepath, testerchain,
                                   agency_local_registry):
    #
    # Setup
    #

    if custom_filepath.exists():
        shutil.rmtree(str(custom_filepath), ignore_errors=True)
    assert not custom_filepath.exists()

    # Parse node addresses
    # TODO: Is testerchain & Full contract deployment needed here (causes massive slowdown)?
    alice, ursula, another_ursula, felix, staker, *all_yall = testerchain.unassigned_accounts

    envvars = {
        NUCYPHER_ENVVAR_KEYRING_PASSWORD: INSECURE_DEVELOPMENT_PASSWORD,
        NUCYPHER_ENVVAR_ALICE_ETH_PASSWORD: INSECURE_DEVELOPMENT_PASSWORD,
        NUCYPHER_ENVVAR_BOB_ETH_PASSWORD: INSECURE_DEVELOPMENT_PASSWORD
    }

    # Future configuration filepaths for assertions...
    public_keys_dir = custom_filepath / 'keyring' / 'public'
    known_nodes_dir = custom_filepath / 'known_nodes'

    # ... Ensure they do not exist to begin with.

    # No keys have been generated...
    assert not public_keys_dir.exists()

    # No known nodes exist...
    assert not known_nodes_dir.exists()

    # Not the configuration root...
    assert not os.path.isdir(custom_filepath)

    # ... nothing
    None

    #
    # Create
    #

    # Expected config files
    felix_file_location = custom_filepath / FelixConfiguration.generate_filename(
    )
    alice_file_location = custom_filepath / AliceConfiguration.generate_filename(
    )
    ursula_file_location = custom_filepath / UrsulaConfiguration.generate_filename(
    )
    another_ursula_configuration_file_location = custom_filepath / UrsulaConfiguration.generate_filename(
        modifier=another_ursula)

    # Felix creates a system configuration
    felix_init_args = ('felix', 'init', '--config-root', custom_filepath,
                       '--network', TEMPORARY_DOMAIN, '--provider',
                       TEST_PROVIDER_URI, '--checksum-address', felix,
                       '--registry-filepath', agency_local_registry.filepath,
                       '--debug')

    result = click_runner.invoke(nucypher_cli,
                                 felix_init_args,
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0

    # All configuration files still exist.
    assert os.path.isdir(custom_filepath)
    assert os.path.isfile(felix_file_location)
    assert os.path.isdir(public_keys_dir)
    assert len(os.listdir(public_keys_dir)) == 3

    # Use a custom local filepath to init a persistent Alice
    alice_init_args = ('alice', 'init', '--network', TEMPORARY_DOMAIN,
                       '--provider', TEST_PROVIDER_URI, '--pay-with', alice,
                       '--registry-filepath', agency_local_registry.filepath,
                       '--config-root', custom_filepath)

    result = click_runner.invoke(nucypher_cli,
                                 alice_init_args,
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0

    # All configuration files still exist.
    assert os.path.isfile(felix_file_location)
    assert os.path.isfile(alice_file_location)
    assert len(os.listdir(public_keys_dir)) == 5

    # Use the same local filepath to init a persistent Ursula
    init_args = ('ursula', 'init', '--network', TEMPORARY_DOMAIN, '--provider',
                 TEST_PROVIDER_URI, '--worker-address', ursula, '--rest-host',
                 MOCK_IP_ADDRESS, '--registry-filepath',
                 agency_local_registry.filepath, '--config-root',
                 custom_filepath)

    result = click_runner.invoke(nucypher_cli,
                                 init_args,
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0, result.output

    # All configuration files still exist.
    assert len(os.listdir(public_keys_dir)) == 8
    assert os.path.isfile(felix_file_location)
    assert os.path.isfile(alice_file_location)
    assert os.path.isfile(ursula_file_location)

    # keyring signing key
    signing_public_key = SecretKey.random().public_key()
    with patch('nucypher.config.keyring.NucypherKeyring.signing_public_key',
               PropertyMock(return_value=signing_public_key)):
        # Use the same local filepath to init another persistent Ursula
        init_args = ('ursula', 'init', '--network', TEMPORARY_DOMAIN,
                     '--worker-address', another_ursula, '--rest-host',
                     MOCK_IP_ADDRESS_2, '--registry-filepath',
                     agency_local_registry.filepath, '--provider',
                     TEST_PROVIDER_URI, '--config-root', custom_filepath)

        result = click_runner.invoke(nucypher_cli,
                                     init_args,
                                     catch_exceptions=False,
                                     env=envvars)
        assert result.exit_code == 0

    another_ursula_configuration_file_location = custom_filepath / UrsulaConfiguration.generate_filename(
        modifier=bytes(signing_public_key).hex()[:8])

    # All configuration files still exist.
    assert os.path.isfile(felix_file_location)
    assert os.path.isfile(alice_file_location)
    assert os.path.isfile(another_ursula_configuration_file_location)
    assert os.path.isfile(ursula_file_location)
    assert len(os.listdir(public_keys_dir)) == 11

    #
    # Run
    #

    # Run an Ursula amidst the other configuration files
    run_args = ('ursula', 'run', '--dry-run', '--no-ip-checkup',
                '--config-file', another_ursula_configuration_file_location)

    user_input = f'{INSECURE_DEVELOPMENT_PASSWORD}\n' * 2

    Worker.READY_POLL_RATE = 1
    Worker.READY_TIMEOUT = 1
    with pytest.raises(Teacher.UnbondedWorker):
        # Worker init success, but not bonded.
        result = click_runner.invoke(nucypher_cli,
                                     run_args,
                                     input=user_input,
                                     catch_exceptions=False)
    assert result.exit_code == 0
    Worker.READY_TIMEOUT = None

    # All configuration files still exist.
    assert os.path.isfile(felix_file_location)
    assert os.path.isfile(alice_file_location)
    assert os.path.isfile(another_ursula_configuration_file_location)
    assert os.path.isfile(ursula_file_location)
    assert len(os.listdir(public_keys_dir)) == 11

    # Check that the proper Ursula console is attached
    assert another_ursula in result.output

    #
    # Destroy
    #

    another_ursula_destruction_args = (
        'ursula', 'destroy', '--force', '--config-file',
        another_ursula_configuration_file_location)
    result = click_runner.invoke(nucypher_cli,
                                 another_ursula_destruction_args,
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0
    assert len(os.listdir(public_keys_dir)) == 8
    assert not os.path.isfile(another_ursula_configuration_file_location)

    ursula_destruction_args = ('ursula', 'destroy', '--config-file',
                               ursula_file_location)
    result = click_runner.invoke(nucypher_cli,
                                 ursula_destruction_args,
                                 input='Y',
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0
    assert 'y/N' in result.output
    assert len(os.listdir(public_keys_dir)) == 5
    assert not os.path.isfile(ursula_file_location)

    alice_destruction_args = ('alice', 'destroy', '--force', '--config-file',
                              alice_file_location)
    result = click_runner.invoke(nucypher_cli,
                                 alice_destruction_args,
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0
    assert len(os.listdir(public_keys_dir)) == 3
    assert not os.path.isfile(alice_file_location)

    felix_destruction_args = ('felix', 'destroy', '--force', '--config-file',
                              felix_file_location)
    result = click_runner.invoke(nucypher_cli,
                                 felix_destruction_args,
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0
    assert len(os.listdir(public_keys_dir)) == 0
    assert not os.path.isfile(felix_file_location)
Beispiel #6
0
def worker_configuration_file_location(custom_filepath) -> Path:
    _configuration_file_location = MOCK_CUSTOM_INSTALLATION_PATH / UrsulaConfiguration.generate_filename(
    )
    return _configuration_file_location
def test_coexisting_configurations(click_runner, custom_filepath, testerchain,
                                   test_registry, agency):
    #
    # Setup
    #

    # Parse node addresses
    alice, ursula, another_ursula, felix, staker, *all_yall = testerchain.unassigned_accounts

    envvars = {
        'NUCYPHER_KEYRING_PASSWORD': INSECURE_DEVELOPMENT_PASSWORD,
        'NUCYPHER_FELIX_DB_SECRET': INSECURE_DEVELOPMENT_PASSWORD
    }

    # Future configuration filepaths for assertions...
    public_keys_dir = os.path.join(custom_filepath, 'keyring', 'public')
    known_nodes_dir = os.path.join(custom_filepath, 'known_nodes')

    # ... Ensure they do not exist to begin with.
    assert not os.path.isdir(public_keys_dir)
    assert not os.path.isfile(known_nodes_dir)

    # No keys have been generated...
    with pytest.raises(FileNotFoundError):
        assert len(os.listdir(public_keys_dir)) == 0

    # No known nodes exist...
    with pytest.raises(FileNotFoundError):
        assert len(os.listdir(known_nodes_dir)) == 0

    # Not the configuration root...
    assert not os.path.isdir(custom_filepath)

    #
    # Create
    #

    # Expected config files
    felix_file_location = os.path.join(custom_filepath,
                                       FelixConfiguration.generate_filename())
    alice_file_location = os.path.join(custom_filepath,
                                       AliceConfiguration.generate_filename())
    ursula_file_location = os.path.join(
        custom_filepath, UrsulaConfiguration.generate_filename())
    another_ursula_configuration_file_location = os.path.join(
        custom_filepath,
        UrsulaConfiguration.generate_filename(modifier=another_ursula))

    # Felix creates a system configuration
    felix_init_args = ('felix', 'init', '--config-root', custom_filepath,
                       '--network', TEMPORARY_DOMAIN, '--provider',
                       TEST_PROVIDER_URI, '--checksum-address', felix,
                       '--registry-filepath', MOCK_REGISTRY_FILEPATH,
                       '--debug')

    result = click_runner.invoke(nucypher_cli,
                                 felix_init_args,
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0

    # All configuration files still exist.
    assert os.path.isdir(custom_filepath)
    assert os.path.isfile(felix_file_location)
    assert os.path.isdir(public_keys_dir)
    assert len(os.listdir(public_keys_dir)) == 3

    # Use a custom local filepath to init a persistent Alice
    alice_init_args = ('alice', 'init', '--network', TEMPORARY_DOMAIN,
                       '--provider', TEST_PROVIDER_URI, '--pay-with', alice,
                       '--registry-filepath', MOCK_REGISTRY_FILEPATH,
                       '--config-root', custom_filepath)

    result = click_runner.invoke(nucypher_cli,
                                 alice_init_args,
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0

    # All configuration files still exist.
    assert os.path.isfile(felix_file_location)
    assert os.path.isfile(alice_file_location)
    assert len(os.listdir(public_keys_dir)) == 5

    # Use the same local filepath to init a persistent Ursula
    init_args = ('ursula', 'init', '--network', TEMPORARY_DOMAIN, '--provider',
                 TEST_PROVIDER_URI, '--worker-address', ursula,
                 '--staker-address', staker, '--rest-host', MOCK_IP_ADDRESS,
                 '--registry-filepath', MOCK_REGISTRY_FILEPATH,
                 '--config-root', custom_filepath)

    result = click_runner.invoke(nucypher_cli,
                                 init_args,
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0

    # All configuration files still exist.
    assert len(os.listdir(public_keys_dir)) == 8
    assert os.path.isfile(felix_file_location)
    assert os.path.isfile(alice_file_location)
    assert os.path.isfile(ursula_file_location)

    # Use the same local filepath to init another persistent Ursula
    init_args = ('ursula', 'init', '--network', TEMPORARY_DOMAIN,
                 '--worker-address', another_ursula, '--staker-address',
                 staker, '--rest-host', MOCK_IP_ADDRESS_2,
                 '--registry-filepath', MOCK_REGISTRY_FILEPATH, '--provider',
                 TEST_PROVIDER_URI, '--config-root', custom_filepath)

    result = click_runner.invoke(nucypher_cli,
                                 init_args,
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0

    # All configuration files still exist.
    assert os.path.isfile(felix_file_location)
    assert os.path.isfile(alice_file_location)
    assert os.path.isfile(another_ursula_configuration_file_location)
    assert os.path.isfile(ursula_file_location)
    assert len(os.listdir(public_keys_dir)) == 11

    #
    # Run
    #

    # Run an Ursula amidst the other configuration files
    run_args = ('ursula', 'run', '--dry-run', '--interactive', '--config-file',
                another_ursula_configuration_file_location)

    user_input = f'{INSECURE_DEVELOPMENT_PASSWORD}\n' * 2
    with pytest.raises(Teacher.DetachedWorker):
        # Worker init success, but unassigned.
        result = click_runner.invoke(nucypher_cli,
                                     run_args,
                                     input=user_input,
                                     catch_exceptions=False)
    assert result.exit_code == 0

    # All configuration files still exist.
    assert os.path.isfile(felix_file_location)
    assert os.path.isfile(alice_file_location)
    assert os.path.isfile(another_ursula_configuration_file_location)
    assert os.path.isfile(ursula_file_location)
    assert len(os.listdir(public_keys_dir)) == 11

    # Check that the proper Ursula console is attached
    assert another_ursula in result.output

    #
    # Destroy
    #

    another_ursula_destruction_args = (
        'ursula', 'destroy', '--force', '--config-file',
        another_ursula_configuration_file_location)
    result = click_runner.invoke(nucypher_cli,
                                 another_ursula_destruction_args,
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0
    assert len(os.listdir(public_keys_dir)) == 8
    assert not os.path.isfile(another_ursula_configuration_file_location)

    ursula_destruction_args = ('ursula', 'destroy', '--config-file',
                               ursula_file_location)
    result = click_runner.invoke(nucypher_cli,
                                 ursula_destruction_args,
                                 input='Y',
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0
    assert 'y/N' in result.output
    assert len(os.listdir(public_keys_dir)) == 5
    assert not os.path.isfile(ursula_file_location)

    alice_destruction_args = ('alice', 'destroy', '--force', '--config-file',
                              alice_file_location)
    result = click_runner.invoke(nucypher_cli,
                                 alice_destruction_args,
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0
    assert len(os.listdir(public_keys_dir)) == 3
    assert not os.path.isfile(alice_file_location)

    felix_destruction_args = ('felix', 'destroy', '--force', '--config-file',
                              felix_file_location)
    result = click_runner.invoke(nucypher_cli,
                                 felix_destruction_args,
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0
    assert len(os.listdir(public_keys_dir)) == 0
    assert not os.path.isfile(felix_file_location)
def test_corrupted_configuration(click_runner, custom_filepath, testerchain):
    alice, ursula, another_ursula, felix, staker, *all_yall = testerchain.unassigned_accounts

    init_args = (
        'ursula',
        'init',
        '--provider',
        TEST_PROVIDER_URI,
        '--worker-address',
        another_ursula,
        '--staker-address',
        staker,
        '--network',
        TEMPORARY_DOMAIN,
        '--rest-host',
        MOCK_IP_ADDRESS,
        '--config-root',
        custom_filepath,
    )

    # Fails because password is too short and the command uses incomplete args (needs either -F or blockchain details)
    envvars = {'NUCYPHER_KEYRING_PASSWORD': ''}

    with pytest.raises(NucypherKeyring.AuthenticationFailed):
        result = click_runner.invoke(nucypher_cli,
                                     init_args,
                                     catch_exceptions=False,
                                     env=envvars)
        assert result.exit_code != 0

    # Ensure there is no unintentional file creation (keys, config, etc.)
    top_level_config_root = os.listdir(custom_filepath)
    assert 'ursula.config' not in top_level_config_root  # no config file was created
    assert not os.listdir(os.path.join(custom_filepath, 'keyring',
                                       'private'))  # no keys were created
    for field in ['known_nodes', 'keyring']:
        assert field in top_level_config_root  # only the empty default directories
        path = os.path.join(custom_filepath, field)
        assert os.path.isdir(path)
        assert len(os.listdir(path)) == 2  # public and private directories

    # Attempt installation again, with full args
    init_args = ('ursula', 'init', '--network', TEMPORARY_DOMAIN, '--provider',
                 TEST_PROVIDER_URI, '--worker-address', another_ursula,
                 '--staker-address', staker, '--rest-host', MOCK_IP_ADDRESS,
                 '--registry-filepath', MOCK_REGISTRY_FILEPATH,
                 '--config-root', custom_filepath)

    envvars = {'NUCYPHER_KEYRING_PASSWORD': INSECURE_DEVELOPMENT_PASSWORD}
    result = click_runner.invoke(nucypher_cli,
                                 init_args,
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0

    default_filename = UrsulaConfiguration.generate_filename()

    # Ensure configuration creation
    top_level_config_root = os.listdir(custom_filepath)
    assert default_filename in top_level_config_root, "JSON configuration file was not created"
    assert len(os.listdir(os.path.join(custom_filepath, 'keyring',
                                       'private'))) == 4  # keys were created
    for field in ['known_nodes', 'keyring', default_filename]:
        assert field in top_level_config_root

    # "Corrupt" the configuration by removing the contract registry
    os.remove(MOCK_REGISTRY_FILEPATH)

    # Attempt destruction with invalid configuration (missing registry)
    ursula_file_location = os.path.join(custom_filepath, default_filename)
    destruction_args = ('ursula', '--debug', 'destroy', '--config-file',
                        ursula_file_location)
    result = click_runner.invoke(nucypher_cli,
                                 destruction_args,
                                 input='Y\n',
                                 catch_exceptions=False,
                                 env=envvars)
    assert result.exit_code == 0

    # Ensure character destruction
    top_level_config_root = os.listdir(custom_filepath)
    assert default_filename not in top_level_config_root  # config file was destroyed
    assert len(os.listdir(os.path.join(custom_filepath, 'keyring',
                                       'private'))) == 0  # keys were destroyed
def test_ursula_and_local_keystore_signer_integration(
        click_runner, tmp_path, manual_staker, stake_value, token_economics,
        mocker, mock_funded_account_password_keystore, testerchain):
    config_root_path = tmp_path
    ursula_config_path = config_root_path / UrsulaConfiguration.generate_filename(
    )
    stakeholder_config_path = config_root_path / StakeHolderConfiguration.generate_filename(
    )
    worker_account, password, mock_keystore_path = mock_funded_account_password_keystore

    #
    # Stakeholder Steps
    #

    init_args = ('stake', 'init-stakeholder', '--config-root',
                 config_root_path, '--provider', TEST_PROVIDER_URI,
                 '--network', TEMPORARY_DOMAIN)
    click_runner.invoke(nucypher_cli, init_args, catch_exceptions=False)

    stake_args = ('stake', 'create', '--config-file', stakeholder_config_path,
                  '--staking-address', manual_staker, '--value',
                  stake_value.to_tokens(), '--lock-periods',
                  token_economics.minimum_locked_periods, '--force')
    # TODO: Is This test is writing to the default system directory and ignoring updates to the passed filepath?
    user_input = f'0\n{password}\nY\n'
    click_runner.invoke(nucypher_cli,
                        stake_args,
                        input=user_input,
                        catch_exceptions=False)

    init_args = ('stake', 'bond-worker', '--config-file',
                 stakeholder_config_path, '--staking-address', manual_staker,
                 '--worker-address', worker_account.address, '--force')
    user_input = password
    click_runner.invoke(nucypher_cli,
                        init_args,
                        input=user_input,
                        catch_exceptions=False)

    #
    # Worker Steps
    #

    # Good signer...
    mock_signer_uri = f'keystore:{mock_keystore_path}'
    pre_config_signer = KeystoreSigner.from_signer_uri(uri=mock_signer_uri)
    assert worker_account.address in pre_config_signer.accounts

    init_args = (
        'ursula',
        'init',
        '--network',
        TEMPORARY_DOMAIN,
        '--worker-address',
        worker_account.address,
        '--config-root',
        config_root_path,
        '--provider',
        TEST_PROVIDER_URI,
        '--rest-host',
        MOCK_IP_ADDRESS,
        '--rest-port',
        MOCK_URSULA_STARTING_PORT,

        # The bit we are testing for here
        '--signer',
        mock_signer_uri)

    cli_env = {
        NUCYPHER_ENVVAR_KEYRING_PASSWORD: password,
        NUCYPHER_ENVVAR_WORKER_ETH_PASSWORD: password,
    }
    result = click_runner.invoke(nucypher_cli,
                                 init_args,
                                 catch_exceptions=False,
                                 env=cli_env)
    assert result.exit_code == 0, result.stdout

    # Inspect the configuration file for the signer URI
    with open(ursula_config_path, 'r') as config_file:
        raw_config_data = config_file.read()
        config_data = json.loads(raw_config_data)
        assert config_data['signer_uri'] == mock_signer_uri,\
            "Keystore URI was not correctly included in configuration file"

    # Recreate a configuration with the signer URI preserved
    ursula_config = UrsulaConfiguration.from_configuration_file(
        ursula_config_path)
    assert ursula_config.signer_uri == mock_signer_uri

    # Mock decryption of web3 client keyring
    mocker.patch.object(Account,
                        'decrypt',
                        return_value=worker_account.privateKey)
    ursula_config.attach_keyring(checksum_address=worker_account.address)
    ursula_config.keyring.unlock(password=password)

    # Produce an ursula with a Keystore signer correctly derived from the signer URI, and dont do anything else!
    mocker.patch.object(StakeList, 'refresh', autospec=True)
    ursula = ursula_config.produce(client_password=password,
                                   block_until_ready=False)

    # Verify the keystore path is still preserved
    assert isinstance(ursula.signer, KeystoreSigner)
    assert isinstance(ursula.signer.path, str), "Use str"
    assert ursula.signer.path == str(mock_keystore_path)

    # Show that we can produce the exact same signer as pre-config...
    assert pre_config_signer.path == ursula.signer.path

    # ...and that transactions are signed by the keytore signer
    receipt = ursula.commit_to_next_period()
    transaction_data = testerchain.client.w3.eth.getTransaction(
        receipt['transactionHash'])
    assert transaction_data['from'] == worker_account.address
Beispiel #10
0
def custom_config_filepath(custom_filepath: Path):
    filepath = custom_filepath / UrsulaConfiguration.generate_filename()
    return filepath