chia-blockchain/chia/cmds/keys_funcs.py

662 lines
24 KiB
Python
Raw Normal View History

[CLI] chia keys derive [wallet-address | child-key | search] (#9184) * Added chia keys derive (wallet-address | child-key) to display derived wallet addresses or public keys * Support for public key (unhardened) derivation * Fleshed out the search command. Can perform a substring search on wallet addresses, public, and private keys. Support for deriving private keys * Default to unhardened derivation. Added --hardened-derivation option. HD paths denote hardened derivation with a 'h' suffix at each index. * Added --no-progress to reduce output. Exit code indicates search success/failure. Option name cleanup. * chia keys derive search can now search for multiple terms * chia keys derive search can be restricted to searching pubkeys|privkeys|addresses|all * Allow child-key derivation rooted from an arbitrary HD path * Search derived keys rooted under an arbitrary HD path * LGTM fixes * Remove extra master_sk_to_wallet_sk_unhardened definition * Cleanup and fixed search output * Cleanup and comments * Added tests for `chia keys` commands * Using @pytest_asyncio.fixture to decorate empty_keyring() as suggested in pytest's output. * Set asyncio-mode to auto to address pytest warning * See if tests pass without checking exit status * Added chia init step to tests that direclty invoke the `cli` function * Explicitly add --root-path option to tests that run the `cli` function. * Tests fix * Re-enable checks against exit_code * More fine tuning to address CI failures * Changes to address naming and other feedback * Updated tests
2022-01-26 07:42:16 +03:00
import os
import sys
[CLI] chia keys derive [wallet-address | child-key | search] (#9184) * Added chia keys derive (wallet-address | child-key) to display derived wallet addresses or public keys * Support for public key (unhardened) derivation * Fleshed out the search command. Can perform a substring search on wallet addresses, public, and private keys. Support for deriving private keys * Default to unhardened derivation. Added --hardened-derivation option. HD paths denote hardened derivation with a 'h' suffix at each index. * Added --no-progress to reduce output. Exit code indicates search success/failure. Option name cleanup. * chia keys derive search can now search for multiple terms * chia keys derive search can be restricted to searching pubkeys|privkeys|addresses|all * Allow child-key derivation rooted from an arbitrary HD path * Search derived keys rooted under an arbitrary HD path * LGTM fixes * Remove extra master_sk_to_wallet_sk_unhardened definition * Cleanup and fixed search output * Cleanup and comments * Added tests for `chia keys` commands * Using @pytest_asyncio.fixture to decorate empty_keyring() as suggested in pytest's output. * Set asyncio-mode to auto to address pytest warning * See if tests pass without checking exit status * Added chia init step to tests that direclty invoke the `cli` function * Explicitly add --root-path option to tests that run the `cli` function. * Tests fix * Re-enable checks against exit_code * More fine tuning to address CI failures * Changes to address naming and other feedback * Updated tests
2022-01-26 07:42:16 +03:00
from blspy import AugSchemeMPL, G1Element, G2Element, PrivateKey
from enum import Enum
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple, Union
from chia.consensus.coinbase import create_puzzlehash_for_pk
from chia.util.bech32m import encode_puzzle_hash
from chia.util.config import load_config
from chia.util.default_root import DEFAULT_ROOT_PATH
from chia.util.ints import uint32
[CLI] chia keys derive [wallet-address | child-key | search] (#9184) * Added chia keys derive (wallet-address | child-key) to display derived wallet addresses or public keys * Support for public key (unhardened) derivation * Fleshed out the search command. Can perform a substring search on wallet addresses, public, and private keys. Support for deriving private keys * Default to unhardened derivation. Added --hardened-derivation option. HD paths denote hardened derivation with a 'h' suffix at each index. * Added --no-progress to reduce output. Exit code indicates search success/failure. Option name cleanup. * chia keys derive search can now search for multiple terms * chia keys derive search can be restricted to searching pubkeys|privkeys|addresses|all * Allow child-key derivation rooted from an arbitrary HD path * Search derived keys rooted under an arbitrary HD path * LGTM fixes * Remove extra master_sk_to_wallet_sk_unhardened definition * Cleanup and fixed search output * Cleanup and comments * Added tests for `chia keys` commands * Using @pytest_asyncio.fixture to decorate empty_keyring() as suggested in pytest's output. * Set asyncio-mode to auto to address pytest warning * See if tests pass without checking exit status * Added chia init step to tests that direclty invoke the `cli` function * Explicitly add --root-path option to tests that run the `cli` function. * Tests fix * Re-enable checks against exit_code * More fine tuning to address CI failures * Changes to address naming and other feedback * Updated tests
2022-01-26 07:42:16 +03:00
from chia.util.keychain import Keychain, bytes_to_mnemonic, generate_mnemonic, mnemonic_to_seed, unlocks_keyring
from chia.wallet.derive_keys import (
master_sk_to_farmer_sk,
master_sk_to_pool_sk,
master_sk_to_wallet_sk,
master_sk_to_wallet_sk_unhardened,
)
def generate_and_print():
"""
Generates a seed for a private key, and prints the mnemonic to the terminal.
"""
mnemonic = generate_mnemonic()
print("Generating private key. Mnemonic (24 secret words):")
print(mnemonic)
print("Note that this key has not been added to the keychain. Run chia keys add")
return mnemonic
Keyring passphrase protection (#7249) * Moved keyring handling into a KeyringWrapper class * Update click to 8.0.x for prompt_required support * Renamed KeyringWrapper to _KeyringWrapper * Expose password management options on Linux * CLI support for setting/removing a password * Global option for specifying the master password * Cache the password instead of setting on the context * Password bootstrapping during chia init * Tidying up _KeyringWraper's interface * Initial pass migrating the legacy keyring contents * Encryption/decryption of keyring.yaml contents * FileKeyring backend encrypts with ChaCha20Poly1305 * Tightened up keyring migration and initialization * Fixed issues identified by linters * Remove root_path from Keychain * Prevent double-migration if setting master passwd * KeyringWrapper tests are mostly complete * FileKeyring will now honor the service param * Tests for get/set/delete password * Formatting/commenting updates * Writer lock support with tests - WIP * keyring.yaml is now watched for modifications * Reader/Writer lock for get/delete password * Fixed linter issues * Reader lock tests * Formatting update * Hook up CHIA_ROOT support for KeychainWrapper * Quick fix to address test failures * Fixed failures when existing legacy keyring exists * Fixed test failures caused by reusing the same temp dir * keyring.yaml now lives in ~/.chia_keys by default. Can be overridden with CHIA_KEYS_ROOT or --keys-root-path * Fixed migration failure when setting a password (not using the default) * KeyringWrapper now uses supports_keyring_password to determine if a FileKeyring should be used. Patched tests to work regardless of whether supports_keyring_password return False * The daemon now takes a --have-gui option that will prevent calling check_keys() during startup. If the keyring is locked, we want the GUI to prompt for the password. * Added is_keyring_locked RPC call * Added 'unlock_keyring' RPC command * Added KeychainProxy and KeychainServer to handle RPC messages related to keyring operations. WalletNode no longer directly accesses the Keychain class. * Turn on macOS support for testing keyring passwords * Fixed get_key_for_fingerprint to use the ocal keychain if the platform doesn't need to remotely access the daemon's keychain. Fixed key reconstruction when sent over RPC. * Farmer now accesses the keychain over RPC * Fixes for linter issues and some restructuring to support tests that use setup_nodes.py * Couple of fixes to unblock the GUI from launching when a keyring password is set * Added a keychain RPC call for add_private_key() * Added remaining keychain proxy RPC calls for delete_key_by_fingerprint and delete_all_keys * Check for None when inspecting request arguments * Run check_keys after unlocking the keyring when the daemon is launched via GUI * Added check_keys RPC method. Fixed deserialization of key entropy in get_all_private_keys. This was preventing the GUI from being able to show key details. * Added get_first_private_key to keychain_server/proxy. create_plots now uses the keychain proxy when launched from the daemon. * Added a comment about KeychainProxy in chia plots check * Workaround import conflict when importing from 'tests.*' due to fasteners name conflict * Simulator now uses KeychainProxy if launched by the daemon. KeychainServer/Proxy now takes keychain user/testing params for testing scenarios. * Added "set_keyring_passphrase" RPC message * Reworking KeychainProxy usage to handle local keychain tests and RPC keychain tests. * Replace my prior usage of asyncio.run() with asyncio.get_event_loop().run_until_complete() * Silencing file_keyring logging for the moment. * Updated tests to use test keychains and appropriate BlockTools construction BlockTools should now be created with create_block_tools(_async) to handle async scenarios. Updated block_tools to be async compatible Updated fasteners to fix installation of top-level 'tests' in site-packages * Added 'remove_keyring_passphrase' RPC message to the daemon Minor tweak to TempKeyring to default to some test params * Fixed linter issues * Remove flake8 ignore statement now that the fasteners module has been updated * Some initial renaming changes: password -> passphrase * Fixed wallet RPC issue where get_key_for_fingerprint wasn't awaited-upon. Fixed legacy keyring initialization (for migration scenarios) * Fixed improperly merged file * Fixed linter issues. More renaming. * Updated spots that were still using an incorrect keychain call * Renamed use_password_cache, obtain_current_password * Renamed supports_keyring_password * Renamed has_master_password * Renamed has_cached_password, get_cached_master_password * Linter fixes * Renamed master_password_is_valid * Renamed set_cached_master_password * Renamed set_master_password * Renamed remove_master_password * Renamed has_cached_master_password * Renaming in file_keyring and keyring_wrapper Updated default keyring payload used for tests * Renamed get_password Other renaming updates * Renamed set_password Other renaming updates * Renamed remaining password occurrences (where appropriate) * password -> passphrase * Added tests for setting an emoji and Japanese master passphrase * Attempt to notify the daemon when a keyring passphrase is set/updated/removed * Missed one password -> passphrase replacement. * Fixed some file synchronization issues found when running tests on macOS * Adjusted timeout values for test_writer_lock_reacquisition_failure for macOS. * Removed logging statements previously added for debugging * Prompt for keyring passphrase up-front when launching a service. Changed --have-gui flag to --wait-for-unlock * Updated set_keyring_passphrase RPC message to fix optional current_passphrase param when the keyring is using the default passphrase. * Minor test cleanup to deduplicate some code. * Fixed regression when setting a new master passphrase * Minor refactoring and docs/commenting updates * Renaming password -> passphrase went too far. Keyring backends use password terminology for compatibility with third party backends. * Disabling macOS support (previously added for testing only) * Disabling passphrase support in preparation for sending out the PR * Fixed improper merge (vscode didn't save changes during rebase) * Update chia/cmds/init_funcs.py Co-authored-by: Adam Kelly <338792+aqk@users.noreply.github.com> * skip_check_keys -> should_check_keys * Shuffling some imports around to break cycles reported by LGTM * Handle unlocking the daemon if it's already launched and waiting for unlock. * Replaced uses_keychain_proxy decorator in farmer.py. Fixed async usage of get_reward_targets. Linter/reformatting fixes * Replaced uses_keychain_proxy decorator with a clearer method. * Cleanup the temp keyring dir using shutil.rmtree() * Restored self._root_path (had been changed to self.root_path) * Minor cleanup * ensure_keychain_proxy() now throws if connect_to_keychain_and_validate() fails * Plot key resolution now yields a PlotKeys object which can be passed into create_plots. De-indented test_invalid_icc_sub_slot_vdf to keep git blame tidy. * Added 'keyring_status' daemon RPC message to support the GUI * Minor changes relating to PR feedback * Addressed more PR feedback (mostly type annotations) * Commented-out macOS file keyring usage. This can be re-enabled for testing purposes. * Addressed test failures that require multiple keyrings in the same process. Each TempKeyring will now set a custom KeyringWrapper instance. * Fixed logic for communicating user_passphrase_is_set in the keyring_status RPC response. * Updated type annotations and method signature for set_passphrase to expect a string instead of bytes. * Fixed Wallet RPC tests * Fixed full_node_store tests. BlockTools should be created using the create_block_tools(_async) function(s) * Fixed test failures in test_pool_rpc * Fixed test_daemon. After BlockTools.setup_plots is run, the config file needs to be re-read to refresh stale plot_directories. * Suppressing LGTM false positives regarding passphrase leakage in CLI error output. Seems that LGTM sees MIN_PASSPHRASE_LEN as sensitive data. * Second attempt at suppressing LGTM false positives * Third attempt at addressing LGTM false positives * Removed test_keyring_wrapper param from Keychain ctor. Test setup now sets the keyring_wrapper property directly. * Reformatting * More targeted update of the test config to refresh just the "plot_directories" value * More LGTM suppressions Co-authored-by: Adam Kelly <338792+aqk@users.noreply.github.com> Co-authored-by: wjblanke <wjb98672@gmail.com>
2021-08-04 22:46:55 +03:00
@unlocks_keyring(use_passphrase_cache=True)
def generate_and_add():
"""
Generates a seed for a private key, prints the mnemonic to the terminal, and adds the key to the keyring.
"""
mnemonic = generate_mnemonic()
print("Generating private key")
add_private_key_seed(mnemonic)
Keyring passphrase protection (#7249) * Moved keyring handling into a KeyringWrapper class * Update click to 8.0.x for prompt_required support * Renamed KeyringWrapper to _KeyringWrapper * Expose password management options on Linux * CLI support for setting/removing a password * Global option for specifying the master password * Cache the password instead of setting on the context * Password bootstrapping during chia init * Tidying up _KeyringWraper's interface * Initial pass migrating the legacy keyring contents * Encryption/decryption of keyring.yaml contents * FileKeyring backend encrypts with ChaCha20Poly1305 * Tightened up keyring migration and initialization * Fixed issues identified by linters * Remove root_path from Keychain * Prevent double-migration if setting master passwd * KeyringWrapper tests are mostly complete * FileKeyring will now honor the service param * Tests for get/set/delete password * Formatting/commenting updates * Writer lock support with tests - WIP * keyring.yaml is now watched for modifications * Reader/Writer lock for get/delete password * Fixed linter issues * Reader lock tests * Formatting update * Hook up CHIA_ROOT support for KeychainWrapper * Quick fix to address test failures * Fixed failures when existing legacy keyring exists * Fixed test failures caused by reusing the same temp dir * keyring.yaml now lives in ~/.chia_keys by default. Can be overridden with CHIA_KEYS_ROOT or --keys-root-path * Fixed migration failure when setting a password (not using the default) * KeyringWrapper now uses supports_keyring_password to determine if a FileKeyring should be used. Patched tests to work regardless of whether supports_keyring_password return False * The daemon now takes a --have-gui option that will prevent calling check_keys() during startup. If the keyring is locked, we want the GUI to prompt for the password. * Added is_keyring_locked RPC call * Added 'unlock_keyring' RPC command * Added KeychainProxy and KeychainServer to handle RPC messages related to keyring operations. WalletNode no longer directly accesses the Keychain class. * Turn on macOS support for testing keyring passwords * Fixed get_key_for_fingerprint to use the ocal keychain if the platform doesn't need to remotely access the daemon's keychain. Fixed key reconstruction when sent over RPC. * Farmer now accesses the keychain over RPC * Fixes for linter issues and some restructuring to support tests that use setup_nodes.py * Couple of fixes to unblock the GUI from launching when a keyring password is set * Added a keychain RPC call for add_private_key() * Added remaining keychain proxy RPC calls for delete_key_by_fingerprint and delete_all_keys * Check for None when inspecting request arguments * Run check_keys after unlocking the keyring when the daemon is launched via GUI * Added check_keys RPC method. Fixed deserialization of key entropy in get_all_private_keys. This was preventing the GUI from being able to show key details. * Added get_first_private_key to keychain_server/proxy. create_plots now uses the keychain proxy when launched from the daemon. * Added a comment about KeychainProxy in chia plots check * Workaround import conflict when importing from 'tests.*' due to fasteners name conflict * Simulator now uses KeychainProxy if launched by the daemon. KeychainServer/Proxy now takes keychain user/testing params for testing scenarios. * Added "set_keyring_passphrase" RPC message * Reworking KeychainProxy usage to handle local keychain tests and RPC keychain tests. * Replace my prior usage of asyncio.run() with asyncio.get_event_loop().run_until_complete() * Silencing file_keyring logging for the moment. * Updated tests to use test keychains and appropriate BlockTools construction BlockTools should now be created with create_block_tools(_async) to handle async scenarios. Updated block_tools to be async compatible Updated fasteners to fix installation of top-level 'tests' in site-packages * Added 'remove_keyring_passphrase' RPC message to the daemon Minor tweak to TempKeyring to default to some test params * Fixed linter issues * Remove flake8 ignore statement now that the fasteners module has been updated * Some initial renaming changes: password -> passphrase * Fixed wallet RPC issue where get_key_for_fingerprint wasn't awaited-upon. Fixed legacy keyring initialization (for migration scenarios) * Fixed improperly merged file * Fixed linter issues. More renaming. * Updated spots that were still using an incorrect keychain call * Renamed use_password_cache, obtain_current_password * Renamed supports_keyring_password * Renamed has_master_password * Renamed has_cached_password, get_cached_master_password * Linter fixes * Renamed master_password_is_valid * Renamed set_cached_master_password * Renamed set_master_password * Renamed remove_master_password * Renamed has_cached_master_password * Renaming in file_keyring and keyring_wrapper Updated default keyring payload used for tests * Renamed get_password Other renaming updates * Renamed set_password Other renaming updates * Renamed remaining password occurrences (where appropriate) * password -> passphrase * Added tests for setting an emoji and Japanese master passphrase * Attempt to notify the daemon when a keyring passphrase is set/updated/removed * Missed one password -> passphrase replacement. * Fixed some file synchronization issues found when running tests on macOS * Adjusted timeout values for test_writer_lock_reacquisition_failure for macOS. * Removed logging statements previously added for debugging * Prompt for keyring passphrase up-front when launching a service. Changed --have-gui flag to --wait-for-unlock * Updated set_keyring_passphrase RPC message to fix optional current_passphrase param when the keyring is using the default passphrase. * Minor test cleanup to deduplicate some code. * Fixed regression when setting a new master passphrase * Minor refactoring and docs/commenting updates * Renaming password -> passphrase went too far. Keyring backends use password terminology for compatibility with third party backends. * Disabling macOS support (previously added for testing only) * Disabling passphrase support in preparation for sending out the PR * Fixed improper merge (vscode didn't save changes during rebase) * Update chia/cmds/init_funcs.py Co-authored-by: Adam Kelly <338792+aqk@users.noreply.github.com> * skip_check_keys -> should_check_keys * Shuffling some imports around to break cycles reported by LGTM * Handle unlocking the daemon if it's already launched and waiting for unlock. * Replaced uses_keychain_proxy decorator in farmer.py. Fixed async usage of get_reward_targets. Linter/reformatting fixes * Replaced uses_keychain_proxy decorator with a clearer method. * Cleanup the temp keyring dir using shutil.rmtree() * Restored self._root_path (had been changed to self.root_path) * Minor cleanup * ensure_keychain_proxy() now throws if connect_to_keychain_and_validate() fails * Plot key resolution now yields a PlotKeys object which can be passed into create_plots. De-indented test_invalid_icc_sub_slot_vdf to keep git blame tidy. * Added 'keyring_status' daemon RPC message to support the GUI * Minor changes relating to PR feedback * Addressed more PR feedback (mostly type annotations) * Commented-out macOS file keyring usage. This can be re-enabled for testing purposes. * Addressed test failures that require multiple keyrings in the same process. Each TempKeyring will now set a custom KeyringWrapper instance. * Fixed logic for communicating user_passphrase_is_set in the keyring_status RPC response. * Updated type annotations and method signature for set_passphrase to expect a string instead of bytes. * Fixed Wallet RPC tests * Fixed full_node_store tests. BlockTools should be created using the create_block_tools(_async) function(s) * Fixed test failures in test_pool_rpc * Fixed test_daemon. After BlockTools.setup_plots is run, the config file needs to be re-read to refresh stale plot_directories. * Suppressing LGTM false positives regarding passphrase leakage in CLI error output. Seems that LGTM sees MIN_PASSPHRASE_LEN as sensitive data. * Second attempt at suppressing LGTM false positives * Third attempt at addressing LGTM false positives * Removed test_keyring_wrapper param from Keychain ctor. Test setup now sets the keyring_wrapper property directly. * Reformatting * More targeted update of the test config to refresh just the "plot_directories" value * More LGTM suppressions Co-authored-by: Adam Kelly <338792+aqk@users.noreply.github.com> Co-authored-by: wjblanke <wjb98672@gmail.com>
2021-08-04 22:46:55 +03:00
@unlocks_keyring(use_passphrase_cache=True)
def query_and_add_private_key_seed():
mnemonic = input("Enter the mnemonic you want to use: ")
add_private_key_seed(mnemonic)
Keyring passphrase protection (#7249) * Moved keyring handling into a KeyringWrapper class * Update click to 8.0.x for prompt_required support * Renamed KeyringWrapper to _KeyringWrapper * Expose password management options on Linux * CLI support for setting/removing a password * Global option for specifying the master password * Cache the password instead of setting on the context * Password bootstrapping during chia init * Tidying up _KeyringWraper's interface * Initial pass migrating the legacy keyring contents * Encryption/decryption of keyring.yaml contents * FileKeyring backend encrypts with ChaCha20Poly1305 * Tightened up keyring migration and initialization * Fixed issues identified by linters * Remove root_path from Keychain * Prevent double-migration if setting master passwd * KeyringWrapper tests are mostly complete * FileKeyring will now honor the service param * Tests for get/set/delete password * Formatting/commenting updates * Writer lock support with tests - WIP * keyring.yaml is now watched for modifications * Reader/Writer lock for get/delete password * Fixed linter issues * Reader lock tests * Formatting update * Hook up CHIA_ROOT support for KeychainWrapper * Quick fix to address test failures * Fixed failures when existing legacy keyring exists * Fixed test failures caused by reusing the same temp dir * keyring.yaml now lives in ~/.chia_keys by default. Can be overridden with CHIA_KEYS_ROOT or --keys-root-path * Fixed migration failure when setting a password (not using the default) * KeyringWrapper now uses supports_keyring_password to determine if a FileKeyring should be used. Patched tests to work regardless of whether supports_keyring_password return False * The daemon now takes a --have-gui option that will prevent calling check_keys() during startup. If the keyring is locked, we want the GUI to prompt for the password. * Added is_keyring_locked RPC call * Added 'unlock_keyring' RPC command * Added KeychainProxy and KeychainServer to handle RPC messages related to keyring operations. WalletNode no longer directly accesses the Keychain class. * Turn on macOS support for testing keyring passwords * Fixed get_key_for_fingerprint to use the ocal keychain if the platform doesn't need to remotely access the daemon's keychain. Fixed key reconstruction when sent over RPC. * Farmer now accesses the keychain over RPC * Fixes for linter issues and some restructuring to support tests that use setup_nodes.py * Couple of fixes to unblock the GUI from launching when a keyring password is set * Added a keychain RPC call for add_private_key() * Added remaining keychain proxy RPC calls for delete_key_by_fingerprint and delete_all_keys * Check for None when inspecting request arguments * Run check_keys after unlocking the keyring when the daemon is launched via GUI * Added check_keys RPC method. Fixed deserialization of key entropy in get_all_private_keys. This was preventing the GUI from being able to show key details. * Added get_first_private_key to keychain_server/proxy. create_plots now uses the keychain proxy when launched from the daemon. * Added a comment about KeychainProxy in chia plots check * Workaround import conflict when importing from 'tests.*' due to fasteners name conflict * Simulator now uses KeychainProxy if launched by the daemon. KeychainServer/Proxy now takes keychain user/testing params for testing scenarios. * Added "set_keyring_passphrase" RPC message * Reworking KeychainProxy usage to handle local keychain tests and RPC keychain tests. * Replace my prior usage of asyncio.run() with asyncio.get_event_loop().run_until_complete() * Silencing file_keyring logging for the moment. * Updated tests to use test keychains and appropriate BlockTools construction BlockTools should now be created with create_block_tools(_async) to handle async scenarios. Updated block_tools to be async compatible Updated fasteners to fix installation of top-level 'tests' in site-packages * Added 'remove_keyring_passphrase' RPC message to the daemon Minor tweak to TempKeyring to default to some test params * Fixed linter issues * Remove flake8 ignore statement now that the fasteners module has been updated * Some initial renaming changes: password -> passphrase * Fixed wallet RPC issue where get_key_for_fingerprint wasn't awaited-upon. Fixed legacy keyring initialization (for migration scenarios) * Fixed improperly merged file * Fixed linter issues. More renaming. * Updated spots that were still using an incorrect keychain call * Renamed use_password_cache, obtain_current_password * Renamed supports_keyring_password * Renamed has_master_password * Renamed has_cached_password, get_cached_master_password * Linter fixes * Renamed master_password_is_valid * Renamed set_cached_master_password * Renamed set_master_password * Renamed remove_master_password * Renamed has_cached_master_password * Renaming in file_keyring and keyring_wrapper Updated default keyring payload used for tests * Renamed get_password Other renaming updates * Renamed set_password Other renaming updates * Renamed remaining password occurrences (where appropriate) * password -> passphrase * Added tests for setting an emoji and Japanese master passphrase * Attempt to notify the daemon when a keyring passphrase is set/updated/removed * Missed one password -> passphrase replacement. * Fixed some file synchronization issues found when running tests on macOS * Adjusted timeout values for test_writer_lock_reacquisition_failure for macOS. * Removed logging statements previously added for debugging * Prompt for keyring passphrase up-front when launching a service. Changed --have-gui flag to --wait-for-unlock * Updated set_keyring_passphrase RPC message to fix optional current_passphrase param when the keyring is using the default passphrase. * Minor test cleanup to deduplicate some code. * Fixed regression when setting a new master passphrase * Minor refactoring and docs/commenting updates * Renaming password -> passphrase went too far. Keyring backends use password terminology for compatibility with third party backends. * Disabling macOS support (previously added for testing only) * Disabling passphrase support in preparation for sending out the PR * Fixed improper merge (vscode didn't save changes during rebase) * Update chia/cmds/init_funcs.py Co-authored-by: Adam Kelly <338792+aqk@users.noreply.github.com> * skip_check_keys -> should_check_keys * Shuffling some imports around to break cycles reported by LGTM * Handle unlocking the daemon if it's already launched and waiting for unlock. * Replaced uses_keychain_proxy decorator in farmer.py. Fixed async usage of get_reward_targets. Linter/reformatting fixes * Replaced uses_keychain_proxy decorator with a clearer method. * Cleanup the temp keyring dir using shutil.rmtree() * Restored self._root_path (had been changed to self.root_path) * Minor cleanup * ensure_keychain_proxy() now throws if connect_to_keychain_and_validate() fails * Plot key resolution now yields a PlotKeys object which can be passed into create_plots. De-indented test_invalid_icc_sub_slot_vdf to keep git blame tidy. * Added 'keyring_status' daemon RPC message to support the GUI * Minor changes relating to PR feedback * Addressed more PR feedback (mostly type annotations) * Commented-out macOS file keyring usage. This can be re-enabled for testing purposes. * Addressed test failures that require multiple keyrings in the same process. Each TempKeyring will now set a custom KeyringWrapper instance. * Fixed logic for communicating user_passphrase_is_set in the keyring_status RPC response. * Updated type annotations and method signature for set_passphrase to expect a string instead of bytes. * Fixed Wallet RPC tests * Fixed full_node_store tests. BlockTools should be created using the create_block_tools(_async) function(s) * Fixed test failures in test_pool_rpc * Fixed test_daemon. After BlockTools.setup_plots is run, the config file needs to be re-read to refresh stale plot_directories. * Suppressing LGTM false positives regarding passphrase leakage in CLI error output. Seems that LGTM sees MIN_PASSPHRASE_LEN as sensitive data. * Second attempt at suppressing LGTM false positives * Third attempt at addressing LGTM false positives * Removed test_keyring_wrapper param from Keychain ctor. Test setup now sets the keyring_wrapper property directly. * Reformatting * More targeted update of the test config to refresh just the "plot_directories" value * More LGTM suppressions Co-authored-by: Adam Kelly <338792+aqk@users.noreply.github.com> Co-authored-by: wjblanke <wjb98672@gmail.com>
2021-08-04 22:46:55 +03:00
@unlocks_keyring(use_passphrase_cache=True)
def add_private_key_seed(mnemonic: str):
"""
Add a private key seed to the keyring, with the given mnemonic.
"""
try:
passphrase = ""
[CLI] chia keys derive [wallet-address | child-key | search] (#9184) * Added chia keys derive (wallet-address | child-key) to display derived wallet addresses or public keys * Support for public key (unhardened) derivation * Fleshed out the search command. Can perform a substring search on wallet addresses, public, and private keys. Support for deriving private keys * Default to unhardened derivation. Added --hardened-derivation option. HD paths denote hardened derivation with a 'h' suffix at each index. * Added --no-progress to reduce output. Exit code indicates search success/failure. Option name cleanup. * chia keys derive search can now search for multiple terms * chia keys derive search can be restricted to searching pubkeys|privkeys|addresses|all * Allow child-key derivation rooted from an arbitrary HD path * Search derived keys rooted under an arbitrary HD path * LGTM fixes * Remove extra master_sk_to_wallet_sk_unhardened definition * Cleanup and fixed search output * Cleanup and comments * Added tests for `chia keys` commands * Using @pytest_asyncio.fixture to decorate empty_keyring() as suggested in pytest's output. * Set asyncio-mode to auto to address pytest warning * See if tests pass without checking exit status * Added chia init step to tests that direclty invoke the `cli` function * Explicitly add --root-path option to tests that run the `cli` function. * Tests fix * Re-enable checks against exit_code * More fine tuning to address CI failures * Changes to address naming and other feedback * Updated tests
2022-01-26 07:42:16 +03:00
sk = Keychain().add_private_key(mnemonic, passphrase)
fingerprint = sk.get_g1().get_fingerprint()
Pools mainnet (#7047) * added clarifying comments * WIP test * added WIP test * Refine genesis challenge. Remove unnecessary pool_puzzle function * Sign spend. Remove create_member_spend. Rename state transition function to create_travel_spend * Rename create_member_spend to create_travel_spend * Add singleton id logging * Enhance logging for debugging * renaming * rephrase inside the puzzle * fixed signing and added some support functions * Fix issue with announcement * Progress spending the singleton * Fix arguments to pool_state_to_inner_puzzle call * Fix arguments to pool_state_to_inner_puzzle * Improve error message when wallet is not running * Remove misleading message about missing wallet process, when problem is the farmer by making poolnft command error out earlier * Fix parent coin info bug * Multiple state transitions in one block * Lint * Remove assert * Fix incorrect p2_singleton_ph calculation (thanks nil00) * Update waiting room puzzle to accept genesis_challenge * Update calls to create_waiting * Go to waiting state from committed state * Augment debug_spend_bundle * fix 2 bugs in wallet * Fix lint * fix bad_agg_sig bug * Tests and lint * remove breakpoint * fix clvm tests for new hexs and hashs * Fixed a bug in the coin store that was probably from merging. (#6577) * Fixed a bug in the coin store that was probably from merging. * The exception doesn't need to be there * CI Lint fix * Added lifecycle tests for pooling drivers (#6610) * Ms.poolabsorb (#6615) * Support for absorbing rewards in pools (untested) * Style improvements * More work on absorb * Revert default root and remove log * Revert small plots * Use real sub slot iters * Update types * debug1 * Fix bugs * fix output of agg sig log messages * Make fewer calls to pw_status in test * remove old comment * logging and state management * logging * small bug fix & rename for accuracy * format * Fix types for uncurry function * lint * Update test to use exceptions * Change assumptions about self-pooling in lifecycle test * Install types for mypy * Revert "Install types for mypy" This reverts commit a82dcb712a6a97b8789b17c98cac8eafaffe90f5. * install types for mypy * install types for mypy * More keys * Remove flags requiring interactive prompts * Change initial spend to waiting room if self-pooling * lint * lint * linting * Refactor test * Use correct value in log message * update p2_singleton_or_delated_puzhash * initial version of pool wallet with p2_singleton_or_delay * run black formatting * fix rebase wonkiness * fix announcement code in p2_singleton_or_delayed * removed redundant defaulting standardised hexstr handling * lint fixes * Fixed pool lifecycle tests to current standards, but discovered tests are not validating signatures * Signatures validate on this test now although the test still does not check it. * Lint fix * Fixed plotnft show and linting errors * fixed failing farmer/harvester rpc test * lint fix * Commenting out some outdated tests * Updated test coverage * lint fix * Some minor P2singleton improvements (#6325) * Improve some debugging tools. * Tidy pool clvm. * Use `SINGLETON_STRUCT`. Remove unused `and` macro. * Use better name `SINGLETON_MOD_HASH`. * Finish lifecycle test suite. * Fixing for merge with chia-blockchain/pools_delayed_puzzle (#72) Co-authored-by: Matt Hauff <quexington@gmail.com> * Default delay time was being set incorrectly * Extracted get_delayed_puz_info_from_launcher_spend to driver code * Ms.taproot plot2 (#6692) * Start work on adding taproot to new plots * Fix issue in block_tools * new test-cache * Lint * DID fixexs * Fix other tests * Python black * Fix full node store test * Ensure block index <= 128 bits. * fix test_pool_config test * fix comments in pool_config and in chialisp files * self_pool -> pool -> self_pool * Implement leaving pools * Fix conflicts with main via mini-rebase * Fixup rebase mistakes * Bring in Mariano's node discovery chagnes from pools.dev * Fix adapters - Thanks Richard * build tests * Add pools tests * Disable DID tests * farmer|protocol: Some renaming related to the pool protocol * farmer: Use `None` instead of `{}` and add local `pool_state` * protocol|farmer: Introduce and use `PoolErrorCode` * rename: `pool_payout_instructions` -> `payout_instructions` * refactor: `AuthenticationKeyInfo` -> `authentication_key` * refactor: Move `launcher_id` up * rename: Some variable name changes * rename: `points_balance` -> `points` * format: Squash aggregation into one line * farmer: Make `update_pool_state` public * farmer: Print traceback if `update_pool_state` fails * farmer: Periodically call `GET /pool_info`, add `_pool_get_pool_info` * farmer: Add `authentication_token_timeout` to `pool_state` Fetch it from `GET /pool_info` * protocol|farmer: Implement support for `GET|POST|PUT /farmer` * farmer: Make use of `GET|POST /farmer` - To make the farmer known by the pool - To update local balance/difficulty from the pool periodically * farmer|protocol: Adjust `POST /partial` to match the latest spec * farmer: Hash messages before signing * pools: Drop unused code * farmer: Fix aggregation of partial signatures * farmer: support self pooling, don't pool if url=="" * wallet: return uint64 for delay time, instead of bytes * pool: add error code for delay time too short * farmer: cleaner logging when no connection to pool * farmer: add harvester node id to pool protocol * Rename method (test fix) and lint fix * Change errors to warnings (pool communication) * Remove pool callbacks on a reorg * farmer: Continue earlier when no pool URL is provided * farmer: Print method in log * farmer: Handle exceptions for all pool endpoint calls * farmer|protocol: Keep track of failed requests to the pool * farmer: Fix typo which caused issue with pooling * wallet: simplify solution_to_extra_data * tests: Comment out DID tests which are not working yet * Remove DID Wallet test workflows * Return launcher_id when creating Pool Wallet * Name p2_singleton_puzzle_hash correctly * Improve 'test_singleton_lifecycle_fast.py'. * Make test more robust in the face of asynchronous adversity * Add commandline cmds for joining and leaving pools * Fix poolnft leave params * Remove redundant assignment brought in from main * Remove unneeded code * Style and parsimony * pool_puzzles: Check was wrong, and bad naming * format: Fix linting * format: Remove log and rename variable * pool-wallet: Fix self pooling with multiple pool wallets. Don't remove interested puzzle_hash * gui: Use pools branch * format: fix lint * Remove ununsed code, improve initial_pool_state_from_dict * farmer: Instantly update the config, when config file changes * format: Speed up loading of the authentication key * logging: less annoying logging * Test pool NFT creation directly to pool * Test switching pools without self-farming in between * lint * pooling: Use integer for protocol version (#6797) * pooling: Use integer for protocol version * pooling: Fix import * Update GUI commit * Ms.login2 (#6804) * pooling: Login WIP * pooling: add RPC for get_link * dont use timeout * pooling: rename to get_login_link * format: remove logging * Fix SES test * Required cli argument Co-authored-by: almog <almogdepaz@gmail.com> * farmer|protocols: Rename `current_difficulty` for `POST /partial` (#6807) * Fix to farm summary * Use target_puzzlehash param name in RPC call * Pool test coverage (#6782) * Improvement in test coverage and typing * Added an extra absorb to the pool lifecycle test (only works when merged with https://github.com/Chia-Network/chia-blockchain/pull/6733) * Added new drivers for the p2_singleton puzzles * Added new tests and test coverage for singletons * organize pools testing directory * black formatting * black formatting in venv * lint fix * Update CI tests * Fixing tests post rebase * lint fix * Minor readability fix Co-authored-by: matt <matt@chia.net> * farmer: Drop `target_puzzle_hash` from `GET /farmer` and `GET /login` (#6816) * Allow creation of PlotNFTs in self-farming state * gui: Fix install with more RAM (#6821) * Allow implicit payout_address in self-pool state, improve error messages and param ergonomics * print units in non-standard wallets correctly * Fix farmer import * Make syncing message in CLI more intuitive like the GUI * Fix linting and show header hash instead of height * gui: Update to 725071236eff8c81d5b267dc8eb69d7e03f3df8c * Revert "Merge" This reverts commit 23a1e688c5fb4f72983fd896d4933336a365fe38, reversing changes made to a850246c6f4de4d2eb65c4ac1d6023431f3ba7e9. * Revert "Revert "Merge"" This reverts commit 680331859f5dc404cca9c2ff8f4a61df374db125. * Treat tx_record as Dict. Refactor tx submission * Also add passed-in coin spends when processing new blocks in reconsider_peak * Test utilities had moved * Fix import of moved block_tools * Potentially fix yaml * Previously didn't take the right part of this change * Add -y flag, improve commandline plotnft handling * Fix typo * Add -y flag to plotnft create * pool_wallet: Restore from DB properly * wallet: ignore bad pool configs * Reduce memory * pool_wallet: Add claim command * pool_wallet: Set transaction records to confirmed * wallet: Fix bug in transaction cache * Formatting and remove log * pool_wallet: CLI balance and improvements to plotnft_funcs.py * pool_wallet: Simplify, and fix issue with double submission * pool_wallet: Fix tests * pool_wallet: Don't allow switching before relative lock height * update gui * change to 3000 mem * Correct sense of -y flag for self-pooling * cli: Display payout instructions for pool * pool_wallet: Don't create massive transactions * cli: Improvements to plotnft * pool_wallet: Get correct pool state * pool_wallet: Use last transaction block to prevent condition failure * Add block height for current state * Add outstanding unconfirmed transactions to pw_status * Refine command line plotnft show pending transactions * Fix tests by using the correct output from pw_status * Try to fix windows build * Print expected leave height * label pool urls * pool_wallet: Don't include pool 1.75 rewards in total * wallet: Add RPC and CLI for deleting unconfirmed transactions for a wallet * pool_wallet: If farming to a pool, show 0 balance in wallet * pool_wallet: Show error message if invalid state, in CLI * pool_wallet: Don't allow switching if there are pending unconfirmed transactions * tests: Clean up pool test logging * tests: Fix lint * Changed the pool innerpuzzes (#6802) * overload solutions for pool_innerpuz parameters * Fix tests for reduced size puzzles * deleted messy deprecated test * Fix lint. * fix bug where spend types were the wrong way around * merge with richard's lint fix * fix wallet bug remove unnecessary signature add defun-inline for clarity * Swap to defun for absorb case Use cons box for member innerpuz solution * fix if statement for cons box p1 * remove unnecessary solution arg * quick innerpuz fix to make tests pass * Switch to key-value pairs Undo cons box solution in pool_member inner puzzle * fix singleton lifecycle test * added some comments to calrify the meaning on "ps" * lint fix * reduce label size, search for label when reconstructing from solution * no need to keep looping if `p` found * lint fix * Removed unecessary defun-inline and changed hyphens to underscores * Changed created_coin_value_or_0 to an inline function * Changed morph_condition to an inline function * Added a comment for odd_cons_m113 * Rename output_odd and odd_output_found * Add inline functions to document the lineage proof values * Stager two rewrite * Added an ASSER_MY_AMOUNT to p2_singleton_or_delayed * Extract truth functionality to singleton_truths.clib * Fix tree hashes * Changed truths to a struct rather than a list. * fix test_singletons update did_innerpuz * recompile did_innerpuz * fix a log error * Renamed variable and factored out code per @richardkiss * lint fix * switch launcher extra_data to key_value pairs * fix parsing of new format of extra_data in launcher solution * fix broken test for new launcher solution format * remove bare raise Co-authored-by: Richard Kiss <him@richardkiss.com> Co-authored-by: Matt Hauff <quexington@gmail.com> * Also add passed-in coin spends when processing new blocks in reconsider_peak (#6898) Co-authored-by: Adam Kelly <aqk> * Moved debug_spend_bundle and added it to the SpendBundle object (#6840) * Moved debug_spend_bundle and added it to the SpendBundle object * Remove problematic typing * Add testnet config * wallet: Memory would get corrupted if there was an error (#6902) * wallet: Memory would get corrupted if there was an error * wallet: Use block_record * wallet: Add records in a full fork too * wallet: remove unnecessary arguments in CC and DID * add to cache, revert if transaction fails Co-authored-by: Yostra <straya@chia.net> * Improve comment * pool_wallet: Fix driver bug * wallet: Fix memory corruption * gui: Update to latest * Increase memory size * tests: Add test for absorbing from pool * small fix in solution_to_extra_data * Fixed incorrect function name * pooling: Fix EOS handling in full node * [pools.testnet9]add post /partial and /farmer header (#6957) * Update farmer.py add post header * Update farmer_api.py add post header * Update chia/farmer/farmer.py Co-authored-by: dustinface <35775977+xdustinface@users.noreply.github.com> * Update chia/farmer/farmer_api.py Co-authored-by: dustinface <35775977+xdustinface@users.noreply.github.com> Co-authored-by: Mariano Sorgente <3069354+mariano54@users.noreply.github.com> Co-authored-by: dustinface <35775977+xdustinface@users.noreply.github.com> * Fix lint and cleanup farmer.py * farmer: Fix linting issues (#7010) * Handle the case of incorrectly formatted PoolState data returned from inner singleton * wallet: Resubmit transaction if not successful, rename to new_transaction_block_callback (#7008) * Fix lint in pool_puzzles * pooling: Fix owner private key lookup, and remove unnecessary argument * pooling: Clear target state on `delete_unconfirmed_transactions` * Lint * Fix non-deterministic test * Slight cleanup clvm driver code (#7028) * Return None when a deserialized CLVM structure does not fit the expected format of var-value pair for singleton data * lint Co-authored-by: Adam Kelly <aqk> * Revert "Add testnet config" This reverts commit 98124427241b8a268fbab43ac116887c89e9974f. Co-authored-by: matt <matt@chia.net> Co-authored-by: Adam Kelly <aqk@aqk.im> Co-authored-by: Mariano Sorgente <sorgente711@gmail.com> Co-authored-by: Matt Hauff <quexington@gmail.com> Co-authored-by: Mariano Sorgente <3069354+mariano54@users.noreply.github.com> Co-authored-by: Adam <aqk@Adams-MacBook-Pro.local> Co-authored-by: Adam Kelly <aqk> Co-authored-by: Richard Kiss <him@richardkiss.com> Co-authored-by: xdustinface <xdustinfacex@gmail.com> Co-authored-by: almog <almogdepaz@gmail.com> Co-authored-by: dustinface <35775977+xdustinface@users.noreply.github.com> Co-authored-by: Earle Lowe <e.lowe@chia.net> Co-authored-by: arvidn <arvid@libtorrent.org> Co-authored-by: willi123yao <willi123yao@gmail.com> Co-authored-by: arty <art.yerkes@gmail.com> Co-authored-by: William Blanke <wjb98672@gmail.com> Co-authored-by: matt-o-how <48453825+matt-o-how@users.noreply.github.com> Co-authored-by: Chris Marslender <chrismarslender@gmail.com> Co-authored-by: Yostra <straya@chia.net> Co-authored-by: DouCrazy <43004977+lpf763827726@users.noreply.github.com>
2021-06-30 00:21:25 +03:00
print(f"Added private key with public key fingerprint {fingerprint}")
except ValueError as e:
print(e)
return None
Keyring passphrase protection (#7249) * Moved keyring handling into a KeyringWrapper class * Update click to 8.0.x for prompt_required support * Renamed KeyringWrapper to _KeyringWrapper * Expose password management options on Linux * CLI support for setting/removing a password * Global option for specifying the master password * Cache the password instead of setting on the context * Password bootstrapping during chia init * Tidying up _KeyringWraper's interface * Initial pass migrating the legacy keyring contents * Encryption/decryption of keyring.yaml contents * FileKeyring backend encrypts with ChaCha20Poly1305 * Tightened up keyring migration and initialization * Fixed issues identified by linters * Remove root_path from Keychain * Prevent double-migration if setting master passwd * KeyringWrapper tests are mostly complete * FileKeyring will now honor the service param * Tests for get/set/delete password * Formatting/commenting updates * Writer lock support with tests - WIP * keyring.yaml is now watched for modifications * Reader/Writer lock for get/delete password * Fixed linter issues * Reader lock tests * Formatting update * Hook up CHIA_ROOT support for KeychainWrapper * Quick fix to address test failures * Fixed failures when existing legacy keyring exists * Fixed test failures caused by reusing the same temp dir * keyring.yaml now lives in ~/.chia_keys by default. Can be overridden with CHIA_KEYS_ROOT or --keys-root-path * Fixed migration failure when setting a password (not using the default) * KeyringWrapper now uses supports_keyring_password to determine if a FileKeyring should be used. Patched tests to work regardless of whether supports_keyring_password return False * The daemon now takes a --have-gui option that will prevent calling check_keys() during startup. If the keyring is locked, we want the GUI to prompt for the password. * Added is_keyring_locked RPC call * Added 'unlock_keyring' RPC command * Added KeychainProxy and KeychainServer to handle RPC messages related to keyring operations. WalletNode no longer directly accesses the Keychain class. * Turn on macOS support for testing keyring passwords * Fixed get_key_for_fingerprint to use the ocal keychain if the platform doesn't need to remotely access the daemon's keychain. Fixed key reconstruction when sent over RPC. * Farmer now accesses the keychain over RPC * Fixes for linter issues and some restructuring to support tests that use setup_nodes.py * Couple of fixes to unblock the GUI from launching when a keyring password is set * Added a keychain RPC call for add_private_key() * Added remaining keychain proxy RPC calls for delete_key_by_fingerprint and delete_all_keys * Check for None when inspecting request arguments * Run check_keys after unlocking the keyring when the daemon is launched via GUI * Added check_keys RPC method. Fixed deserialization of key entropy in get_all_private_keys. This was preventing the GUI from being able to show key details. * Added get_first_private_key to keychain_server/proxy. create_plots now uses the keychain proxy when launched from the daemon. * Added a comment about KeychainProxy in chia plots check * Workaround import conflict when importing from 'tests.*' due to fasteners name conflict * Simulator now uses KeychainProxy if launched by the daemon. KeychainServer/Proxy now takes keychain user/testing params for testing scenarios. * Added "set_keyring_passphrase" RPC message * Reworking KeychainProxy usage to handle local keychain tests and RPC keychain tests. * Replace my prior usage of asyncio.run() with asyncio.get_event_loop().run_until_complete() * Silencing file_keyring logging for the moment. * Updated tests to use test keychains and appropriate BlockTools construction BlockTools should now be created with create_block_tools(_async) to handle async scenarios. Updated block_tools to be async compatible Updated fasteners to fix installation of top-level 'tests' in site-packages * Added 'remove_keyring_passphrase' RPC message to the daemon Minor tweak to TempKeyring to default to some test params * Fixed linter issues * Remove flake8 ignore statement now that the fasteners module has been updated * Some initial renaming changes: password -> passphrase * Fixed wallet RPC issue where get_key_for_fingerprint wasn't awaited-upon. Fixed legacy keyring initialization (for migration scenarios) * Fixed improperly merged file * Fixed linter issues. More renaming. * Updated spots that were still using an incorrect keychain call * Renamed use_password_cache, obtain_current_password * Renamed supports_keyring_password * Renamed has_master_password * Renamed has_cached_password, get_cached_master_password * Linter fixes * Renamed master_password_is_valid * Renamed set_cached_master_password * Renamed set_master_password * Renamed remove_master_password * Renamed has_cached_master_password * Renaming in file_keyring and keyring_wrapper Updated default keyring payload used for tests * Renamed get_password Other renaming updates * Renamed set_password Other renaming updates * Renamed remaining password occurrences (where appropriate) * password -> passphrase * Added tests for setting an emoji and Japanese master passphrase * Attempt to notify the daemon when a keyring passphrase is set/updated/removed * Missed one password -> passphrase replacement. * Fixed some file synchronization issues found when running tests on macOS * Adjusted timeout values for test_writer_lock_reacquisition_failure for macOS. * Removed logging statements previously added for debugging * Prompt for keyring passphrase up-front when launching a service. Changed --have-gui flag to --wait-for-unlock * Updated set_keyring_passphrase RPC message to fix optional current_passphrase param when the keyring is using the default passphrase. * Minor test cleanup to deduplicate some code. * Fixed regression when setting a new master passphrase * Minor refactoring and docs/commenting updates * Renaming password -> passphrase went too far. Keyring backends use password terminology for compatibility with third party backends. * Disabling macOS support (previously added for testing only) * Disabling passphrase support in preparation for sending out the PR * Fixed improper merge (vscode didn't save changes during rebase) * Update chia/cmds/init_funcs.py Co-authored-by: Adam Kelly <338792+aqk@users.noreply.github.com> * skip_check_keys -> should_check_keys * Shuffling some imports around to break cycles reported by LGTM * Handle unlocking the daemon if it's already launched and waiting for unlock. * Replaced uses_keychain_proxy decorator in farmer.py. Fixed async usage of get_reward_targets. Linter/reformatting fixes * Replaced uses_keychain_proxy decorator with a clearer method. * Cleanup the temp keyring dir using shutil.rmtree() * Restored self._root_path (had been changed to self.root_path) * Minor cleanup * ensure_keychain_proxy() now throws if connect_to_keychain_and_validate() fails * Plot key resolution now yields a PlotKeys object which can be passed into create_plots. De-indented test_invalid_icc_sub_slot_vdf to keep git blame tidy. * Added 'keyring_status' daemon RPC message to support the GUI * Minor changes relating to PR feedback * Addressed more PR feedback (mostly type annotations) * Commented-out macOS file keyring usage. This can be re-enabled for testing purposes. * Addressed test failures that require multiple keyrings in the same process. Each TempKeyring will now set a custom KeyringWrapper instance. * Fixed logic for communicating user_passphrase_is_set in the keyring_status RPC response. * Updated type annotations and method signature for set_passphrase to expect a string instead of bytes. * Fixed Wallet RPC tests * Fixed full_node_store tests. BlockTools should be created using the create_block_tools(_async) function(s) * Fixed test failures in test_pool_rpc * Fixed test_daemon. After BlockTools.setup_plots is run, the config file needs to be re-read to refresh stale plot_directories. * Suppressing LGTM false positives regarding passphrase leakage in CLI error output. Seems that LGTM sees MIN_PASSPHRASE_LEN as sensitive data. * Second attempt at suppressing LGTM false positives * Third attempt at addressing LGTM false positives * Removed test_keyring_wrapper param from Keychain ctor. Test setup now sets the keyring_wrapper property directly. * Reformatting * More targeted update of the test config to refresh just the "plot_directories" value * More LGTM suppressions Co-authored-by: Adam Kelly <338792+aqk@users.noreply.github.com> Co-authored-by: wjblanke <wjb98672@gmail.com>
2021-08-04 22:46:55 +03:00
@unlocks_keyring(use_passphrase_cache=True)
2021-04-18 21:07:02 +03:00
def show_all_keys(show_mnemonic: bool):
"""
Prints all keys and mnemonics (if available).
"""
root_path = DEFAULT_ROOT_PATH
config = load_config(root_path, "config.yaml")
[CLI] chia keys derive [wallet-address | child-key | search] (#9184) * Added chia keys derive (wallet-address | child-key) to display derived wallet addresses or public keys * Support for public key (unhardened) derivation * Fleshed out the search command. Can perform a substring search on wallet addresses, public, and private keys. Support for deriving private keys * Default to unhardened derivation. Added --hardened-derivation option. HD paths denote hardened derivation with a 'h' suffix at each index. * Added --no-progress to reduce output. Exit code indicates search success/failure. Option name cleanup. * chia keys derive search can now search for multiple terms * chia keys derive search can be restricted to searching pubkeys|privkeys|addresses|all * Allow child-key derivation rooted from an arbitrary HD path * Search derived keys rooted under an arbitrary HD path * LGTM fixes * Remove extra master_sk_to_wallet_sk_unhardened definition * Cleanup and fixed search output * Cleanup and comments * Added tests for `chia keys` commands * Using @pytest_asyncio.fixture to decorate empty_keyring() as suggested in pytest's output. * Set asyncio-mode to auto to address pytest warning * See if tests pass without checking exit status * Added chia init step to tests that direclty invoke the `cli` function * Explicitly add --root-path option to tests that run the `cli` function. * Tests fix * Re-enable checks against exit_code * More fine tuning to address CI failures * Changes to address naming and other feedback * Updated tests
2022-01-26 07:42:16 +03:00
private_keys = Keychain().get_all_private_keys()
selected = config["selected_network"]
prefix = config["network_overrides"]["config"][selected]["address_prefix"]
if len(private_keys) == 0:
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 sk, seed in private_keys:
print("")
print("Fingerprint:", sk.get_g1().get_fingerprint())
print("Master public key (m):", sk.get_g1())
print(
2021-04-18 09:59:30 +03:00
"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())
print(
"First wallet address:",
encode_puzzle_hash(create_puzzlehash_for_pk(master_sk_to_wallet_sk(sk, uint32(0)).get_g1()), prefix),
)
assert seed is not None
2021-04-18 21:07:02 +03:00
if show_mnemonic:
print("Master private key (m):", bytes(sk).hex())
print(
"First wallet secret key (m/12381/8444/2/0):",
2021-05-24 23:26:21 +03:00
master_sk_to_wallet_sk(sk, uint32(0)),
)
2021-04-18 21:07:02 +03:00
mnemonic = bytes_to_mnemonic(seed)
print(" Mnemonic seed (24 secret words):")
print(mnemonic)
Keyring passphrase protection (#7249) * Moved keyring handling into a KeyringWrapper class * Update click to 8.0.x for prompt_required support * Renamed KeyringWrapper to _KeyringWrapper * Expose password management options on Linux * CLI support for setting/removing a password * Global option for specifying the master password * Cache the password instead of setting on the context * Password bootstrapping during chia init * Tidying up _KeyringWraper's interface * Initial pass migrating the legacy keyring contents * Encryption/decryption of keyring.yaml contents * FileKeyring backend encrypts with ChaCha20Poly1305 * Tightened up keyring migration and initialization * Fixed issues identified by linters * Remove root_path from Keychain * Prevent double-migration if setting master passwd * KeyringWrapper tests are mostly complete * FileKeyring will now honor the service param * Tests for get/set/delete password * Formatting/commenting updates * Writer lock support with tests - WIP * keyring.yaml is now watched for modifications * Reader/Writer lock for get/delete password * Fixed linter issues * Reader lock tests * Formatting update * Hook up CHIA_ROOT support for KeychainWrapper * Quick fix to address test failures * Fixed failures when existing legacy keyring exists * Fixed test failures caused by reusing the same temp dir * keyring.yaml now lives in ~/.chia_keys by default. Can be overridden with CHIA_KEYS_ROOT or --keys-root-path * Fixed migration failure when setting a password (not using the default) * KeyringWrapper now uses supports_keyring_password to determine if a FileKeyring should be used. Patched tests to work regardless of whether supports_keyring_password return False * The daemon now takes a --have-gui option that will prevent calling check_keys() during startup. If the keyring is locked, we want the GUI to prompt for the password. * Added is_keyring_locked RPC call * Added 'unlock_keyring' RPC command * Added KeychainProxy and KeychainServer to handle RPC messages related to keyring operations. WalletNode no longer directly accesses the Keychain class. * Turn on macOS support for testing keyring passwords * Fixed get_key_for_fingerprint to use the ocal keychain if the platform doesn't need to remotely access the daemon's keychain. Fixed key reconstruction when sent over RPC. * Farmer now accesses the keychain over RPC * Fixes for linter issues and some restructuring to support tests that use setup_nodes.py * Couple of fixes to unblock the GUI from launching when a keyring password is set * Added a keychain RPC call for add_private_key() * Added remaining keychain proxy RPC calls for delete_key_by_fingerprint and delete_all_keys * Check for None when inspecting request arguments * Run check_keys after unlocking the keyring when the daemon is launched via GUI * Added check_keys RPC method. Fixed deserialization of key entropy in get_all_private_keys. This was preventing the GUI from being able to show key details. * Added get_first_private_key to keychain_server/proxy. create_plots now uses the keychain proxy when launched from the daemon. * Added a comment about KeychainProxy in chia plots check * Workaround import conflict when importing from 'tests.*' due to fasteners name conflict * Simulator now uses KeychainProxy if launched by the daemon. KeychainServer/Proxy now takes keychain user/testing params for testing scenarios. * Added "set_keyring_passphrase" RPC message * Reworking KeychainProxy usage to handle local keychain tests and RPC keychain tests. * Replace my prior usage of asyncio.run() with asyncio.get_event_loop().run_until_complete() * Silencing file_keyring logging for the moment. * Updated tests to use test keychains and appropriate BlockTools construction BlockTools should now be created with create_block_tools(_async) to handle async scenarios. Updated block_tools to be async compatible Updated fasteners to fix installation of top-level 'tests' in site-packages * Added 'remove_keyring_passphrase' RPC message to the daemon Minor tweak to TempKeyring to default to some test params * Fixed linter issues * Remove flake8 ignore statement now that the fasteners module has been updated * Some initial renaming changes: password -> passphrase * Fixed wallet RPC issue where get_key_for_fingerprint wasn't awaited-upon. Fixed legacy keyring initialization (for migration scenarios) * Fixed improperly merged file * Fixed linter issues. More renaming. * Updated spots that were still using an incorrect keychain call * Renamed use_password_cache, obtain_current_password * Renamed supports_keyring_password * Renamed has_master_password * Renamed has_cached_password, get_cached_master_password * Linter fixes * Renamed master_password_is_valid * Renamed set_cached_master_password * Renamed set_master_password * Renamed remove_master_password * Renamed has_cached_master_password * Renaming in file_keyring and keyring_wrapper Updated default keyring payload used for tests * Renamed get_password Other renaming updates * Renamed set_password Other renaming updates * Renamed remaining password occurrences (where appropriate) * password -> passphrase * Added tests for setting an emoji and Japanese master passphrase * Attempt to notify the daemon when a keyring passphrase is set/updated/removed * Missed one password -> passphrase replacement. * Fixed some file synchronization issues found when running tests on macOS * Adjusted timeout values for test_writer_lock_reacquisition_failure for macOS. * Removed logging statements previously added for debugging * Prompt for keyring passphrase up-front when launching a service. Changed --have-gui flag to --wait-for-unlock * Updated set_keyring_passphrase RPC message to fix optional current_passphrase param when the keyring is using the default passphrase. * Minor test cleanup to deduplicate some code. * Fixed regression when setting a new master passphrase * Minor refactoring and docs/commenting updates * Renaming password -> passphrase went too far. Keyring backends use password terminology for compatibility with third party backends. * Disabling macOS support (previously added for testing only) * Disabling passphrase support in preparation for sending out the PR * Fixed improper merge (vscode didn't save changes during rebase) * Update chia/cmds/init_funcs.py Co-authored-by: Adam Kelly <338792+aqk@users.noreply.github.com> * skip_check_keys -> should_check_keys * Shuffling some imports around to break cycles reported by LGTM * Handle unlocking the daemon if it's already launched and waiting for unlock. * Replaced uses_keychain_proxy decorator in farmer.py. Fixed async usage of get_reward_targets. Linter/reformatting fixes * Replaced uses_keychain_proxy decorator with a clearer method. * Cleanup the temp keyring dir using shutil.rmtree() * Restored self._root_path (had been changed to self.root_path) * Minor cleanup * ensure_keychain_proxy() now throws if connect_to_keychain_and_validate() fails * Plot key resolution now yields a PlotKeys object which can be passed into create_plots. De-indented test_invalid_icc_sub_slot_vdf to keep git blame tidy. * Added 'keyring_status' daemon RPC message to support the GUI * Minor changes relating to PR feedback * Addressed more PR feedback (mostly type annotations) * Commented-out macOS file keyring usage. This can be re-enabled for testing purposes. * Addressed test failures that require multiple keyrings in the same process. Each TempKeyring will now set a custom KeyringWrapper instance. * Fixed logic for communicating user_passphrase_is_set in the keyring_status RPC response. * Updated type annotations and method signature for set_passphrase to expect a string instead of bytes. * Fixed Wallet RPC tests * Fixed full_node_store tests. BlockTools should be created using the create_block_tools(_async) function(s) * Fixed test failures in test_pool_rpc * Fixed test_daemon. After BlockTools.setup_plots is run, the config file needs to be re-read to refresh stale plot_directories. * Suppressing LGTM false positives regarding passphrase leakage in CLI error output. Seems that LGTM sees MIN_PASSPHRASE_LEN as sensitive data. * Second attempt at suppressing LGTM false positives * Third attempt at addressing LGTM false positives * Removed test_keyring_wrapper param from Keychain ctor. Test setup now sets the keyring_wrapper property directly. * Reformatting * More targeted update of the test config to refresh just the "plot_directories" value * More LGTM suppressions Co-authored-by: Adam Kelly <338792+aqk@users.noreply.github.com> Co-authored-by: wjblanke <wjb98672@gmail.com>
2021-08-04 22:46:55 +03:00
@unlocks_keyring(use_passphrase_cache=True)
def delete(fingerprint: int):
"""
Delete a key by its public key fingerprint (which is an integer).
"""
print(f"Deleting private_key with fingerprint {fingerprint}")
[CLI] chia keys derive [wallet-address | child-key | search] (#9184) * Added chia keys derive (wallet-address | child-key) to display derived wallet addresses or public keys * Support for public key (unhardened) derivation * Fleshed out the search command. Can perform a substring search on wallet addresses, public, and private keys. Support for deriving private keys * Default to unhardened derivation. Added --hardened-derivation option. HD paths denote hardened derivation with a 'h' suffix at each index. * Added --no-progress to reduce output. Exit code indicates search success/failure. Option name cleanup. * chia keys derive search can now search for multiple terms * chia keys derive search can be restricted to searching pubkeys|privkeys|addresses|all * Allow child-key derivation rooted from an arbitrary HD path * Search derived keys rooted under an arbitrary HD path * LGTM fixes * Remove extra master_sk_to_wallet_sk_unhardened definition * Cleanup and fixed search output * Cleanup and comments * Added tests for `chia keys` commands * Using @pytest_asyncio.fixture to decorate empty_keyring() as suggested in pytest's output. * Set asyncio-mode to auto to address pytest warning * See if tests pass without checking exit status * Added chia init step to tests that direclty invoke the `cli` function * Explicitly add --root-path option to tests that run the `cli` function. * Tests fix * Re-enable checks against exit_code * More fine tuning to address CI failures * Changes to address naming and other feedback * Updated tests
2022-01-26 07:42:16 +03:00
Keychain().delete_key_by_fingerprint(fingerprint)
[CLI] chia keys derive [wallet-address | child-key | search] (#9184) * Added chia keys derive (wallet-address | child-key) to display derived wallet addresses or public keys * Support for public key (unhardened) derivation * Fleshed out the search command. Can perform a substring search on wallet addresses, public, and private keys. Support for deriving private keys * Default to unhardened derivation. Added --hardened-derivation option. HD paths denote hardened derivation with a 'h' suffix at each index. * Added --no-progress to reduce output. Exit code indicates search success/failure. Option name cleanup. * chia keys derive search can now search for multiple terms * chia keys derive search can be restricted to searching pubkeys|privkeys|addresses|all * Allow child-key derivation rooted from an arbitrary HD path * Search derived keys rooted under an arbitrary HD path * LGTM fixes * Remove extra master_sk_to_wallet_sk_unhardened definition * Cleanup and fixed search output * Cleanup and comments * Added tests for `chia keys` commands * Using @pytest_asyncio.fixture to decorate empty_keyring() as suggested in pytest's output. * Set asyncio-mode to auto to address pytest warning * See if tests pass without checking exit status * Added chia init step to tests that direclty invoke the `cli` function * Explicitly add --root-path option to tests that run the `cli` function. * Tests fix * Re-enable checks against exit_code * More fine tuning to address CI failures * Changes to address naming and other feedback * Updated tests
2022-01-26 07:42:16 +03:00
def derive_sk_from_hd_path(master_sk: PrivateKey, hd_path_root: str) -> Tuple[PrivateKey, str]:
"""
Derive a private key from the provided HD path. Takes a master key and HD path as input,
and returns the derived key and the HD path that was used to derive it.
"""
[CLI] chia keys derive [wallet-address | child-key | search] (#9184) * Added chia keys derive (wallet-address | child-key) to display derived wallet addresses or public keys * Support for public key (unhardened) derivation * Fleshed out the search command. Can perform a substring search on wallet addresses, public, and private keys. Support for deriving private keys * Default to unhardened derivation. Added --hardened-derivation option. HD paths denote hardened derivation with a 'h' suffix at each index. * Added --no-progress to reduce output. Exit code indicates search success/failure. Option name cleanup. * chia keys derive search can now search for multiple terms * chia keys derive search can be restricted to searching pubkeys|privkeys|addresses|all * Allow child-key derivation rooted from an arbitrary HD path * Search derived keys rooted under an arbitrary HD path * LGTM fixes * Remove extra master_sk_to_wallet_sk_unhardened definition * Cleanup and fixed search output * Cleanup and comments * Added tests for `chia keys` commands * Using @pytest_asyncio.fixture to decorate empty_keyring() as suggested in pytest's output. * Set asyncio-mode to auto to address pytest warning * See if tests pass without checking exit status * Added chia init step to tests that direclty invoke the `cli` function * Explicitly add --root-path option to tests that run the `cli` function. * Tests fix * Re-enable checks against exit_code * More fine tuning to address CI failures * Changes to address naming and other feedback * Updated tests
2022-01-26 07:42:16 +03:00
from chia.wallet.derive_keys import _derive_path, _derive_path_unhardened
class DerivationType(Enum):
NONOBSERVER = 0
OBSERVER = 1
path: List[str] = hd_path_root.split("/")
if len(path) == 0 or path[0] != "m":
raise ValueError("Invalid HD path. Must start with 'm'")
path = path[1:] # Skip "m"
2022-01-29 02:34:39 +03:00
if len(path) > 0 and path[-1] == "": # remove trailing slash
[CLI] chia keys derive [wallet-address | child-key | search] (#9184) * Added chia keys derive (wallet-address | child-key) to display derived wallet addresses or public keys * Support for public key (unhardened) derivation * Fleshed out the search command. Can perform a substring search on wallet addresses, public, and private keys. Support for deriving private keys * Default to unhardened derivation. Added --hardened-derivation option. HD paths denote hardened derivation with a 'h' suffix at each index. * Added --no-progress to reduce output. Exit code indicates search success/failure. Option name cleanup. * chia keys derive search can now search for multiple terms * chia keys derive search can be restricted to searching pubkeys|privkeys|addresses|all * Allow child-key derivation rooted from an arbitrary HD path * Search derived keys rooted under an arbitrary HD path * LGTM fixes * Remove extra master_sk_to_wallet_sk_unhardened definition * Cleanup and fixed search output * Cleanup and comments * Added tests for `chia keys` commands * Using @pytest_asyncio.fixture to decorate empty_keyring() as suggested in pytest's output. * Set asyncio-mode to auto to address pytest warning * See if tests pass without checking exit status * Added chia init step to tests that direclty invoke the `cli` function * Explicitly add --root-path option to tests that run the `cli` function. * Tests fix * Re-enable checks against exit_code * More fine tuning to address CI failures * Changes to address naming and other feedback * Updated tests
2022-01-26 07:42:16 +03:00
path = path[:-1]
index_and_derivation_types: List[Tuple[int, DerivationType]] = []
# Validate path
for current_index_str in path:
if len(current_index_str) == 0:
raise ValueError("Invalid HD path. Empty index")
non_observer: bool = current_index_str[-1] == "n"
current_index: int = int(current_index_str[:-1]) if non_observer else int(current_index_str)
index_and_derivation_types.append(
(current_index, DerivationType.NONOBSERVER if non_observer else DerivationType.OBSERVER)
)
current_sk: PrivateKey = master_sk
# Derive keys along the path
for (current_index, derivation_type) in index_and_derivation_types:
if derivation_type == DerivationType.NONOBSERVER:
current_sk = _derive_path(current_sk, [current_index])
elif derivation_type == DerivationType.OBSERVER:
current_sk = _derive_path_unhardened(current_sk, [current_index])
else:
raise ValueError(f"Unhandled derivation type: {derivation_type}")
return (current_sk, "m/" + "/".join(path) + "/")
def sign(message: str, private_key: PrivateKey, hd_path: str, as_bytes: bool):
sk: PrivateKey = derive_sk_from_hd_path(private_key, hd_path)[0]
data = bytes.fromhex(message) if as_bytes else bytes(message, "utf-8")
print("Public key:", sk.get_g1())
print("Signature:", AugSchemeMPL.sign(sk, data))
def verify(message: str, public_key: str, signature: str):
messageBytes = bytes(message, "utf-8")
public_key = G1Element.from_bytes(bytes.fromhex(public_key))
signature = G2Element.from_bytes(bytes.fromhex(signature))
print(AugSchemeMPL.verify(public_key, messageBytes, signature))
[CLI] chia keys derive [wallet-address | child-key | search] (#9184) * Added chia keys derive (wallet-address | child-key) to display derived wallet addresses or public keys * Support for public key (unhardened) derivation * Fleshed out the search command. Can perform a substring search on wallet addresses, public, and private keys. Support for deriving private keys * Default to unhardened derivation. Added --hardened-derivation option. HD paths denote hardened derivation with a 'h' suffix at each index. * Added --no-progress to reduce output. Exit code indicates search success/failure. Option name cleanup. * chia keys derive search can now search for multiple terms * chia keys derive search can be restricted to searching pubkeys|privkeys|addresses|all * Allow child-key derivation rooted from an arbitrary HD path * Search derived keys rooted under an arbitrary HD path * LGTM fixes * Remove extra master_sk_to_wallet_sk_unhardened definition * Cleanup and fixed search output * Cleanup and comments * Added tests for `chia keys` commands * Using @pytest_asyncio.fixture to decorate empty_keyring() as suggested in pytest's output. * Set asyncio-mode to auto to address pytest warning * See if tests pass without checking exit status * Added chia init step to tests that direclty invoke the `cli` function * Explicitly add --root-path option to tests that run the `cli` function. * Tests fix * Re-enable checks against exit_code * More fine tuning to address CI failures * Changes to address naming and other feedback * Updated tests
2022-01-26 07:42:16 +03:00
def migrate_keys():
from chia.util.keyring_wrapper import KeyringWrapper
from chia.util.misc import prompt_yes_no
# Check if the keyring needs a full migration (i.e. if it's using the old keyring)
if Keychain.needs_migration():
KeyringWrapper.get_shared_instance().migrate_legacy_keyring_interactive()
else:
keys_to_migrate, legacy_keyring = Keychain.get_keys_needing_migration()
if len(keys_to_migrate) > 0 and legacy_keyring is not None:
print(f"Found {len(keys_to_migrate)} key(s) that need migration:")
for key, _ in keys_to_migrate:
print(f"Fingerprint: {key.get_g1().get_fingerprint()}")
print()
response = prompt_yes_no("Migrate these keys? (y/n) ")
if response:
keychain = Keychain()
for sk, seed_bytes in keys_to_migrate:
mnemonic = bytes_to_mnemonic(seed_bytes)
keychain.add_private_key(mnemonic, "")
fingerprint = sk.get_g1().get_fingerprint()
print(f"Added private key with public key fingerprint {fingerprint}")
print(f"Migrated {len(keys_to_migrate)} key(s)")
print("Verifying migration results...", end="")
if Keychain.verify_keys_present(keys_to_migrate):
print(" Verified")
print()
response = prompt_yes_no("Remove key(s) from old keyring? (y/n) ")
if response:
legacy_keyring.delete_keys(keys_to_migrate)
print(f"Removed {len(keys_to_migrate)} key(s) from old keyring")
print("Migration complete")
else:
print(" Failed")
sys.exit(1)
else:
print("No keys need migration")
Keychain.mark_migration_checked_for_current_version()
[CLI] chia keys derive [wallet-address | child-key | search] (#9184) * Added chia keys derive (wallet-address | child-key) to display derived wallet addresses or public keys * Support for public key (unhardened) derivation * Fleshed out the search command. Can perform a substring search on wallet addresses, public, and private keys. Support for deriving private keys * Default to unhardened derivation. Added --hardened-derivation option. HD paths denote hardened derivation with a 'h' suffix at each index. * Added --no-progress to reduce output. Exit code indicates search success/failure. Option name cleanup. * chia keys derive search can now search for multiple terms * chia keys derive search can be restricted to searching pubkeys|privkeys|addresses|all * Allow child-key derivation rooted from an arbitrary HD path * Search derived keys rooted under an arbitrary HD path * LGTM fixes * Remove extra master_sk_to_wallet_sk_unhardened definition * Cleanup and fixed search output * Cleanup and comments * Added tests for `chia keys` commands * Using @pytest_asyncio.fixture to decorate empty_keyring() as suggested in pytest's output. * Set asyncio-mode to auto to address pytest warning * See if tests pass without checking exit status * Added chia init step to tests that direclty invoke the `cli` function * Explicitly add --root-path option to tests that run the `cli` function. * Tests fix * Re-enable checks against exit_code * More fine tuning to address CI failures * Changes to address naming and other feedback * Updated tests
2022-01-26 07:42:16 +03:00
def _clear_line_part(n: int):
# Move backward, overwrite with spaces, then move backward again
sys.stdout.write("\b" * n)
sys.stdout.write(" " * n)
sys.stdout.write("\b" * n)
def _search_derived(
current_sk: PrivateKey,
search_terms: Tuple[str, ...],
path: str,
path_indices: Optional[List[int]],
limit: int,
non_observer_derivation: bool,
show_progress: bool,
search_public_key: bool,
search_private_key: bool,
search_address: bool,
) -> List[str]: # Return a subset of search_terms that were found
"""
Performs a shallow search of keys derived from the current sk for items matching
the provided search terms.
"""
from chia.wallet.derive_keys import _derive_path, _derive_path_unhardened
class DerivedSearchResultType(Enum):
PUBLIC_KEY = "public key"
PRIVATE_KEY = "private key"
WALLET_ADDRESS = "wallet address"
remaining_search_terms: Dict[str, None] = dict.fromkeys(search_terms)
current_path: str = path
current_path_indices: List[int] = path_indices if path_indices is not None else []
found_search_terms: List[str] = []
for index in range(limit):
found_items: List[Tuple[str, str, DerivedSearchResultType]] = []
printed_match: bool = False
current_index_str = str(index) + ("n" if non_observer_derivation else "")
current_path += f"{current_index_str}"
current_path_indices.append(index)
if show_progress:
# Output just the current index e.g. "25" or "25n"
sys.stdout.write(f"{current_index_str}")
sys.stdout.flush()
# Derive the private key
if non_observer_derivation:
child_sk = _derive_path(current_sk, current_path_indices)
else:
child_sk = _derive_path_unhardened(current_sk, current_path_indices)
child_pk: Optional[G1Element] = None
# Public key is needed for searching against wallet addresses or public keys
if search_public_key or search_address:
child_pk = child_sk.get_g1()
address: Optional[str] = None
if search_address:
# Generate a wallet address using the standard p2_delegated_puzzle_or_hidden_puzzle puzzle
# TODO: consider generating addresses using other puzzles
address = encode_puzzle_hash(create_puzzlehash_for_pk(child_pk), "xch")
for term in remaining_search_terms:
found_item: Any = None
found_item_type: Optional[DerivedSearchResultType] = None
if search_private_key and term in str(child_sk):
found_item = private_key_string_repr(child_sk)
found_item_type = DerivedSearchResultType.PRIVATE_KEY
elif search_public_key and child_pk is not None and term in str(child_pk):
found_item = child_pk
found_item_type = DerivedSearchResultType.PUBLIC_KEY
elif search_address and address is not None and term in address:
found_item = address
found_item_type = DerivedSearchResultType.WALLET_ADDRESS
if found_item is not None and found_item_type is not None:
found_items.append((term, found_item, found_item_type))
if len(found_items) > 0 and show_progress:
print()
for (term, found_item, found_item_type) in found_items:
# Update remaining_search_terms and found_search_terms
del remaining_search_terms[term]
found_search_terms.append(term)
print(
f"Found {found_item_type.value}: {found_item} (HD path: {current_path})"
) # lgtm [py/clear-text-logging-sensitive-data]
printed_match = True
if len(remaining_search_terms) == 0:
break
# Remove the last index from the path
current_path = current_path[: -len(str(current_index_str))]
current_path_indices = current_path_indices[:-1]
if show_progress:
if printed_match:
# Write the path (without current_index_str) since we printed out a match
# e.g. m/12381/8444/2/
sys.stdout.write(f"{current_path}") # lgtm [py/clear-text-logging-sensitive-data]
# Remove the last index from the output
else:
_clear_line_part(len(current_index_str))
return found_search_terms
def search_derive(
private_key: Optional[PrivateKey],
search_terms: Tuple[str, ...],
limit: int,
non_observer_derivation: bool,
show_progress: bool,
search_types: Tuple[str, ...],
derive_from_hd_path: Optional[str],
) -> bool:
"""
Searches for items derived from the provided private key, or if not specified,
search each private key in the keyring.
"""
from time import perf_counter
start_time = perf_counter()
private_keys: List[PrivateKey]
remaining_search_terms: Dict[str, None] = dict.fromkeys(search_terms) # poor man's ordered set
search_address = "address" in search_types
search_public_key = "public_key" in search_types
search_private_key = "private_key" in search_types
if "all" in search_types:
search_address = True
search_public_key = True
search_private_key = True
if private_key is None:
private_keys = [sk for sk, _ in Keychain().get_all_private_keys()]
else:
private_keys = [private_key]
for sk in private_keys:
current_path: str = ""
found_terms: List[str] = []
if show_progress:
print(f"Searching keys derived from: {sk.get_g1().get_fingerprint()}")
# Derive from the provided HD path
if derive_from_hd_path is not None:
derivation_root_sk, hd_path_root = derive_sk_from_hd_path(sk, derive_from_hd_path)
if show_progress:
sys.stdout.write(hd_path_root)
# Shallow search under hd_path_root
found_terms = _search_derived(
derivation_root_sk,
tuple(remaining_search_terms.keys()),
hd_path_root,
None,
limit,
non_observer_derivation,
show_progress,
search_public_key,
search_private_key,
search_address,
)
# Update remaining_search_terms
for term in found_terms:
del remaining_search_terms[term]
if len(remaining_search_terms) == 0:
# Found everything we were looking for
break
current_path = hd_path_root
# Otherwise derive from well-known derivation paths
else:
current_path_indices: List[int] = [12381, 8444]
path_root: str = "m/"
for i in [12381, 8444]:
path_root += f"{i}{'n' if non_observer_derivation else ''}/"
if show_progress:
# Print the path root (without last index)
# e.g. m/12381/8444/
sys.stdout.write(path_root)
# 7 account levels for derived keys (0-6):
# 0 = farmer, 1 = pool, 2 = wallet, 3 = local, 4 = backup key, 5 = singleton, 6 = pooling authentication
for account in range(7):
account_str = str(account) + ("n" if non_observer_derivation else "")
current_path = path_root + f"{account_str}/"
current_path_indices.append(account)
if show_progress:
# Print the current path index
# e.g. 2/ (example full output: m/12381/8444/2/)
sys.stdout.write(f"{account_str}/") # lgtm [py/clear-text-logging-sensitive-data]
found_terms = _search_derived(
sk,
tuple(remaining_search_terms.keys()),
current_path,
list(current_path_indices), # copy
limit,
non_observer_derivation,
show_progress,
search_public_key,
search_private_key,
search_address,
)
# Update remaining_search_terms
for found_term in found_terms:
del remaining_search_terms[found_term]
if len(remaining_search_terms) == 0:
# Found everything we were looking for
break
if show_progress:
# +1 to remove the trailing slash
_clear_line_part(1 + len(str(account_str)))
current_path_indices = current_path_indices[:-1]
if len(remaining_search_terms) == 0:
# Found everything we were looking for
break
if show_progress:
# +1 to remove the trailing slash
_clear_line_part(1 + len(current_path))
sys.stdout.flush()
end_time = perf_counter()
if len(remaining_search_terms) > 0:
for term in remaining_search_terms:
print(f"Could not find '{term}'")
if show_progress:
print()
print(f"Search completed in {end_time - start_time} seconds")
return len(remaining_search_terms) == 0
def derive_wallet_address(
root_path: Path,
private_key: PrivateKey,
index: int,
count: int,
prefix: Optional[str],
non_observer_derivation: bool,
show_hd_path: bool,
):
"""
Generate wallet addresses using keys derived from the provided private key.
"""
if prefix is None:
config: Dict = load_config(root_path, "config.yaml")
selected: str = config["selected_network"]
prefix = config["network_overrides"]["config"][selected]["address_prefix"]
path_indices: List[int] = [12381, 8444, 2]
wallet_hd_path_root: str = "m/"
for i in path_indices:
wallet_hd_path_root += f"{i}{'n' if non_observer_derivation else ''}/"
for i in range(index, index + count):
if non_observer_derivation:
sk = master_sk_to_wallet_sk(private_key, uint32(i))
else:
sk = master_sk_to_wallet_sk_unhardened(private_key, uint32(i))
# Generate a wallet address using the standard p2_delegated_puzzle_or_hidden_puzzle puzzle
# TODO: consider generating addresses using other puzzles
address = encode_puzzle_hash(create_puzzlehash_for_pk(sk.get_g1()), prefix)
if show_hd_path:
print(
f"Wallet address {i} "
f"({wallet_hd_path_root + str(i) + ('n' if non_observer_derivation else '')}): {address}"
)
else:
print(f"Wallet address {i}: {address}")
def private_key_string_repr(private_key: PrivateKey):
"""Print a PrivateKey in a human-readable formats"""
s: str = str(private_key)
return s[len("<PrivateKey ") : s.rfind(">")] if s.startswith("<PrivateKey ") else s
def derive_child_key(
master_sk: PrivateKey,
key_type: Optional[str],
derive_from_hd_path: Optional[str],
index: int,
count: int,
non_observer_derivation: bool,
show_private_keys: bool,
show_hd_path: bool,
):
"""
Derive child keys from the provided master key.
"""
from chia.wallet.derive_keys import _derive_path, _derive_path_unhardened
derivation_root_sk: Optional[PrivateKey] = None
hd_path_root: Optional[str] = None
current_sk: Optional[PrivateKey] = None
# Key type was specified
if key_type is not None:
path_indices: List[int] = [12381, 8444]
path_indices.append(
{
"farmer": 0,
"pool": 1,
"wallet": 2,
"local": 3,
"backup": 4,
"singleton": 5,
"pool_auth": 6,
}[key_type]
)
if non_observer_derivation:
current_sk = _derive_path(master_sk, path_indices)
else:
current_sk = _derive_path_unhardened(master_sk, path_indices)
derivation_root_sk = current_sk
hd_path_root = "m/"
for i in path_indices:
hd_path_root += f"{i}{'n' if non_observer_derivation else ''}/"
# Arbitrary HD path was specified
elif derive_from_hd_path is not None:
derivation_root_sk, hd_path_root = derive_sk_from_hd_path(master_sk, derive_from_hd_path)
# Derive child keys from derivation_root_sk
if derivation_root_sk is not None and hd_path_root is not None:
for i in range(index, index + count):
if non_observer_derivation:
sk = _derive_path(derivation_root_sk, [i])
else:
sk = _derive_path_unhardened(derivation_root_sk, [i])
hd_path: str = (
" (" + hd_path_root + str(i) + ("n" if non_observer_derivation else "") + ")" if show_hd_path else ""
)
key_type_str: Optional[str]
if key_type is not None:
key_type_str = key_type.capitalize()
else:
key_type_str = "Non-Observer" if non_observer_derivation else "Observer"
print(f"{key_type_str} public key {i}{hd_path}: {sk.get_g1()}")
if show_private_keys:
print(f"{key_type_str} private key {i}{hd_path}: {private_key_string_repr(sk)}")
@unlocks_keyring(use_passphrase_cache=True)
def private_key_for_fingerprint(fingerprint: int) -> Optional[PrivateKey]:
private_keys = Keychain().get_all_private_keys()
for sk, _ in private_keys:
if sk.get_g1().get_fingerprint() == fingerprint:
return sk
return None
def get_private_key_with_fingerprint_or_prompt(fingerprint: Optional[int]):
"""
Get a private key with the specified fingerprint. If fingerprint is not
specified, prompt the user to select a key.
"""
# Return the private key matching the specified fingerprint
if fingerprint is not None:
return private_key_for_fingerprint(fingerprint)
fingerprints: List[int] = [pk.get_fingerprint() for pk in Keychain().get_all_public_keys()]
while True:
print("Choose key:")
for i, fp in enumerate(fingerprints):
print(f"{i+1}) {fp}")
val = None
while val is None:
val = input("Enter a number to pick or q to quit: ")
if val == "q":
return None
if not val.isdigit():
val = None
else:
index = int(val) - 1
if index >= len(fingerprints):
print("Invalid value")
val = None
continue
else:
return private_key_for_fingerprint(fingerprints[index])
def private_key_from_mnemonic_seed_file(filename: Path) -> PrivateKey:
"""
Create a private key from a mnemonic seed file.
"""
mnemonic = filename.read_text().rstrip()
seed = mnemonic_to_seed(mnemonic, "")
return AugSchemeMPL.key_gen(seed)
def resolve_derivation_master_key(fingerprint_or_filename: Optional[Union[int, str, Path]]) -> PrivateKey:
"""
Given a key fingerprint of file containing a mnemonic seed, return the private key.
"""
if fingerprint_or_filename is not None and (
isinstance(fingerprint_or_filename, str) or isinstance(fingerprint_or_filename, Path)
):
return private_key_from_mnemonic_seed_file(Path(os.fspath(fingerprint_or_filename)))
else:
return get_private_key_with_fingerprint_or_prompt(fingerprint_or_filename)