Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make --execution_address and --eth1_withdrawal_address compatible alias #339

Merged
merged 1 commit into from
Mar 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ You can use `new-mnemonic --help` to see all arguments. Note that if there are m
| `--mnemonic_language` | String. Options: `简体中文`, `繁體中文`, `český jazyk`, `English`, `Italiano`, `한국어`, `Português`, `Español`. Default to `English` | The language of the mnemonic word list |
| `--folder` | String. Pointing to `./validator_keys` by default | The folder path for the keystore(s) and deposit(s) |
| `--chain` | String. `mainnet` by default | The chain setting for the signing domain. |
| `--eth1_withdrawal_address` | String. Eth1 address in hexadecimal encoded form | If this field is set and valid, the given Eth1 address will be used to create the withdrawal credentials. Otherwise, it will generate withdrawal credentials with the mnemonic-derived withdrawal public key in [ERC-2334 format](https://eips.ethereum.org/EIPS/eip-2334#eth2-specific-parameters). |
| `--execution_address` (or `--eth1_withdrawal_address`) | String. Eth1 address in hexadecimal encoded form | If this field is set and valid, the given Eth1 address will be used to create the withdrawal credentials. Otherwise, it will generate withdrawal credentials with the mnemonic-derived withdrawal public key in [ERC-2334 format](https://eips.ethereum.org/EIPS/eip-2334#eth2-specific-parameters). |

###### `existing-mnemonic` Arguments

Expand All @@ -161,7 +161,7 @@ You can use `existing-mnemonic --help` to see all arguments. Note that if there
| `--num_validators` | Non-negative integer | The number of new signing keys you want to generate. Note that the child key(s) are generated via the same master key. |
| `--folder` | String. Pointing to `./validator_keys` by default | The folder path for the keystore(s) and deposit(s) |
| `--chain` | String. `mainnet` by default | The chain setting for the signing domain. |
| `--eth1_withdrawal_address` | String. Eth1 address in hexadecimal encoded form | If this field is set and valid, the given Eth1 address will be used to create the withdrawal credentials. Otherwise, it will generate withdrawal credentials with the mnemonic-derived withdrawal public key in [ERC-2334 format](https://eips.ethereum.org/EIPS/eip-2334#eth2-specific-parameters). |
| `--execution_address` (or `--eth1_withdrawal_address`) | String. Eth1 address in hexadecimal encoded form | If this field is set and valid, the given Eth1 address will be used to create the withdrawal credentials. Otherwise, it will generate withdrawal credentials with the mnemonic-derived withdrawal public key in [ERC-2334 format](https://eips.ethereum.org/EIPS/eip-2334#eth2-specific-parameters). |

###### Successful message

Expand Down Expand Up @@ -191,7 +191,7 @@ You can use `bls-to-execution-change --help` to see all arguments. Note that if
| `--validator_start_index` | Non-negative integer | The index position for the keys to start generating withdrawal credentials in [ERC-2334 format](https://eips.ethereum.org/EIPS/eip-2334#eth2-specific-parameters). |
| `--validator_indices` | String of integer(s) | A list of the chosen validator index number(s) as identified on the beacon chain. Split multiple items with whitespaces or commas. |
| `--bls_withdrawal_credentials_list` | String of hexstring(s). | A list of the old BLS withdrawal credentials of the given validator(s). It is for confirming you are using the correct keys. Split multiple items with whitespaces or commas. |
| `--execution_address` | String. 20-byte Execution (Eth1) address in hexadecimal encoded form | The execution (Eth1) address you want to change to for withdrawals. |
| `--execution_address` (or `--eth1_withdrawal_address`) | String. Eth1 address in hexadecimal encoded form | If this field is set and valid, the given Eth1 address will be used to create the withdrawal credentials. Otherwise, it will generate withdrawal credentials with the mnemonic-derived withdrawal public key in [ERC-2334 format](https://eips.ethereum.org/EIPS/eip-2334#eth2-specific-parameters). |
| `--devnet_chain_setting` | String. JSON string `'{"network_name": "<NETWORK_NAME>", "genesis_fork_version": "<GENESIS_FORK_VERSION>", "genesis_validator_root": "<GENESIS_VALIDATOR_ROOT>"}'` | The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. |

#### Option 2. Build `deposit-cli` with native Python
Expand Down
2 changes: 1 addition & 1 deletion staking_deposit/cli/generate_bls_to_execution_change.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def get_password(text: str) -> str:
lambda: load_text(['arg_execution_address', 'mismatch'], func=FUNC_NAME),
),
help=lambda: load_text(['arg_execution_address', 'help'], func=FUNC_NAME),
param_decls='--execution_address',
param_decls=['--execution_address', '--eth1_withdrawal_address'],
prompt=lambda: load_text(['arg_execution_address', 'prompt'], func=FUNC_NAME),
)
@jit_option(
Expand Down
6 changes: 3 additions & 3 deletions staking_deposit/cli/generate_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def generate_keys_arguments_decorator(function: Callable[..., Any]) -> Callable[
),
default=None,
help=lambda: load_text(['arg_execution_address', 'help'], func='generate_keys_arguments_decorator'),
param_decls='--eth1_withdrawal_address',
param_decls=['--execution_address', '--eth1_withdrawal_address'],
),
]
for decorator in reversed(decorators):
Expand All @@ -114,7 +114,7 @@ def generate_keys_arguments_decorator(function: Callable[..., Any]) -> Callable[
@click.pass_context
def generate_keys(ctx: click.Context, validator_start_index: int,
num_validators: int, folder: str, chain: str, keystore_password: str,
eth1_withdrawal_address: HexAddress, **kwargs: Any) -> None:
execution_address: HexAddress, **kwargs: Any) -> None:
mnemonic = ctx.obj['mnemonic']
mnemonic_password = ctx.obj['mnemonic_password']
amounts = [MAX_DEPOSIT_AMOUNT] * num_validators
Expand All @@ -132,7 +132,7 @@ def generate_keys(ctx: click.Context, validator_start_index: int,
amounts=amounts,
chain_setting=chain_setting,
start_index=validator_start_index,
hex_eth1_withdrawal_address=eth1_withdrawal_address,
hex_eth1_withdrawal_address=execution_address,
)
keystore_filefolders = credentials.export_keystores(password=keystore_password, folder=folder)
deposits_file = credentials.export_deposit_data_json(folder=folder)
Expand Down
8 changes: 6 additions & 2 deletions staking_deposit/utils/click.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class JITOption(click.Option):
'''
def __init__(
self,
param_decls: str,
param_decls: Union[str, Sequence[str]],
default: Union[Callable[[], Any], None, Any] = None,
help: Union[Callable[[], str], str, None] = None,
prompt: Union[Callable[[], str], str, None] = None,
Expand All @@ -36,8 +36,12 @@ def __init__(
self.callable_help = help
self.callable_prompt = prompt

# `click.Option.Argument.param_decls` takes a list of flags or argument names.
if isinstance(param_decls, str):
param_decls = [_value_of(param_decls)]

return super().__init__(
param_decls=[_value_of(param_decls)],
param_decls=param_decls,
default=_value_of(default),
help=_value_of(help),
prompt=_value_of(prompt),
Expand Down
87 changes: 87 additions & 0 deletions tests/test_cli/test_new_mnemonic.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,93 @@ def mock_get_mnemonic(language, words_path, entropy=None) -> str:
clean_key_folder(my_folder_path)


def test_new_mnemonic_eth1_address_withdrawal_alias(monkeypatch) -> None:
# monkeypatch get_mnemonic
def mock_get_mnemonic(language, words_path, entropy=None) -> str:
return "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"

monkeypatch.setattr(new_mnemonic, "get_mnemonic", mock_get_mnemonic)

# Prepare folder
my_folder_path = os.path.join(os.getcwd(), 'TESTING_TEMP_FOLDER')
clean_key_folder(my_folder_path)
if not os.path.exists(my_folder_path):
os.mkdir(my_folder_path)

runner = CliRunner()
execution_address = '0x00000000219ab540356cBB839Cbe05303d7705Fa'
inputs = [execution_address, 'english', '1', 'mainnet', 'MyPassword', 'MyPassword',
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about']
data = '\n'.join(inputs)
arguments = [
'--language', 'english',
'new-mnemonic',
'--folder', my_folder_path,
'--execution_address', execution_address, # execution_address and eth1_withdrawal_address are aliases
]
result = runner.invoke(cli, arguments, input=data)
assert result.exit_code == 0

# Check files
validator_keys_folder_path = os.path.join(my_folder_path, DEFAULT_VALIDATOR_KEYS_FOLDER_NAME)
_, _, key_files = next(os.walk(validator_keys_folder_path))

deposit_file = [key_file for key_file in key_files if key_file.startswith('deposit_data')][0]
with open(validator_keys_folder_path + '/' + deposit_file, 'r') as f:
deposits_dict = json.load(f)
for deposit in deposits_dict:
withdrawal_credentials = bytes.fromhex(deposit['withdrawal_credentials'])
assert withdrawal_credentials == (
ETH1_ADDRESS_WITHDRAWAL_PREFIX + b'\x00' * 11 + decode_hex(execution_address)
)

all_uuid = [
get_uuid(validator_keys_folder_path + '/' + key_file)
for key_file in key_files
if key_file.startswith('keystore')
]
assert len(set(all_uuid)) == 1

# Verify file permissions
if os.name == 'posix':
for file_name in key_files:
assert get_permissions(validator_keys_folder_path, file_name) == '0o440'

# Clean up
clean_key_folder(my_folder_path)


def test_new_mnemonic_eth1_address_withdrawal_double_params(monkeypatch) -> None:
# monkeypatch get_mnemonic
def mock_get_mnemonic(language, words_path, entropy=None) -> str:
return "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"

monkeypatch.setattr(new_mnemonic, "get_mnemonic", mock_get_mnemonic)

# Prepare folder
my_folder_path = os.path.join(os.getcwd(), 'TESTING_TEMP_FOLDER')
clean_key_folder(my_folder_path)
if not os.path.exists(my_folder_path):
os.mkdir(my_folder_path)

runner = CliRunner()
execution_address = '0x00000000219ab540356cBB839Cbe05303d7705Fa'
inputs = [execution_address, 'english', '1', 'mainnet', 'MyPassword', 'MyPassword',
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about']
data = '\n'.join(inputs)
arguments = [
'--language', 'english',
'new-mnemonic',
'--folder', my_folder_path,
'--execution_address', execution_address,
'--eth1_withdrawal_address', execution_address, # double param
]
result = runner.invoke(cli, arguments, input=data)

# FIXME: Should not allow it
assert result.exit_code == 0


@pytest.mark.asyncio
async def test_script_bls_withdrawal() -> None:
# Prepare folder
Expand Down