mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2024-11-10 02:26:47 +03:00
chia keys show --json (display all keys as json) (#13637)
* chia keys show --json (display all keys as json) * black (linting) chia keys show --json (display all keys as json) * output a root object containing the keys array * support key with empty label * add test_show_json and test_show_mnemonic_json to test_keys * chia keys show --json -- do not format json output * tests/core/cmds/test_keys.py -- result.output.find(<value>) != -1 * tests/core/cmds/test_keys.py -- result.output.find(<value>) != -1 -- black * Pass root_path in show_all_keys and fix tests Co-authored-by: Jeff Cruikshank <jeff@chia.net>
This commit is contained in:
parent
769d9e2e2f
commit
a3c4c2367a
@ -54,10 +54,19 @@ def generate_cmd(ctx: click.Context, label: Optional[str]):
|
||||
show_default=True,
|
||||
is_flag=True,
|
||||
)
|
||||
def show_cmd(show_mnemonic_seed, non_observer_derivation):
|
||||
@click.option(
|
||||
"--json",
|
||||
"-j",
|
||||
help=("Displays all the keys in keychain as JSON"),
|
||||
default=False,
|
||||
show_default=True,
|
||||
is_flag=True,
|
||||
)
|
||||
@click.pass_context
|
||||
def show_cmd(ctx: click.Context, show_mnemonic_seed, non_observer_derivation, json):
|
||||
from .keys_funcs import show_all_keys
|
||||
|
||||
show_all_keys(show_mnemonic_seed, non_observer_derivation)
|
||||
show_all_keys(ctx.obj["root_path"], show_mnemonic_seed, non_observer_derivation, json)
|
||||
|
||||
|
||||
@keys_cmd.command("add", short_help="Add a private key by mnemonic")
|
||||
|
@ -1,3 +1,4 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
@ -14,7 +15,6 @@ from chia.daemon.keychain_proxy import KeychainProxy, connect_to_keychain_and_va
|
||||
from chia.util.bech32m import encode_puzzle_hash
|
||||
from chia.util.errors import KeychainNotSet
|
||||
from chia.util.config import load_config
|
||||
from chia.util.default_root import DEFAULT_ROOT_PATH
|
||||
from chia.util.errors import KeychainException
|
||||
from chia.util.file_keyring import MAX_LABEL_LENGTH
|
||||
from chia.util.ints import uint32
|
||||
@ -126,51 +126,73 @@ def delete_key_label(fingerprint: int) -> None:
|
||||
sys.exit(f"Error: {e}")
|
||||
|
||||
|
||||
def show_all_keys(show_mnemonic: bool, non_observer_derivation: bool):
|
||||
def show_all_keys(root_path: Path, show_mnemonic: bool, non_observer_derivation: bool, json_output: bool):
|
||||
"""
|
||||
Prints all keys and mnemonics (if available).
|
||||
"""
|
||||
unlock_keyring()
|
||||
root_path = DEFAULT_ROOT_PATH
|
||||
config = load_config(root_path, "config.yaml")
|
||||
all_keys = Keychain().get_keys(True)
|
||||
selected = config["selected_network"]
|
||||
prefix = config["network_overrides"]["config"][selected]["address_prefix"]
|
||||
|
||||
if len(all_keys) == 0:
|
||||
print("There are no saved private keys")
|
||||
if json_output:
|
||||
print(json.dumps({"keys": []}))
|
||||
else:
|
||||
print("There are no saved private keys")
|
||||
return None
|
||||
msg = "Showing all public keys derived from your master seed and private key:"
|
||||
if show_mnemonic:
|
||||
msg = "Showing all public and private keys"
|
||||
print(msg)
|
||||
for key_data in all_keys:
|
||||
|
||||
if not json_output:
|
||||
msg = "Showing all public keys derived from your master seed and private key:"
|
||||
if show_mnemonic:
|
||||
msg = "Showing all public and private keys"
|
||||
print(msg)
|
||||
|
||||
def process_key_data(key_data):
|
||||
key = {}
|
||||
sk = key_data.private_key
|
||||
print("")
|
||||
if key_data.label is not None:
|
||||
print("Label:", key_data.label)
|
||||
print("Fingerprint:", key_data.fingerprint)
|
||||
print("Master public key (m):", key_data.public_key)
|
||||
print(
|
||||
"Farmer public key (m/12381/8444/0/0):",
|
||||
master_sk_to_farmer_sk(sk).get_g1(),
|
||||
)
|
||||
print("Pool public key (m/12381/8444/1/0):", master_sk_to_pool_sk(sk).get_g1())
|
||||
key["label"] = key_data.label
|
||||
|
||||
key["fingerprint"] = key_data.fingerprint
|
||||
key["master_pk"] = bytes(key_data.public_key).hex()
|
||||
key["farmer_pk"] = bytes(master_sk_to_farmer_sk(sk).get_g1()).hex()
|
||||
key["pool_pk"] = bytes(master_sk_to_pool_sk(sk).get_g1()).hex()
|
||||
first_wallet_sk: PrivateKey = (
|
||||
master_sk_to_wallet_sk(sk, uint32(0))
|
||||
if non_observer_derivation
|
||||
else master_sk_to_wallet_sk_unhardened(sk, uint32(0))
|
||||
)
|
||||
wallet_address: str = encode_puzzle_hash(create_puzzlehash_for_pk(first_wallet_sk.get_g1()), prefix)
|
||||
print(f"First wallet address{' (non-observer)' if non_observer_derivation else ''}: {wallet_address}")
|
||||
key["wallet_address"] = wallet_address
|
||||
key["non_observer"] = non_observer_derivation
|
||||
|
||||
if show_mnemonic:
|
||||
print("Master private key (m):", bytes(sk).hex())
|
||||
print(
|
||||
"First wallet secret key (m/12381/8444/2/0):",
|
||||
master_sk_to_wallet_sk(sk, uint32(0)),
|
||||
)
|
||||
mnemonic = bytes_to_mnemonic(key_data.entropy)
|
||||
print(" Mnemonic seed (24 secret words):")
|
||||
print(mnemonic)
|
||||
key["master_sk"] = bytes(sk).hex()
|
||||
key["wallet_sk"] = bytes(master_sk_to_wallet_sk(sk, uint32(0))).hex()
|
||||
key["mnemonic"] = bytes_to_mnemonic(key_data.entropy)
|
||||
return key
|
||||
|
||||
keys = map(process_key_data, all_keys)
|
||||
|
||||
if json_output:
|
||||
print(json.dumps({"keys": list(keys)}))
|
||||
else:
|
||||
for key in keys:
|
||||
print("")
|
||||
if "label" in key:
|
||||
print("Label:", key["label"])
|
||||
print("Fingerprint:", key["fingerprint"])
|
||||
print("Master public key (m):", key["master_pk"])
|
||||
print("Farmer public key (m/12381/8444/0/0):", key["farmer_pk"])
|
||||
print("Pool public key (m/12381/8444/1/0):", key["pool_pk"])
|
||||
print(f"First wallet address{' (non-observer)' if key['non_observer'] else ''}: {key['wallet_address']}")
|
||||
if show_mnemonic:
|
||||
print("Master private key (m):", key["master_sk"])
|
||||
print("First wallet secret key (m/12381/8444/2/0):", key["wallet_sk"])
|
||||
print(" Mnemonic seed (24 secret words):")
|
||||
print(key["mnemonic"])
|
||||
|
||||
|
||||
def delete(fingerprint: int):
|
||||
|
@ -1,9 +1,10 @@
|
||||
import json
|
||||
import os
|
||||
import pytest
|
||||
import re
|
||||
|
||||
from chia.cmds.chia import cli
|
||||
from chia.cmds.keys import delete_all_cmd, generate_and_print_cmd, show_cmd, sign_cmd, verify_cmd
|
||||
from chia.cmds.keys import delete_all_cmd, generate_and_print_cmd, sign_cmd, verify_cmd
|
||||
from chia.util.config import load_config
|
||||
from chia.util.file_keyring import FileKeyring
|
||||
from chia.util.keychain import KeyData, DEFAULT_USER, DEFAULT_SERVICE, Keychain, generate_mnemonic
|
||||
@ -358,7 +359,7 @@ class TestKeysCommands:
|
||||
else:
|
||||
assert label == key.label
|
||||
|
||||
def test_show(self, keyring_with_one_key):
|
||||
def test_show(self, keyring_with_one_key, tmp_path):
|
||||
"""
|
||||
Test that the `chia keys show` command shows the correct key.
|
||||
"""
|
||||
@ -367,13 +368,54 @@ class TestKeysCommands:
|
||||
|
||||
assert len(keychain.get_all_private_keys()) == 1
|
||||
|
||||
keys_root_path = keychain.keyring_wrapper.keys_root_path
|
||||
base_params = [
|
||||
"--no-force-legacy-keyring-migration",
|
||||
"--root-path",
|
||||
os.fspath(tmp_path),
|
||||
"--keys-root-path",
|
||||
os.fspath(keys_root_path),
|
||||
]
|
||||
runner = CliRunner()
|
||||
result: Result = runner.invoke(show_cmd, [])
|
||||
cmd_params = ["keys", "show"]
|
||||
# Generate a new config
|
||||
assert runner.invoke(cli, [*base_params, "init"]).exit_code == 0
|
||||
# Run the command
|
||||
result: Result = runner.invoke(cli, [*base_params, *cmd_params])
|
||||
|
||||
# assert result.exit_code == 0
|
||||
assert result.output.find(f"Fingerprint: {TEST_FINGERPRINT}") != 0
|
||||
assert result.output.find(f"Fingerprint: {TEST_FINGERPRINT}") != -1
|
||||
|
||||
def test_show_mnemonic(self, keyring_with_one_key):
|
||||
def test_show_json(self, keyring_with_one_key, tmp_path):
|
||||
"""
|
||||
Test that the `chia keys show --json` command shows the correct key.
|
||||
"""
|
||||
|
||||
keychain = keyring_with_one_key
|
||||
|
||||
assert len(keychain.get_all_private_keys()) == 1
|
||||
|
||||
keys_root_path = keychain.keyring_wrapper.keys_root_path
|
||||
base_params = [
|
||||
"--no-force-legacy-keyring-migration",
|
||||
"--root-path",
|
||||
os.fspath(tmp_path),
|
||||
"--keys-root-path",
|
||||
os.fspath(keys_root_path),
|
||||
]
|
||||
runner = CliRunner()
|
||||
cmd_params = ["keys", "show", "--json"]
|
||||
# Generate a new config
|
||||
assert runner.invoke(cli, [*base_params, "init"]).exit_code == 0
|
||||
# Run the command
|
||||
result: Result = runner.invoke(cli, [*base_params, *cmd_params])
|
||||
|
||||
json_result = json.loads(result.output)
|
||||
|
||||
# assert result.exit_code == 0
|
||||
assert json_result["keys"][0]["fingerprint"] == TEST_FINGERPRINT
|
||||
|
||||
def test_show_mnemonic(self, keyring_with_one_key, tmp_path):
|
||||
"""
|
||||
Test that the `chia keys show --show-mnemonic-seed` command shows the key's mnemonic seed.
|
||||
"""
|
||||
@ -382,13 +424,54 @@ class TestKeysCommands:
|
||||
|
||||
assert len(keychain.get_all_private_keys()) == 1
|
||||
|
||||
keys_root_path = keychain.keyring_wrapper.keys_root_path
|
||||
base_params = [
|
||||
"--no-force-legacy-keyring-migration",
|
||||
"--root-path",
|
||||
os.fspath(tmp_path),
|
||||
"--keys-root-path",
|
||||
os.fspath(keys_root_path),
|
||||
]
|
||||
runner = CliRunner()
|
||||
result: Result = runner.invoke(show_cmd, ["--show-mnemonic-seed"])
|
||||
cmd_params = ["keys", "show", "--show-mnemonic-seed"]
|
||||
# Generate a new config
|
||||
assert runner.invoke(cli, [*base_params, "init"]).exit_code == 0
|
||||
# Run the command
|
||||
result: Result = runner.invoke(cli, [*base_params, *cmd_params])
|
||||
|
||||
# assert result.exit_code == 0
|
||||
assert result.output.find(f"Fingerprint: {TEST_FINGERPRINT}") != 0
|
||||
assert result.output.find("Mnemonic: seed (24 secret words):") != 0
|
||||
assert result.output.find(TEST_MNEMONIC_SEED) != 0
|
||||
assert result.output.find(f"Fingerprint: {TEST_FINGERPRINT}") != -1
|
||||
assert result.output.find("Mnemonic seed (24 secret words):") != -1
|
||||
assert result.output.find(TEST_MNEMONIC_SEED) != -1
|
||||
|
||||
def test_show_mnemonic_json(self, keyring_with_one_key, tmp_path):
|
||||
"""
|
||||
Test that the `chia keys show --show-mnemonic-seed --json` command shows the key's mnemonic seed.
|
||||
"""
|
||||
|
||||
keychain = keyring_with_one_key
|
||||
|
||||
assert len(keychain.get_all_private_keys()) == 1
|
||||
|
||||
keys_root_path = keychain.keyring_wrapper.keys_root_path
|
||||
base_params = [
|
||||
"--no-force-legacy-keyring-migration",
|
||||
"--root-path",
|
||||
os.fspath(tmp_path),
|
||||
"--keys-root-path",
|
||||
os.fspath(keys_root_path),
|
||||
]
|
||||
runner = CliRunner()
|
||||
cmd_params = ["keys", "show", "--show-mnemonic-seed", "--json"]
|
||||
# Generate a new config
|
||||
assert runner.invoke(cli, [*base_params, "init"]).exit_code == 0
|
||||
# Run the command
|
||||
result: Result = runner.invoke(cli, [*base_params, *cmd_params])
|
||||
json_result = json.loads(result.output)
|
||||
|
||||
# assert result.exit_code == 0
|
||||
assert json_result["keys"][0]["fingerprint"] == TEST_FINGERPRINT
|
||||
assert json_result["keys"][0]["mnemonic"] == TEST_MNEMONIC_SEED
|
||||
|
||||
def test_add_interactive(self, tmp_path, empty_keyring):
|
||||
"""
|
||||
@ -545,7 +628,7 @@ class TestKeysCommands:
|
||||
result: Result = runner.invoke(generate_and_print_cmd, [])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert result.output.find("Mnemonic (24 secret words):") != 0
|
||||
assert result.output.find("Mnemonic (24 secret words):") != -1
|
||||
|
||||
def test_sign(self, keyring_with_one_key):
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user