amareleo_chain_cli/commands/
clean.rs

1// Copyright 2024 Aleo Network Foundation
2// This file is part of the snarkOS library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use amareleo_node::bft::helpers::{
17    DEFAULT_FILE_TAG,
18    amareleo_storage_mode,
19    custom_ledger_dir,
20    default_ledger_dir,
21    proposal_cache_path,
22};
23use snarkvm::console::network::{CanaryV0, MainnetV0, Network, TestnetV0};
24
25use anyhow::{Result, bail};
26use clap::Parser;
27use colored::Colorize;
28use std::path::PathBuf;
29
30/// Cleans the node storage.
31#[derive(Debug, Parser)]
32pub struct Clean {
33    /// Specify the network to remove from storage (0 = mainnet, 1 = testnet, 2 = canary)
34    #[clap(default_value_t=TestnetV0::ID, long = "network", value_parser = clap::value_parser!(u16).range((MainnetV0::ID as i64)..=(CanaryV0::ID as i64)))]
35    pub network: u16,
36    /// Specify the path to the ledger storage directory [default: current directory]
37    #[clap(long = "path")]
38    pub path: Option<PathBuf>,
39}
40
41impl Clean {
42    /// Cleans the node storage.
43    pub fn parse(&self) -> Result<String> {
44        self.remove_all(false)?;
45        self.remove_all(true)?;
46
47        Ok(String::from("✅ Clean Completed"))
48    }
49
50    fn get_file_list(pattern: &str) -> Vec<PathBuf> {
51        let mut paths: Vec<PathBuf> = Vec::new();
52
53        match glob::glob(pattern) {
54            Ok(entries) => {
55                for entry in entries {
56                    match entry {
57                        Ok(path) => paths.push(path),
58                        Err(e) => println!("⚠️  Glob entry error: {}", e),
59                    }
60                }
61            }
62            Err(e) => println!("⚠️  Glob pattern error: {}", e),
63        }
64        paths
65    }
66
67    pub fn remove_all(&self, keep_state: bool) -> Result<()> {
68        let file_tag = if keep_state { DEFAULT_FILE_TAG } else { "*" };
69
70        // Determine the ledger path
71        let pattern = match &self.path {
72            Some(path) => custom_ledger_dir(self.network, keep_state, file_tag, path.clone()),
73            None => default_ledger_dir(self.network, keep_state, file_tag),
74        };
75
76        if let Some(pattern_str) = pattern.to_str() {
77            let paths = Self::get_file_list(pattern_str);
78            for path in paths {
79                // Remove proposal cache file, and ledger
80                Self::remove_proposal_cache(path.clone())?;
81                let msg = Self::remove_ledger(path)?;
82                println!("{msg}");
83            }
84        } else {
85            bail!("Cannot read file pattern!");
86        }
87
88        Ok(())
89    }
90
91    /// Removes the specified ledger from storage.
92    pub(crate) fn remove_proposal_cache(path: PathBuf) -> Result<()> {
93        let storage_mode = amareleo_storage_mode(path);
94
95        // Remove the current proposal cache file, if it exists.
96        let cache_path = proposal_cache_path(&storage_mode)?;
97        if cache_path.exists() {
98            if let Err(err) = std::fs::remove_file(&cache_path) {
99                bail!("Failed to remove the current proposal cache file at {}: {err}", cache_path.display());
100            }
101        }
102
103        Ok(())
104    }
105
106    /// Removes the specified ledger from storage.
107    pub(crate) fn remove_ledger(path: PathBuf) -> Result<String> {
108        // Prepare the path string.
109        let path_string = format!("(in \"{}\")", path.display()).dimmed();
110
111        // Check if the path to the ledger exists in storage.
112        if path.exists() {
113            // Remove the ledger files from storage.
114            match std::fs::remove_dir_all(&path) {
115                Ok(_) => Ok(format!("✅ Cleaned the amareleo node storage {path_string}")),
116                Err(error) => {
117                    bail!("Failed to remove the amareleo node storage {path_string}\n{}", error.to_string().dimmed())
118                }
119            }
120        } else {
121            Ok(format!("✅ No amareleo node storage was found {path_string}"))
122        }
123    }
124}