mirror of https://github.com/nucypher/nucypher.git
Increases correctness, accuracy and density of information provided to CLI users running initialization commands.
parent
0c33c154d9
commit
3e37a106b3
|
@ -317,8 +317,40 @@ def init(general_config, config_options, force, config_root, key_material):
|
|||
"""Create a new Ursula node configuration."""
|
||||
emitter = setup_emitter(general_config, config_options.operator_address)
|
||||
_pre_launch_warnings(emitter, dev=None, force=force)
|
||||
|
||||
if not config_root:
|
||||
config_root = general_config.config_root
|
||||
|
||||
config_path = Path(config_root)
|
||||
keystore_path = config_path / Keystore._DEFAULT_DIR
|
||||
if config_path.exists() and keystore_path.exists():
|
||||
click.clear()
|
||||
emitter.echo(
|
||||
f"There are existing secret keys in '{keystore_path}'.\n"
|
||||
"The 'init' command is a one-time operation, do not run it again.\n\n",
|
||||
color="red",
|
||||
)
|
||||
|
||||
emitter.echo(
|
||||
"To review your existing configuration, run:\n\n"
|
||||
"nucypher ursula config\n\n"
|
||||
"To run your node with the existing configuration, run:\n\n"
|
||||
"nucypher ursula run\n",
|
||||
color="cyan",
|
||||
)
|
||||
return click.get_current_context().exit(1)
|
||||
|
||||
click.clear()
|
||||
emitter.echo(
|
||||
"Hello Operator, welcome on board :-) \n\n"
|
||||
"NOTE: Initializing a new Ursula node configuration is a one-time operation\n"
|
||||
"for the lifetime of your node. This is a two-step process:\n\n"
|
||||
"1. Creating a password to encrypt your operator keys\n"
|
||||
"2. Securing a taco node seed phase\n\n"
|
||||
"Please follow the prompts.",
|
||||
color="cyan",
|
||||
)
|
||||
|
||||
if not config_options.eth_endpoint:
|
||||
raise click.BadOptionUsage(
|
||||
"--eth-endpoint",
|
||||
|
|
|
@ -53,8 +53,8 @@ DEFAULT_TO_LONE_CONFIG_FILE = "Defaulting to {config_class} configuration file:
|
|||
|
||||
# Authentication
|
||||
PASSWORD_COLLECTION_NOTICE = """
|
||||
Please provide a password to lock Operator keys.
|
||||
Do not forget this password, and ideally store it using a password manager.
|
||||
Please provide a password to encrypt your node's private keys.
|
||||
Do not forget this password. Ideally generate and store this password using a password manager.
|
||||
"""
|
||||
|
||||
COLLECT_ETH_PASSWORD = "Enter ethereum account password ({checksum_address})"
|
||||
|
|
|
@ -3,6 +3,7 @@ from constant_sorrow.constants import NO_KEYSTORE_ATTACHED
|
|||
|
||||
from nucypher.characters.banners import NUCYPHER_BANNER
|
||||
from nucypher.config.constants import DEFAULT_CONFIG_ROOT, USER_LOG_DIR
|
||||
from nucypher.crypto.powers import RitualisticPower
|
||||
|
||||
|
||||
def echo_version(ctx, param, value):
|
||||
|
@ -30,17 +31,21 @@ def paint_new_installation_help(emitter, new_configuration, filepath):
|
|||
character_config_class = new_configuration.__class__
|
||||
character_name = character_config_class.NAME.lower()
|
||||
if new_configuration.keystore != NO_KEYSTORE_ATTACHED:
|
||||
maybe_public_key = new_configuration.keystore.id
|
||||
ritual_power = new_configuration.keystore.derive_crypto_power(RitualisticPower)
|
||||
ferveo_public_key = bytes(ritual_power.public_key()).hex()
|
||||
maybe_public_key = f"{ferveo_public_key[:8]}...{ferveo_public_key[-8:]}"
|
||||
else:
|
||||
maybe_public_key = "(no keystore attached)"
|
||||
|
||||
emitter.message("Generated keystore", color="green")
|
||||
emitter.message(
|
||||
f"""
|
||||
|
||||
Public Key: {maybe_public_key}
|
||||
DKG Public Key: {maybe_public_key}
|
||||
Path to Keystore: {new_configuration.keystore_dir}
|
||||
Path to Config: {filepath}
|
||||
Path to Logs: {USER_LOG_DIR}
|
||||
|
||||
- You can share your public key with anyone. Others need it to interact with you.
|
||||
- Never share secret keys with anyone!
|
||||
- Backup your keystore! Character keys are required to interact with the protocol!
|
||||
- Remember your password! Without the password, it's impossible to decrypt the key!
|
||||
|
@ -48,18 +53,6 @@ Path to Keystore: {new_configuration.keystore_dir}
|
|||
"""
|
||||
)
|
||||
|
||||
default_config_filepath = True
|
||||
if new_configuration.default_filepath() != filepath:
|
||||
default_config_filepath = False
|
||||
emitter.message(f'Generated configuration file at {"default" if default_config_filepath else "non-default"} '
|
||||
f'filepath {filepath}', color='green')
|
||||
|
||||
# add hint about --config-file
|
||||
if not default_config_filepath:
|
||||
emitter.message(f'* NOTE: for a non-default configuration filepath use `--config-file "{filepath}"` '
|
||||
f'with subsequent `{character_name}` CLI commands', color='yellow')
|
||||
|
||||
# Ursula
|
||||
if character_name == 'ursula':
|
||||
hint = '''
|
||||
* Review configuration -> nucypher ursula config
|
||||
|
|
|
@ -593,6 +593,7 @@ class CharacterConfiguration(BaseConfiguration):
|
|||
"""Shortcut: Hook-up a new initial installation and configuration."""
|
||||
node_config = cls(dev_mode=False, *args, **kwargs)
|
||||
node_config.initialize(key_material=key_material, password=password)
|
||||
node_config.keystore.unlock(password)
|
||||
return node_config
|
||||
|
||||
def cleanup(self) -> None:
|
||||
|
|
|
@ -380,20 +380,49 @@ class Keystore:
|
|||
|
||||
# notification
|
||||
emitter = StdoutEmitter()
|
||||
emitter.message(
|
||||
"Backup your seed words, you will not be able to view them again.\n"
|
||||
|
||||
emitter.echo(
|
||||
"\nNOTE: Next, you will be assigned a taco node seed phase. This seed phase is used to\n"
|
||||
"generate your keystore. You will need this seed phase to recover your keystore\n"
|
||||
"in the future. Please write down the seed phase and keep it in a safe place.\n",
|
||||
color="cyan",
|
||||
)
|
||||
emitter.message(f"{__words}\n", color="cyan")
|
||||
|
||||
emitter.message(
|
||||
"IMPORTANT: Backup your seed phrase, you will not be able to view them again.\n"
|
||||
"You can use these words to restore your keystore in the future in case of loss of\n"
|
||||
"your keystore files or password. Do not share these words with anyone.\n",
|
||||
color="yellow",
|
||||
)
|
||||
|
||||
emitter.message(
|
||||
"WARNING: If you lose your seed phase and also lose access to your keystore/password "
|
||||
"your stake will be slashed.\n",
|
||||
color="red",
|
||||
)
|
||||
click.confirm("Reveal seed phase?", default=False, abort=True)
|
||||
click.clear()
|
||||
|
||||
formatted_words = "\n".join(
|
||||
f"{i} {w}" for i, w in enumerate(__words.split(), start=1)
|
||||
)
|
||||
emitter.message(f"{formatted_words}\n", color="green")
|
||||
if not click.confirm("Have you backed up your seed phrase?"):
|
||||
emitter.message('Keystore generation aborted.', color='red')
|
||||
raise click.Abort()
|
||||
click.clear()
|
||||
|
||||
# confirmation
|
||||
__response = click.prompt("Confirm seed words")
|
||||
if __response != __words:
|
||||
raise ValueError('Incorrect seed word confirmation. No keystore has been created, try again.')
|
||||
while True:
|
||||
__response = click.prompt("Confirm seed words (space separated)")
|
||||
if __response != __words:
|
||||
emitter.message(
|
||||
"Seed words do not match. Please try again.", color="red"
|
||||
)
|
||||
continue
|
||||
break
|
||||
click.clear()
|
||||
emitter.echo("Seed phrase confirmed. Generating keystore...", color="green")
|
||||
|
||||
@property
|
||||
def id(self) -> str:
|
||||
|
|
Loading…
Reference in New Issue