def _delete_plot(self, str_path: str): if str_path in self.provers: del self.provers[str_path] plot_root = path_from_root(self.root_path, self.config.get("plot_root", ".")) # Remove absolute and relative paths if Path(str_path).exists(): Path(str_path).unlink() if (plot_root / Path(str_path)).exists(): (plot_root / Path(str_path)).unlink() try: # Removes the plot from config.yaml plot_config = load_config(self.root_path, "plots.yaml") if str_path in plot_config["plots"]: del plot_config["plots"][str_path] save_config(self.root_path, "plots.yaml", plot_config) self.plot_config = plot_config except (FileNotFoundError, KeyError) as e: log.warning(f"Could not remove {str_path} {e}") return False self._state_changed("plots") return True
async def setup_daemon(port, alert_url, pubkey): btools = BlockTools(constants=test_constants) root_path = btools.root_path config = btools.config config["daemon_port"] = port lockfile = singleton(daemon_launch_lock_path(root_path)) crt_path = root_path / config["daemon_ssl"]["private_crt"] key_path = root_path / config["daemon_ssl"]["private_key"] ca_crt_path = root_path / config["private_ssl_ca"]["crt"] ca_key_path = root_path / config["private_ssl_ca"]["key"] # TODO: make overrides configurable config["selected_network"] = "testnet5" config["ALERTS_URL"] = alert_url config["CHIA_ALERTS_PUBKEY"] = pubkey config["network_overrides"]["constants"]["testnet5"][ "GENESIS_CHALLENGE"] = None btools._config = config save_config(root_path, "config.yaml", btools._config) assert lockfile is not None create_server_for_daemon(btools.root_path) ws_server = WebSocketServer(root_path, ca_crt_path, ca_key_path, crt_path, key_path) await ws_server.start() yield ws_server await ws_server.stop()
def _add_plot( self, str_path: str, plot_sk: PrivateKey, pool_pk: Optional[PublicKey] ) -> bool: plot_config = load_config(self.root_path, "plots.yaml") if pool_pk is None: for pool_pk_cand in self.pool_pubkeys: pr = DiskProver(str_path) if ( ProofOfSpace.calculate_plot_seed( pool_pk_cand, plot_sk.get_public_key() ) == pr.get_id() ): pool_pk = pool_pk_cand break if pool_pk is None: return False plot_config["plots"][str_path] = { "sk": bytes(plot_sk).hex(), "pool_pk": bytes(pool_pk).hex(), } save_config(self.root_path, "plots.yaml", plot_config) self._refresh_plots() return True
def migrate_from( old_root: Path, new_root: Path, manifest: List[str], do_not_migrate_settings: List[str], ): """ Copy all the files in "manifest" to the new config directory. """ if old_root == new_root: print("same as new path, exiting") return 1 if not old_root.is_dir(): print(f"{old_root} not found - this is ok if you did not install this version") return 0 print(f"\n{old_root} found") print(f"Copying files from {old_root} to {new_root}\n") for f in manifest: old_path = old_root / f new_path = new_root / f copy_files_rec(old_path, new_path) # update config yaml with new keys config: Dict = load_config(new_root, "config.yaml") config_str: str = initial_config_file("config.yaml") default_config: Dict = yaml.safe_load(config_str) flattened_keys = unflatten_properties({k: "" for k in do_not_migrate_settings}) dict_add_new_default(config, default_config, flattened_keys) save_config(new_root, "config.yaml", config) create_all_ssl(new_root) return 1
def check_keys(new_root): keychain: Keychain = Keychain() all_sks = keychain.get_all_private_keys() if len(all_sks) == 0: print("No keys are present in the keychain. Generate them with 'chia keys generate'") return config: Dict = load_config(new_root, "config.yaml") pool_child_pubkeys = [master_sk_to_pool_sk(sk).get_g1() for sk, _ in all_sks] all_targets = [] stop_searching_for_farmer = "xch_target_address" not in config["farmer"] stop_searching_for_pool = "xch_target_address" not in config["pool"] number_of_ph_to_search = 500 selected = config["selected_network"] prefix = config["network_overrides"]["config"][selected]["address_prefix"] for i in range(number_of_ph_to_search): if stop_searching_for_farmer and stop_searching_for_pool and i > 0: break for sk, _ in all_sks: all_targets.append( encode_puzzle_hash(create_puzzlehash_for_pk(master_sk_to_wallet_sk(sk, uint32(i)).get_g1()), prefix) ) if all_targets[-1] == config["farmer"].get("xch_target_address"): stop_searching_for_farmer = True if all_targets[-1] == config["pool"].get("xch_target_address"): stop_searching_for_pool = True # Set the destinations if "xch_target_address" not in config["farmer"]: print(f"Setting the xch destination address for coinbase fees reward to {all_targets[0]}") config["farmer"]["xch_target_address"] = all_targets[0] elif config["farmer"]["xch_target_address"] not in all_targets: print( f"WARNING: using a farmer address which we don't have the private" f" keys for. We searched the first {number_of_ph_to_search} addresses. Consider overriding " f"{config['farmer']['xch_target_address']} with {all_targets[0]}" ) if "pool" not in config: config["pool"] = {} if "xch_target_address" not in config["pool"]: print(f"Setting the xch destination address for coinbase reward to {all_targets[0]}") config["pool"]["xch_target_address"] = all_targets[0] elif config["pool"]["xch_target_address"] not in all_targets: print( f"WARNING: using a pool address which we don't have the private" f" keys for. We searched the first {number_of_ph_to_search} addresses. Consider overriding " f"{config['pool']['xch_target_address']} with {all_targets[0]}" ) # Set the pool pks in the farmer pool_pubkeys_hex = set(bytes(pk).hex() for pk in pool_child_pubkeys) if "pool_public_keys" in config["farmer"]: for pk_hex in config["farmer"]["pool_public_keys"]: # Add original ones in config pool_pubkeys_hex.add(pk_hex) config["farmer"]["pool_public_keys"] = pool_pubkeys_hex save_config(new_root, "config.yaml", config)
def add_plot_directory(str_path: str, root_path: Path) -> Dict: config = load_config(root_path, "config.yaml") if str(Path(str_path).resolve() ) not in config["harvester"]["plot_directories"]: config["harvester"]["plot_directories"].append( str(Path(str_path).resolve())) save_config(root_path, "config.yaml", config) return config
async def _add_plot_directory(self, str_path: str) -> bool: config = load_config(self.root_path, "config.yaml") if str(Path(str_path).resolve() ) not in config["harvester"]["plot_directories"]: config["harvester"]["plot_directories"].append( str(Path(str_path).resolve())) save_config(self.root_path, "config.yaml", config) await self._refresh_plots() return True
def configure(args, parser): config: Dict = load_config(DEFAULT_ROOT_PATH, "config.yaml") change_made = False if args.set_node_introducer: try: if args.set_node_introducer.index(":"): host, port = ( ":".join(args.set_node_introducer.split(":")[:-1]), args.set_node_introducer.split(":")[-1], ) config["full_node"]["introducer_peer"]["host"] = host config["full_node"]["introducer_peer"]["port"] = int(port) config["introducer"]["port"] = int(port) print("Node introducer updated.") change_made = True except ValueError: print("Node introducer address must be in format [IP:Port]") if args.set_fullnode_port: config["full_node"]["port"] = int(args.set_fullnode_port) config["full_node"]["introducer_peer"]["port"] = int( args.set_fullnode_port) config["farmer"]["full_node_peer"]["port"] = int( args.set_fullnode_port) config["timelord"]["full_node_peer"]["port"] = int( args.set_fullnode_port) config["wallet"]["full_node_peer"]["port"] = int( args.set_fullnode_port) config["wallet"]["introducer_peer"]["port"] = int( args.set_fullnode_port) config["introducer"]["port"] = int(args.set_fullnode_port) print("Default full node port updated.") change_made = True if args.set_log_level: if ((args.set_log_level == "CRITICAL") or (args.set_log_level == "ERROR") or (args.set_log_level == "WARNING") or (args.set_log_level == "INFO") or (args.set_log_level == "DEBUG") or (args.set_log_level == "NOTSET")): config["logging"]["log_level"] = args.set_log_level print("Logging level updated. Check CHIA_ROOT/log/debug.log") change_made = True if args.enable_upnp is not None: config["full_node"]["enable_upnp"] = str2bool(args.enable_upnp) if str2bool(args.enable_upnp): print("uPnP enabled.") else: print("uPnP disabled.") change_made = True if change_made: print("Restart any running chia services for changes to take effect.") save_config(args.root_path, "config.yaml", config) else: help_message() return 0
def migrate_from( old_root: Path, new_root: Path, manifest: List[str], do_not_migrate_settings: List[str], ): """ Copy all the files in "manifest" to the new config directory. """ if old_root == new_root: print("same as new path, exiting") return 1 if not old_root.is_dir(): print( f"{old_root} not found - this is ok if you did not install this version." ) return 0 print(f"\n{old_root} found") print(f"Copying files from {old_root} to {new_root}\n") not_found = [] def copy_files_rec(old_path: Path, new_path: Path): if old_path.is_file(): print(f"{new_path}") mkdir(new_path.parent) shutil.copy(old_path, new_path) elif old_path.is_dir(): for old_path_child in old_path.iterdir(): new_path_child = new_path / old_path_child.name copy_files_rec(old_path_child, new_path_child) else: not_found.append(f) print(f"{old_path} not found, skipping") for f in manifest: old_path = old_root / f new_path = new_root / f copy_files_rec(old_path, new_path) # update config yaml with new keys config: Dict = load_config(new_root, "config.yaml") config_str: str = initial_config_file("config.yaml") default_config: Dict = yaml.safe_load(config_str) flattened_keys = unflatten_properties( {k: "" for k in do_not_migrate_settings}) dict_add_new_default(config, default_config, flattened_keys) save_config(new_root, "config.yaml", config) if "config/trusted.key" in not_found or "config/trusted.key" in not_found: initialize_ssl(new_root) return 1
def set_reward_targets(self, farmer_target_encoded: Optional[str], pool_target_encoded: Optional[str]): config = load_config(self._root_path, "config.yaml") if farmer_target_encoded is not None: self.farmer_target_encoded = farmer_target_encoded self.farmer_target = decode_puzzle_hash(farmer_target_encoded) config["farmer"]["xch_target_address"] = farmer_target_encoded if pool_target_encoded is not None: self.pool_target_encoded = pool_target_encoded self.pool_target = decode_puzzle_hash(pool_target_encoded) config["pool"]["xch_target_address"] = pool_target_encoded save_config(self._root_path, "config.yaml", config)
def remove_plot_directory(str_path: str, root_path: Path) -> None: config = load_config(root_path, "config.yaml") str_paths: List[str] = config["harvester"]["plot_directories"] # If path str matches exactly, remove if str_path in str_paths: str_paths.remove(str_path) # If path matcehs full path, remove new_paths = [Path(sp).resolve() for sp in str_paths] if Path(str_path).resolve() in new_paths: new_paths.remove(Path(str_path).resolve()) config["harvester"]["plot_directories"] = [str(np) for np in new_paths] save_config(root_path, "config.yaml", config)
def configure(root_path: Path, set_node_introducer: str, set_fullnode_port: str, set_log_level: str, enable_upnp: str): config: Dict = load_config(DEFAULT_ROOT_PATH, "config.yaml") change_made = False if set_node_introducer: try: if set_node_introducer.index(":"): host, port = ( ":".join(set_node_introducer.split(":")[:-1]), set_node_introducer.split(":")[-1], ) config["full_node"]["introducer_peer"]["host"] = host config["full_node"]["introducer_peer"]["port"] = int(port) config["introducer"]["port"] = int(port) print("Node introducer updated") change_made = True except ValueError: print("Node introducer address must be in format [IP:Port]") if set_fullnode_port: config["full_node"]["port"] = int(set_fullnode_port) config["full_node"]["introducer_peer"]["port"] = int(set_fullnode_port) config["farmer"]["full_node_peer"]["port"] = int(set_fullnode_port) config["timelord"]["full_node_peer"]["port"] = int(set_fullnode_port) config["wallet"]["full_node_peer"]["port"] = int(set_fullnode_port) config["wallet"]["introducer_peer"]["port"] = int(set_fullnode_port) config["introducer"]["port"] = int(set_fullnode_port) print("Default full node port updated") change_made = True if set_log_level: levels = ["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "NOTSET"] if set_log_level in levels: config["logging"]["log_level"] = set_log_level print( f"Logging level updated. Check {DEFAULT_ROOT_PATH}/log/debug.log" ) change_made = True else: print(f"Logging level not updated. Use one of: {levels}") if enable_upnp is not None: config["full_node"]["enable_upnp"] = str2bool(enable_upnp) if str2bool(enable_upnp): print("uPnP enabled") else: print("uPnP disabled") change_made = True if change_made: print("Restart any running chia services for changes to take effect") save_config(root_path, "config.yaml", config) return 0
def check_keys(new_root): print("\nchecking keys.yaml") keys_config = load_config(new_root, "keys.yaml") wallet_sk = ExtendedPrivateKey.from_bytes( bytes.fromhex(keys_config["wallet_sk"])) wallet_target = create_puzzlehash_for_pk( BLSPublicKey(bytes(wallet_sk.public_child(0).get_public_key()))) if (wallet_target.hex() != keys_config["wallet_target"] or wallet_target.hex() != keys_config["pool_target"]): keys_config["wallet_target"] = wallet_target.hex() keys_config["pool_target"] = wallet_target.hex() print( f"updating wallet target and pool target to {wallet_target.hex()}") save_config(new_root, "keys.yaml", keys_config)
def migrate_from( old_root: Path, new_root: Path, manifest: List[str], do_not_migrate_settings: List[str], ): """ Copy all the files in "manifest" to the new config directory. """ if old_root == new_root: print("same as new path, exiting") return 1 if not old_root.is_dir(): print( f"{old_root} not found - this is ok if you did not install this version." ) return 0 print(f"\n{old_root} found") print(f"Copying files from {old_root} to {new_root}\n") not_found = [] for f in manifest: old_path = old_root / f new_path = new_root / f if old_path.is_file(): print(f"{new_path}") mkdir(new_path.parent) shutil.copy(old_path, new_path) else: not_found.append(f) print(f"{old_path} not found, skipping") # update config yaml with new keys config: Dict = load_config(new_root, "config.yaml") config_str: str = initial_config_file("config.yaml") default_config: Dict = yaml.safe_load(config_str) flattened_keys = unflatten_properties( {k: "" for k in do_not_migrate_settings}) dict_add_new_default(config, default_config, flattened_keys) save_config(new_root, "config.yaml", config) # migrate plots # for now, we simply leave them where they are # and make what may have been relative paths absolute if "config/trusted.key" in not_found or "config/trusted.key" in not_found: initialize_ssl(new_root) return 1
def generate(args, parser): root_path = args.root_path keys_yaml = "keys.yaml" key_config_filename = config_path_for_filename(root_path, keys_yaml) if args.keys != ["keys"]: parser.print_help() print("\nTry `chia generate keys`") return 1 if key_config_filename.exists(): # If the file exists, warn the user yn = input( f"The keys file {key_config_filename} already exists. Are you sure" f" you want to override the keys? Plots might become invalid. (y/n): " ) if not (yn.lower() == "y" or yn.lower() == "yes"): return 1 else: # Create the file if if doesn't exist mkdir(key_config_filename.parent) open(key_config_filename, "a").close() key_config = load_config(root_path, keys_yaml) if key_config is None: key_config = {} wallet_target = None if args.wallet: wallet_sk = ExtendedPrivateKey.from_seed(token_bytes(32)) wallet_target = create_puzzlehash_for_pk( BLSPublicKey(bytes(wallet_sk.public_child(0).get_public_key())) ) key_config["wallet_sk"] = bytes(wallet_sk).hex() key_config["wallet_target"] = wallet_target.hex() save_config(root_path, keys_yaml, key_config) if args.harvester: # Replaces the harvester's sk seed. Used to generate plot private keys, which are # used to sign farmed blocks. key_config["sk_seed"] = token_bytes(32).hex() save_config(root_path, keys_yaml, key_config) if args.pool: # Replaces the pools keys and targes. Only useful if running a pool, or doing # solo farming. The pool target allows spending of the coinbase. pool_sks = [PrivateKey.from_seed(token_bytes(32)) for _ in range(2)] if wallet_target is None: pool_target = create_puzzlehash_for_pk( BLSPublicKey(bytes(pool_sks[0].get_public_key())) ) else: pool_target = wallet_target key_config["pool_sks"] = [bytes(pool_sk).hex() for pool_sk in pool_sks] key_config["pool_target"] = pool_target.hex() save_config(root_path, keys_yaml, key_config) if args.pooltarget: # Compute a new pool target and save it to the config assert "wallet_target" in key_config key_config["pool_target"] = key_config["wallet_target"] save_config(root_path, keys_yaml, key_config)
def check_keys(new_root): keychain: Keychain = Keychain() all_pubkeys = keychain.get_all_public_keys() if len(all_pubkeys) == 0: print( "No keys are present in the keychain. Generate them with 'chia keys generate_and_add'" ) return all_targets = [ create_puzzlehash_for_pk( BLSPublicKey(bytes(epk.public_child(0).get_public_key())) ).hex() for epk in all_pubkeys ] config: Dict = load_config(new_root, "config.yaml") # Set the destinations if ( "xch_target_puzzle_hash" not in config["farmer"] or config["farmer"]["xch_target_puzzle_hash"] not in all_targets ): print( f"Setting the xch destination address for coinbase fees reward to {all_targets[0]}" ) config["farmer"]["xch_target_puzzle_hash"] = all_targets[0] if "pool" in config: if ( "xch_target_puzzle_hash" not in config["pool"] or config["pool"]["xch_target_puzzle_hash"] not in all_targets ): print( f"Setting the xch destination address for coinbase reward to {all_targets[0]}" ) config["pool"]["xch_target_puzzle_hash"] = all_targets[0] # Set the pool pks in the farmer all_pubkeys_hex = set([bytes(pk.get_public_key()).hex() for pk in all_pubkeys]) if "pool_public_keys" in config["farmer"]: for pk_hex in config["farmer"]["pool_public_keys"]: # Add original ones in config all_pubkeys_hex.add(pk_hex) config["farmer"]["pool_public_keys"] = all_pubkeys_hex save_config(new_root, "config.yaml", config)
async def check_for_alerts(self): while True: try: if self.shut_down: break await asyncio.sleep(2) selected = self.net_config["selected_network"] alert_url = self.net_config["ALERTS_URL"] log.debug("Fetching alerts") response = await fetch(alert_url) log.debug(f"Fetched alert: {response}") if response is None: continue json_response = json.loads(response) if "data" in json_response: pubkey = self.net_config["CHIA_ALERTS_PUBKEY"] validated = validate_alert(response, pubkey) if validated is False: self.log.error( f"Error unable to validate alert! {response}") continue data = json_response["data"] data_json = json.loads(data) if data_json["ready"] is False: # Network not launched yet log.info("Network is not ready yet") continue challenge = data_json["genesis_challenge"] self.net_config["network_overrides"]["constants"][ selected]["GENESIS_CHALLENGE"] = challenge save_config(self.root_path, "config.yaml", self.net_config) self.genesis_initialized = True break except Exception as e: log.error(f"Exception in check alerts task: {e}")
def main(): """ Script for creating plots and adding them to the plot config file. """ root_path = DEFAULT_ROOT_PATH plot_config_filename = config_path_for_filename(root_path, "plots.yaml") key_config_filename = config_path_for_filename(root_path, "keys.yaml") parser = argparse.ArgumentParser(description="Chia plotting script.") parser.add_argument("-k", "--size", help="Plot size", type=int, default=20) parser.add_argument("-n", "--num_plots", help="Number of plots", type=int, default=10) parser.add_argument("-i", "--index", help="First plot index", type=int, default=0) parser.add_argument("-p", "--pool_pub_key", help="Hex public key of pool", type=str, default="") parser.add_argument( "-t", "--tmp_dir", help= "Temporary directory for plotting files (relative to final directory)", type=Path, default=Path("./plots.tmp"), ) new_plots_root = path_from_root( root_path, load_config(root_path, "config.yaml").get("harvester", {}).get("new_plot_root", "plots"), ) parser.add_argument( "-d", "--final_dir", help="Final directory for plots (relative or absolute)", type=Path, default=new_plots_root, ) # We need the keys file, to access pool keys (if the exist), and the sk_seed. args = parser.parse_args() if not key_config_filename.exists(): raise RuntimeError("Keys not generated. Run chia-generate-keys") # The seed is what will be used to generate a private key for each plot key_config = load_config(root_path, key_config_filename) sk_seed: bytes = bytes.fromhex(key_config["sk_seed"]) pool_pk: PublicKey if len(args.pool_pub_key) > 0: # Use the provided pool public key, useful for using an external pool pool_pk = PublicKey.from_bytes(bytes.fromhex(args.pool_pub_key)) else: # Use the pool public key from the config, useful for solo farming pool_sk = PrivateKey.from_bytes( bytes.fromhex(key_config["pool_sks"][0])) pool_pk = pool_sk.get_public_key() print( f"Creating {args.num_plots} plots, from index {args.index} to " f"{args.index + args.num_plots - 1}, of size {args.size}, sk_seed {sk_seed.hex()} ppk {pool_pk}" ) tmp_dir = args.final_dir / args.tmp_dir mkdir(tmp_dir) mkdir(args.final_dir) for i in range(args.index, args.index + args.num_plots): # Generate a sk based on the seed, plot size (k), and index sk: PrivateKey = PrivateKey.from_seed(sk_seed + args.size.to_bytes(1, "big") + i.to_bytes(4, "big")) # The plot seed is based on the pool and plot pks plot_seed: bytes32 = ProofOfSpace.calculate_plot_seed( pool_pk, sk.get_public_key()) filename: str = f"plot-{i}-{args.size}-{plot_seed}.dat" full_path: Path = args.final_dir / filename if not full_path.exists(): # Creates the plot. This will take a long time for larger plots. plotter: DiskPlotter = DiskPlotter() plotter.create_plot_disk( str(tmp_dir), str(args.final_dir), filename, args.size, bytes([]), plot_seed, ) else: print(f"Plot {filename} already exists") # Updates the config if necessary. plot_config = load_config(root_path, plot_config_filename) plot_config_plots_new = deepcopy(plot_config.get("plots", [])) relative_path = make_path_relative(full_path, root_path) if (relative_path not in plot_config_plots_new and full_path not in plot_config_plots_new): plot_config_plots_new[str(full_path)] = { "sk": bytes(sk).hex(), "pool_pk": bytes(pool_pk).hex(), } plot_config["plots"].update(plot_config_plots_new) # Dumps the new config to disk. save_config(root_path, plot_config_filename, plot_config) try: tmp_dir.rmdir() except Exception: print(f"warning: couldn't delete {tmp_dir}")
def main(): """ Script for creating plots and adding them to the plot config file. """ root_path = DEFAULT_ROOT_PATH plot_config_filename = config_path_for_filename(root_path, "plots.yaml") parser = argparse.ArgumentParser(description="Chia plotting script.") parser.add_argument("-k", "--size", help="Plot size", type=int, default=26) parser.add_argument( "-n", "--num_plots", help="Number of plots", type=int, default=1 ) parser.add_argument( "-i", "--index", help="First plot index", type=int, default=None ) parser.add_argument( "-p", "--pool_pub_key", help="Hex public key of pool", type=str, default="" ) parser.add_argument( "-s", "--sk_seed", help="Secret key seed in hex", type=str, default=None ) parser.add_argument( "-t", "--tmp_dir", help="Temporary directory for plotting files", type=Path, default=Path("."), ) parser.add_argument( "-2", "--tmp2_dir", help="Second temporary directory for plotting files", type=Path, default=Path("."), ) new_plots_root = path_from_root( root_path, load_config(root_path, "config.yaml") .get("harvester", {}) .get("new_plot_root", "plots"), ) parser.add_argument( "-d", "--final_dir", help="Final directory for plots (relative or absolute)", type=Path, default=new_plots_root, ) args = parser.parse_args() if args.sk_seed is None and args.index is not None: log( f"You have specified the -i (index) argument without the -s (sk_seed) argument." f" The program has changes, so that the sk_seed is now generated randomly, so -i is no longer necessary." f" Please run the program without -i." ) quit() if args.index is None: args.index = 0 # The seed is what will be used to generate a private key for each plot if args.sk_seed is not None: sk_seed: bytes = bytes.fromhex(args.sk_seed) log(f"Using the provided sk_seed {sk_seed.hex()}.") else: sk_seed = token_bytes(32) log( f"Using sk_seed {sk_seed.hex()}. Note that sk seed is now generated randomly, as opposed " f"to from keys.yaml. If you want to use a specific seed, use the -s argument." ) pool_pk: PublicKey if len(args.pool_pub_key) > 0: # Use the provided pool public key, useful for using an external pool pool_pk = PublicKey.from_bytes(bytes.fromhex(args.pool_pub_key)) else: # Use the pool public key from the config, useful for solo farming keychain = Keychain() all_public_keys = keychain.get_all_public_keys() if len(all_public_keys) == 0: raise RuntimeError( "There are no private keys in the keychain, so we cannot create a plot. " "Please generate keys using 'chia keys generate' or pass in a pool pk with -p" ) pool_pk = all_public_keys[0].get_public_key() log( f"Creating {args.num_plots} plots, from index {args.index} to " f"{args.index + args.num_plots - 1}, of size {args.size}, sk_seed {sk_seed.hex()} ppk {pool_pk}" ) mkdir(args.tmp_dir) mkdir(args.tmp2_dir) mkdir(args.final_dir) finished_filenames = [] for i in range(args.index, args.index + args.num_plots): # Generate a sk based on the seed, plot size (k), and index sk: PrivateKey = PrivateKey.from_seed( sk_seed + args.size.to_bytes(1, "big") + i.to_bytes(4, "big") ) # The plot seed is based on the pool and plot pks plot_seed: bytes32 = ProofOfSpace.calculate_plot_seed( pool_pk, sk.get_public_key() ) dt_string = datetime.now().strftime("%Y-%m-%d-%H-%M") filename: str = f"plot-k{args.size}-{dt_string}-{plot_seed}.dat" full_path: Path = args.final_dir / filename plot_config = load_config(root_path, plot_config_filename) plot_config_plots_new = deepcopy(plot_config.get("plots", [])) filenames = [Path(k).name for k in plot_config_plots_new.keys()] already_in_config = any(plot_seed.hex() in fname for fname in filenames) if already_in_config: log(f"Plot {filename} already exists (in config)") continue if not full_path.exists(): # Creates the plot. This will take a long time for larger plots. plotter: DiskPlotter = DiskPlotter() plotter.create_plot_disk( str(args.tmp_dir), str(args.tmp2_dir), str(args.final_dir), filename, args.size, bytes([]), plot_seed, ) finished_filenames.append(filename) else: log(f"Plot {filename} already exists") # Updates the config if necessary. plot_config = load_config(root_path, plot_config_filename) plot_config_plots_new = deepcopy(plot_config.get("plots", [])) plot_config_plots_new[str(full_path)] = { "sk": bytes(sk).hex(), "pool_pk": bytes(pool_pk).hex(), } plot_config["plots"].update(plot_config_plots_new) # Dumps the new config to disk. save_config(root_path, plot_config_filename, plot_config) log("") log("Summary:") try: args.tmp_dir.rmdir() except Exception: log( f"warning: did not remove primary temporary folder {args.tmp_dir}, it may not be empty." ) try: args.tmp2_dir.rmdir() except Exception: log( f"warning: did not remove secondary temporary folder {args.tmp2_dir}, it may not be empty." ) log(f"Created a total of {len(finished_filenames)} new plots") for filename in finished_filenames: log(filename)
def main(): """ Allows replacing keys of farmer, harvester, and pool, all default to True. """ root_path = DEFAULT_ROOT_PATH keys_yaml = "keys.yaml" parser = argparse.ArgumentParser(description="Chia key generator script.") parser.add_argument( "-a", "--harvester", type=str2bool, nargs="?", const=True, default=True, help="Regenerate plot key seed", ) parser.add_argument( "-p", "--pool", type=str2bool, nargs="?", const=True, default=True, help="Regenerate pool keys", ) parser.add_argument( "-w", "--wallet", type=str2bool, nargs="?", const=True, default=True, help="Regenerate wallet keys", ) args = parser.parse_args() key_config_filename = config_path_for_filename(root_path, keys_yaml) if key_config_filename.exists(): # If the file exists, warn the user yn = input( f"The keys file {key_config_filename} already exists. Are you sure" f" you want to override the keys? Plots might become invalid. (y/n): " ) if not (yn.lower() == "y" or yn.lower() == "yes"): quit() else: # Create the file if if doesn't exist mkdir(key_config_filename.parent) open(key_config_filename, "a").close() key_config = load_config(root_path, keys_yaml) if key_config is None: key_config = {} wallet_target = None if args.wallet: wallet_sk = ExtendedPrivateKey.from_seed(token_bytes(32)) wallet_target = create_puzzlehash_for_pk( BLSPublicKey(bytes(wallet_sk.public_child(0).get_public_key()))) key_config["wallet_sk"] = bytes(wallet_sk).hex() key_config["wallet_target"] = wallet_target.hex() save_config(root_path, keys_yaml, key_config) if args.harvester: # Replaces the harvester's sk seed. Used to generate plot private keys, which are # used to sign farmed blocks. key_config["sk_seed"] = token_bytes(32).hex() save_config(root_path, keys_yaml, key_config) if args.pool: # Replaces the pools keys and targes. Only useful if running a pool, or doing # solo farming. The pool target allows spending of the coinbase. pool_sks = [PrivateKey.from_seed(token_bytes(32)) for _ in range(2)] if wallet_target is None: pool_target = create_puzzlehash_for_pk( BLSPublicKey(bytes(pool_sks[0].get_public_key()))) else: pool_target = wallet_target key_config["pool_sks"] = [bytes(pool_sk).hex() for pool_sk in pool_sks] key_config["pool_target"] = pool_target.hex() save_config(root_path, keys_yaml, key_config)
def __init__( self, root_path: Path = TEST_ROOT_PATH, real_plots: bool = False, ): create_default_chia_config(root_path) initialize_ssl(root_path) self.root_path = root_path self.n_wesolowski = uint8(0) self.real_plots = real_plots if not real_plots: # No real plots supplied, so we will use the small test plots self.use_any_pos = True self.plot_config: Dict = {"plots": {}} # Can't go much lower than 19, since plots start having no solutions k: uint8 = uint8(19) # Uses many plots for testing, in order to guarantee proofs of space at every height num_plots = 40 # Use the empty string as the seed for the private key self.keychain = Keychain("testing", True) self.keychain.delete_all_keys() self.keychain.add_private_key_seed(b"block_tools") pool_sk: PrivateKey = self.keychain.get_all_private_keys( )[0][0].get_private_key() pool_pk: PublicKey = pool_sk.get_public_key() plot_sks: List[PrivateKey] = [ PrivateKey.from_seed(pn.to_bytes(4, "big")) for pn in range(num_plots) ] plot_pks: List[PublicKey] = [ sk.get_public_key() for sk in plot_sks ] plot_seeds: List[bytes32] = [ ProofOfSpace.calculate_plot_seed(pool_pk, plot_pk) for plot_pk in plot_pks ] plot_dir = get_plot_dir(root_path) mkdir(plot_dir) filenames: List[str] = [ f"genesis-plots-{k}{std_hash(int.to_bytes(i, 4, 'big')).hex()}.dat" for i in range(num_plots) ] done_filenames = set() temp_dir = plot_dir / "plot.tmp" mkdir(temp_dir) try: for pn, filename in enumerate(filenames): if not (plot_dir / filename).exists(): plotter = DiskPlotter() plotter.create_plot_disk( str(plot_dir), str(plot_dir), str(plot_dir), filename, k, b"genesis", plot_seeds[pn], ) done_filenames.add(filename) self.plot_config["plots"][str(plot_dir / filename)] = { "pool_pk": bytes(pool_pk).hex(), "sk": bytes(plot_sks[pn]).hex(), "pool_sk": bytes(pool_sk).hex(), } save_config(self.root_path, "plots.yaml", self.plot_config) except KeyboardInterrupt: for filename in filenames: if (filename not in done_filenames and (plot_dir / filename).exists()): (plot_dir / filename).unlink() sys.exit(1) else: try: plot_config = load_config(DEFAULT_ROOT_PATH, "plots.yaml") normal_config = load_config(DEFAULT_ROOT_PATH, "config.yaml") except FileNotFoundError: raise RuntimeError( "Plots not generated. Run chia-create-plots") self.keychain = Keychain(testing=False) private_keys: List[PrivateKey] = [ k.get_private_key() for (k, _) in self.keychain.get_all_private_keys() ] pool_pubkeys: List[PublicKey] = [ sk.get_public_key() for sk in private_keys ] if len(private_keys) == 0: raise RuntimeError( "Keys not generated. Run `chia generate keys`") self.prover_dict, _, _ = load_plots(normal_config["harvester"], plot_config, pool_pubkeys, DEFAULT_ROOT_PATH) new_plot_config: Dict = {"plots": {}} for key, value in plot_config["plots"].items(): for sk in private_keys: if (bytes(sk.get_public_key()).hex() == value["pool_pk"] and key in self.prover_dict): new_plot_config["plots"][key] = value new_plot_config["plots"][key]["pool_sk"] = bytes( sk).hex() self.plot_config = new_plot_config self.use_any_pos = False a = self.plot_config["plots"] print(f"Using {len(a)} reals plots to initialize block_tools") private_key = self.keychain.get_all_private_keys()[0][0] self.fee_target = create_puzzlehash_for_pk( BLSPublicKey(bytes(private_key.public_child(1).get_public_key())))
def migrate_from( old_root: Path, new_root: Path, manifest: List[str], do_not_migrate_settings: List[str], ): """ Copy all the files in "manifest" to the new config directory. """ if old_root == new_root: print("same as new path, exiting") return 1 if not old_root.is_dir(): print( f"{old_root} not found - this is ok if you did not install this version." ) return 0 print(f"\n{old_root} found") print(f"Copying files from {old_root} to {new_root}\n") not_found = [] for f in manifest: old_path = old_root / f new_path = new_root / f if old_path.is_file(): print(f"{new_path}") mkdir(new_path.parent) shutil.copy(old_path, new_path) else: not_found.append(f) print(f"{old_path} not found, skipping") # update config yaml with new keys config: Dict = load_config(new_root, "config.yaml") config_str: str = initial_config_file("config.yaml") default_config: Dict = yaml.safe_load(config_str) flattened_keys = unflatten_properties( {k: "" for k in do_not_migrate_settings}) dict_add_new_default(config, default_config, flattened_keys) save_config(new_root, "config.yaml", config) # migrate plots # for now, we simply leave them where they are # and make what may have been relative paths absolute if "config/trusted.key" in not_found or "config/trusted.key" in not_found: initialize_ssl(new_root) plots_config: Dict = load_config(new_root, "plots.yaml") plot_root = (load_config(new_root, "config.yaml").get("harvester", {}).get("plot_root", ".")) old_plots_root: Path = path_from_root(old_root, plot_root) new_plots_root: Path = path_from_root(new_root, plot_root) old_plot_paths = plots_config.get("plots", {}) if len(old_plot_paths) == 0: print("no plots found, no plots migrated") return 1 print("\nmigrating plots.yaml") new_plot_paths: Dict = {} for path, values in old_plot_paths.items(): old_path_full = path_from_root(old_plots_root, path) new_path_relative = make_path_relative(old_path_full, new_plots_root) print(f"rewriting {path}\n as {new_path_relative}") new_plot_paths[str(new_path_relative)] = values plots_config_new: Dict = {"plots": new_plot_paths} save_config(new_root, "plots.yaml", plots_config_new) print("\nUpdated plots.yaml to point to where your existing plots are.") print( "\nYour plots have not been moved so be careful deleting old preferences folders." ) print("\nIf you want to move your plot files, you should also modify") print(f"{config_path_for_filename(new_root, 'plots.yaml')}") return 1