Skip to content

Commit

Permalink
Merge pull request ethereum#339 from ethereum/execution-address-alias
Browse files Browse the repository at this point in the history
Make `--execution_address` and `--eth1_withdrawal_address` compatible alias
  • Loading branch information
CarlBeek authored Mar 14, 2023
2 parents 0fcaca4 + 7b07dc3 commit 8165d6d
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 9 deletions.
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

0 comments on commit 8165d6d

Please sign in to comment.