From f548a71f76b71dfb4cf2185008745615c2466f20 Mon Sep 17 00:00:00 2001 From: Roland Sherwin Date: Sat, 7 Dec 2024 15:48:31 +0530 Subject: [PATCH] feat(bootstrap): allow writing or reading from custom bootstrap cache dir --- ant-bootstrap/src/cache_store.rs | 10 +- ant-bootstrap/src/config.rs | 9 +- ant-bootstrap/src/error.rs | 2 + ant-bootstrap/src/initial_peers.rs | 41 +++- ant-bootstrap/tests/address_format_tests.rs | 2 + ant-bootstrap/tests/cli_integration_tests.rs | 5 + ant-node-manager/src/add_services/tests.rs | 173 +++++++++++++++++ ant-node-manager/src/lib.rs | 188 ++++++++++++++++++- ant-node-manager/src/local.rs | 1 + ant-service-management/src/node.rs | 4 + 10 files changed, 426 insertions(+), 9 deletions(-) diff --git a/ant-bootstrap/src/cache_store.rs b/ant-bootstrap/src/cache_store.rs index c435fbec23..eabffd6164 100644 --- a/ant-bootstrap/src/cache_store.rs +++ b/ant-bootstrap/src/cache_store.rs @@ -181,15 +181,21 @@ impl BootstrapCacheStore { /// Create a empty CacheStore from the given peers argument. /// This also modifies the cfg if provided based on the PeersArgs. /// And also performs some actions based on the PeersArgs. + /// + /// `PeersArgs::bootstrap_cache_dir` will take precedence over the path provided inside `config`. pub fn new_from_peers_args( peers_arg: &PeersArgs, - cfg: Option, + config: Option, ) -> Result { - let config = if let Some(cfg) = cfg { + let mut config = if let Some(cfg) = config { cfg } else { BootstrapCacheConfig::default_config()? }; + if let Some(bootstrap_cache_path) = peers_arg.get_bootstrap_cache_path()? { + config.cache_file_path = bootstrap_cache_path; + } + let mut store = Self::new(config)?; // If it is the first node, clear the cache. diff --git a/ant-bootstrap/src/config.rs b/ant-bootstrap/src/config.rs index 52d85b7dee..131d857694 100644 --- a/ant-bootstrap/src/config.rs +++ b/ant-bootstrap/src/config.rs @@ -118,8 +118,13 @@ fn default_cache_path() -> Result { std::fs::create_dir_all(&dir)?; - let network_id = format!("{}_{}", get_key_version_str(), get_truncate_version_str()); - let path = dir.join(format!("bootstrap_cache_{}.json", network_id)); + let path = dir.join(cache_file_name()); Ok(path) } + +/// Returns the name of the cache file +pub fn cache_file_name() -> String { + let network_id = format!("{}_{}", get_key_version_str(), get_truncate_version_str()); + format!("bootstrap_cache_{network_id}.json") +} diff --git a/ant-bootstrap/src/error.rs b/ant-bootstrap/src/error.rs index 70da2ca80a..bc735b753a 100644 --- a/ant-bootstrap/src/error.rs +++ b/ant-bootstrap/src/error.rs @@ -16,6 +16,8 @@ pub enum Error { FailedToParseCacheData, #[error("Could not obtain data directory")] CouldNotObtainDataDir, + #[error("Invalid bootstrap cache directory")] + InvalidBootstrapCacheDir, #[error("Could not obtain bootstrap addresses from {0} after {1} retries")] FailedToObtainAddrsFromUrl(String, usize), #[error("No Bootstrap Addresses found: {0}")] diff --git a/ant-bootstrap/src/initial_peers.rs b/ant-bootstrap/src/initial_peers.rs index daf20d1480..6c0d5538f0 100644 --- a/ant-bootstrap/src/initial_peers.rs +++ b/ant-bootstrap/src/initial_peers.rs @@ -7,6 +7,7 @@ // permissions and limitations relating to use of the SAFE Network Software. use crate::{ + config::cache_file_name, craft_valid_multiaddr, craft_valid_multiaddr_from_str, error::{Error, Result}, BootstrapAddr, BootstrapCacheConfig, BootstrapCacheStore, ContactsFetcher, @@ -14,6 +15,7 @@ use crate::{ use clap::Args; use libp2p::Multiaddr; use serde::{Deserialize, Serialize}; +use std::path::PathBuf; use url::Url; /// The name of the environment variable that can be used to pass peers to the node. @@ -61,17 +63,27 @@ pub struct PeersArgs { /// This disables fetching peers from the mainnet network contacts. #[clap(name = "testnet", long)] pub disable_mainnet_contacts: bool, - /// Set to not load the bootstrap addresses from the local cache. #[clap(long, default_value = "false")] pub ignore_cache: bool, + /// The directory to load and store the bootstrap cache. If not provided, the default path will be used. + /// + /// The JSON filename will be derived automatically from the network ID + /// + /// The default location is platform specific: + /// - Linux: $HOME/.local/share/autonomi/bootstrap_cache/bootstrap_cache_.json + /// - macOS: $HOME/Library/Application Support/autonomi/bootstrap_cache/bootstrap_cache_.json + /// - Windows: C:\Users\\AppData\Roaming\autonomi\bootstrap_cache\bootstrap_cache_.json + #[clap(long)] + pub bootstrap_cache_dir: Option, } + impl PeersArgs { /// Get bootstrap peers /// Order of precedence: /// 1. Addresses from arguments /// 2. Addresses from environment variable SAFE_PEERS - /// 3. Addresses from cache + /// 3. Addresses from cache. `Self::bootstrap_cache_dir` will take precedence over the path provided inside `config` /// 4. Addresses from network contacts URL pub async fn get_addrs(&self, config: Option) -> Result> { Ok(self @@ -86,7 +98,7 @@ impl PeersArgs { /// Order of precedence: /// 1. Addresses from arguments /// 2. Addresses from environment variable SAFE_PEERS - /// 3. Addresses from cache + /// 3. Addresses from cache. `Self::bootstrap_cache_dir` will take precedence over the path provided inside `config` /// 4. Addresses from network contacts URL pub async fn get_bootstrap_addr( &self, @@ -147,7 +159,10 @@ impl PeersArgs { } else { BootstrapCacheConfig::default_config().ok() }; - if let Some(cfg) = cfg { + if let Some(mut cfg) = cfg { + if let Some(file_path) = self.get_bootstrap_cache_path()? { + cfg.cache_file_path = file_path; + } info!("Loading bootstrap addresses from cache"); if let Ok(data) = BootstrapCacheStore::load_cache_data(&cfg) { bootstrap_addresses = data @@ -206,4 +221,22 @@ impl PeersArgs { } bootstrap_addresses } + + /// Get the path to the bootstrap cache JSON file if `Self::bootstrap_cache_dir` is set + pub fn get_bootstrap_cache_path(&self) -> Result> { + if let Some(dir) = &self.bootstrap_cache_dir { + if dir.is_file() { + return Err(Error::InvalidBootstrapCacheDir); + } + + if !dir.exists() { + std::fs::create_dir_all(dir)?; + } + + let path = dir.join(cache_file_name()); + Ok(Some(path)) + } else { + Ok(None) + } + } } diff --git a/ant-bootstrap/tests/address_format_tests.rs b/ant-bootstrap/tests/address_format_tests.rs index 09d73e22b2..a953608039 100644 --- a/ant-bootstrap/tests/address_format_tests.rs +++ b/ant-bootstrap/tests/address_format_tests.rs @@ -49,6 +49,7 @@ async fn test_multiaddr_format_parsing() -> Result<(), Box Result<(), Box local: false, disable_mainnet_contacts: false, ignore_cache: false, + bootstrap_cache_dir: None, }; let addrs = args.get_bootstrap_addr(None).await?; diff --git a/ant-bootstrap/tests/cli_integration_tests.rs b/ant-bootstrap/tests/cli_integration_tests.rs index 4f70c23228..8ac0ab571b 100644 --- a/ant-bootstrap/tests/cli_integration_tests.rs +++ b/ant-bootstrap/tests/cli_integration_tests.rs @@ -35,6 +35,7 @@ async fn test_first_flag() -> Result<(), Box> { local: false, disable_mainnet_contacts: false, ignore_cache: false, + bootstrap_cache_dir: None, }; let addrs = args.get_addrs(Some(config)).await?; @@ -60,6 +61,7 @@ async fn test_peer_argument() -> Result<(), Box> { local: false, disable_mainnet_contacts: true, ignore_cache: false, + bootstrap_cache_dir: None, }; let addrs = args.get_addrs(None).await?; @@ -94,6 +96,7 @@ async fn test_network_contacts_fallback() -> Result<(), Box Result<(), Box> { local: true, disable_mainnet_contacts: false, ignore_cache: false, + bootstrap_cache_dir: None, }; let addrs = args.get_addrs(Some(config)).await?; @@ -159,6 +163,7 @@ async fn test_test_network_peers() -> Result<(), Box> { local: false, disable_mainnet_contacts: true, ignore_cache: false, + bootstrap_cache_dir: None, }; let addrs = args.get_addrs(Some(config)).await?; diff --git a/ant-node-manager/src/add_services/tests.rs b/ant-node-manager/src/add_services/tests.rs index e2eb37aca5..ee19f167b0 100644 --- a/ant-node-manager/src/add_services/tests.rs +++ b/ant-node-manager/src/add_services/tests.rs @@ -116,6 +116,7 @@ async fn add_genesis_node_should_use_latest_version_and_add_one_service() -> Res local: false, disable_mainnet_contacts: false, ignore_cache: false, + bootstrap_cache_dir: None, }; let install_ctx = InstallNodeServiceCtxBuilder { @@ -266,6 +267,7 @@ async fn add_genesis_node_should_return_an_error_if_there_is_already_a_genesis_n local: false, disable_mainnet_contacts: false, ignore_cache: false, + bootstrap_cache_dir: None, }; let mut node_registry = NodeRegistry { auditor: None, @@ -403,6 +405,7 @@ async fn add_genesis_node_should_return_an_error_if_count_is_greater_than_1() -> local: false, disable_mainnet_contacts: false, ignore_cache: false, + bootstrap_cache_dir: None, }; let latest_version = "0.96.4"; @@ -1108,6 +1111,7 @@ async fn add_node_should_create_service_file_with_first_arg() -> Result<()> { local: false, disable_mainnet_contacts: false, ignore_cache: false, + bootstrap_cache_dir: None, }; let mut seq = Sequence::new(); @@ -1221,6 +1225,7 @@ async fn add_node_should_create_service_file_with_first_arg() -> Result<()> { assert_eq!(node_registry.nodes.len(), 1); assert_eq!(node_registry.nodes[0].version, latest_version); assert_eq!(node_registry.nodes[0].peers_args, peers_args); + assert!(node_registry.nodes[0].peers_args.first); Ok(()) } @@ -1260,6 +1265,7 @@ async fn add_node_should_create_service_file_with_peers_args() -> Result<()> { local: false, disable_mainnet_contacts: false, ignore_cache: false, + bootstrap_cache_dir: None, }; let mut seq = Sequence::new(); @@ -1375,6 +1381,7 @@ async fn add_node_should_create_service_file_with_peers_args() -> Result<()> { assert_eq!(node_registry.nodes.len(), 1); assert_eq!(node_registry.nodes[0].version, latest_version); assert_eq!(node_registry.nodes[0].peers_args, peers_args); + assert_eq!(node_registry.nodes[0].peers_args.addrs.len(), 1); Ok(()) } @@ -1411,6 +1418,7 @@ async fn add_node_should_create_service_file_with_local_arg() -> Result<()> { local: true, disable_mainnet_contacts: false, ignore_cache: false, + bootstrap_cache_dir: None, }; let mut seq = Sequence::new(); @@ -1524,6 +1532,7 @@ async fn add_node_should_create_service_file_with_local_arg() -> Result<()> { assert_eq!(node_registry.nodes.len(), 1); assert_eq!(node_registry.nodes[0].version, latest_version); assert_eq!(node_registry.nodes[0].peers_args, peers_args); + assert!(node_registry.nodes[0].peers_args.local); Ok(()) } @@ -1563,6 +1572,7 @@ async fn add_node_should_create_service_file_with_network_contacts_url_arg() -> local: false, disable_mainnet_contacts: false, ignore_cache: false, + bootstrap_cache_dir: None, }; let mut seq = Sequence::new(); @@ -1677,6 +1687,10 @@ async fn add_node_should_create_service_file_with_network_contacts_url_arg() -> assert_eq!(node_registry.nodes.len(), 1); assert_eq!(node_registry.nodes[0].version, latest_version); assert_eq!(node_registry.nodes[0].peers_args, peers_args); + assert_eq!( + node_registry.nodes[0].peers_args.network_contacts_url.len(), + 2 + ); Ok(()) } @@ -1713,6 +1727,7 @@ async fn add_node_should_create_service_file_with_testnet_arg() -> Result<()> { local: false, disable_mainnet_contacts: true, ignore_cache: false, + bootstrap_cache_dir: None, }; let mut seq = Sequence::new(); @@ -1826,6 +1841,7 @@ async fn add_node_should_create_service_file_with_testnet_arg() -> Result<()> { assert_eq!(node_registry.nodes.len(), 1); assert_eq!(node_registry.nodes[0].version, latest_version); assert_eq!(node_registry.nodes[0].peers_args, peers_args); + assert!(node_registry.nodes[0].peers_args.disable_mainnet_contacts); Ok(()) } @@ -1862,6 +1878,7 @@ async fn add_node_should_create_service_file_with_ignore_cache_arg() -> Result<( local: false, disable_mainnet_contacts: false, ignore_cache: true, + bootstrap_cache_dir: None, }; let mut seq = Sequence::new(); @@ -1975,6 +1992,162 @@ async fn add_node_should_create_service_file_with_ignore_cache_arg() -> Result<( assert_eq!(node_registry.nodes.len(), 1); assert_eq!(node_registry.nodes[0].version, latest_version); assert_eq!(node_registry.nodes[0].peers_args, peers_args); + assert!(node_registry.nodes[0].peers_args.ignore_cache); + + Ok(()) +} + +#[tokio::test] +async fn add_node_should_create_service_file_with_custom_bootstrap_cache_path() -> Result<()> { + let tmp_data_dir = assert_fs::TempDir::new()?; + let node_reg_path = tmp_data_dir.child("node_reg.json"); + + let mut mock_service_control = MockServiceControl::new(); + + let mut node_registry = NodeRegistry { + auditor: None, + faucet: None, + save_path: node_reg_path.to_path_buf(), + nat_status: None, + nodes: vec![], + environment_variables: None, + daemon: None, + }; + let latest_version = "0.96.4"; + let temp_dir = assert_fs::TempDir::new()?; + let node_data_dir = temp_dir.child("data"); + node_data_dir.create_dir_all()?; + let node_logs_dir = temp_dir.child("logs"); + node_logs_dir.create_dir_all()?; + let antnode_download_path = temp_dir.child(ANTNODE_FILE_NAME); + antnode_download_path.write_binary(b"fake antnode bin")?; + + let peers_args = PeersArgs { + first: false, + addrs: vec![], + network_contacts_url: vec![], + local: false, + disable_mainnet_contacts: false, + ignore_cache: false, + bootstrap_cache_dir: Some(PathBuf::from("/path/to/bootstrap/cache")), + }; + + let mut seq = Sequence::new(); + + mock_service_control + .expect_get_available_port() + .times(1) + .returning(|| Ok(12001)) + .in_sequence(&mut seq); + + mock_service_control + .expect_install() + .times(1) + .with( + eq(ServiceInstallCtx { + args: vec![ + OsString::from("--rpc"), + OsString::from("127.0.0.1:12001"), + OsString::from("--root-dir"), + OsString::from( + node_data_dir + .to_path_buf() + .join("antnode1") + .to_string_lossy() + .to_string(), + ), + OsString::from("--log-output-dest"), + OsString::from( + node_logs_dir + .to_path_buf() + .join("antnode1") + .to_string_lossy() + .to_string(), + ), + OsString::from("--bootstrap-cache-dir"), + OsString::from("/path/to/bootstrap/cache"), + OsString::from("--rewards-address"), + OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"), + OsString::from("evm-custom"), + OsString::from("--rpc-url"), + OsString::from("http://localhost:8545/"), + OsString::from("--payment-token-address"), + OsString::from("0x5FbDB2315678afecb367f032d93F642f64180aa3"), + OsString::from("--data-payments-address"), + OsString::from("0x8464135c8F25Da09e49BC8782676a84730C318bC"), + ], + autostart: false, + contents: None, + environment: None, + label: "antnode1".parse()?, + program: node_data_dir + .to_path_buf() + .join("antnode1") + .join(ANTNODE_FILE_NAME), + username: Some(get_username()), + working_directory: None, + }), + eq(false), + ) + .returning(|_, _| Ok(())) + .in_sequence(&mut seq); + + add_node( + AddNodeServiceOptions { + auto_restart: false, + auto_set_nat_flags: false, + count: None, + delete_antnode_src: true, + enable_metrics_server: false, + env_variables: None, + home_network: false, + log_format: None, + max_archived_log_files: None, + max_log_files: None, + metrics_port: None, + node_ip: None, + node_port: None, + owner: None, + peers_args: peers_args.clone(), + rpc_address: None, + rpc_port: None, + antnode_dir_path: temp_dir.to_path_buf(), + antnode_src_path: antnode_download_path.to_path_buf(), + service_data_dir_path: node_data_dir.to_path_buf(), + service_log_dir_path: node_logs_dir.to_path_buf(), + upnp: false, + user: Some(get_username()), + user_mode: false, + version: latest_version.to_string(), + evm_network: EvmNetwork::Custom(CustomNetwork { + rpc_url_http: "http://localhost:8545".parse()?, + payment_token_address: RewardsAddress::from_str( + "0x5FbDB2315678afecb367f032d93F642f64180aa3", + )?, + data_payments_address: RewardsAddress::from_str( + "0x8464135c8F25Da09e49BC8782676a84730C318bC", + )?, + }), + rewards_address: RewardsAddress::from_str( + "0x03B770D9cD32077cC0bF330c13C114a87643B124", + )?, + }, + &mut node_registry, + &mock_service_control, + VerbosityLevel::Normal, + ) + .await?; + + antnode_download_path.assert(predicate::path::missing()); + node_data_dir.assert(predicate::path::is_dir()); + node_logs_dir.assert(predicate::path::is_dir()); + assert_eq!(node_registry.nodes.len(), 1); + assert_eq!(node_registry.nodes[0].version, latest_version); + assert_eq!(node_registry.nodes[0].peers_args, peers_args); + assert_eq!( + node_registry.nodes[0].peers_args.bootstrap_cache_dir, + Some(PathBuf::from("/path/to/bootstrap/cache")) + ); Ok(()) } diff --git a/ant-node-manager/src/lib.rs b/ant-node-manager/src/lib.rs index 7987c55224..2b4c6a8921 100644 --- a/ant-node-manager/src/lib.rs +++ b/ant-node-manager/src/lib.rs @@ -2735,6 +2735,7 @@ mod tests { local: false, disable_mainnet_contacts: false, ignore_cache: false, + bootstrap_cache_dir: None, }, pid: Some(1000), rewards_address: RewardsAddress::from_str( @@ -2908,7 +2909,8 @@ mod tests { local: false, disable_mainnet_contacts: false, ignore_cache: false, - }, + bootstrap_cache_dir: None, + }, pid: Some(1000), rewards_address: RewardsAddress::from_str( "0x03B770D9cD32077cC0bF330c13C114a87643B124", @@ -3080,6 +3082,7 @@ mod tests { local: true, disable_mainnet_contacts: false, ignore_cache: false, + bootstrap_cache_dir: None, }, pid: Some(1000), rewards_address: RewardsAddress::from_str( @@ -3251,6 +3254,7 @@ mod tests { local: false, disable_mainnet_contacts: false, ignore_cache: false, + bootstrap_cache_dir: None, }, pid: Some(1000), rewards_address: RewardsAddress::from_str( @@ -3426,6 +3430,7 @@ mod tests { local: false, disable_mainnet_contacts: true, ignore_cache: false, + bootstrap_cache_dir: None, }, pid: Some(1000), rewards_address: RewardsAddress::from_str( @@ -3599,6 +3604,7 @@ mod tests { local: false, disable_mainnet_contacts: false, ignore_cache: true, + bootstrap_cache_dir: None, }, pid: Some(1000), rewards_address: RewardsAddress::from_str( @@ -3638,6 +3644,186 @@ mod tests { Ok(()) } + #[tokio::test] + async fn upgrade_should_retain_the_custom_bootstrap_cache_path() -> Result<()> { + let current_version = "0.1.0"; + let target_version = "0.2.0"; + + let tmp_data_dir = assert_fs::TempDir::new()?; + let current_install_dir = tmp_data_dir.child("antnode_install"); + current_install_dir.create_dir_all()?; + + let current_node_bin = current_install_dir.child("antnode"); + current_node_bin.write_binary(b"fake antnode binary")?; + let target_node_bin = tmp_data_dir.child("antnode"); + target_node_bin.write_binary(b"fake antnode binary")?; + + let mut mock_service_control = MockServiceControl::new(); + let mut mock_rpc_client = MockRpcClient::new(); + + // before binary upgrade + mock_service_control + .expect_get_process_pid() + .with(eq(current_node_bin.to_path_buf().clone())) + .times(1) + .returning(|_| Ok(1000)); + mock_service_control + .expect_stop() + .with(eq("antnode1"), eq(false)) + .times(1) + .returning(|_, _| Ok(())); + + // after binary upgrade + mock_service_control + .expect_uninstall() + .with(eq("antnode1"), eq(false)) + .times(1) + .returning(|_, _| Ok(())); + mock_service_control + .expect_install() + .with( + eq(ServiceInstallCtx { + args: vec![ + OsString::from("--rpc"), + OsString::from("127.0.0.1:8081"), + OsString::from("--root-dir"), + OsString::from("/var/antctl/services/antnode1"), + OsString::from("--log-output-dest"), + OsString::from("/var/log/antnode/antnode1"), + OsString::from("--bootstrap-cache-dir"), + OsString::from("/var/antctl/services/antnode1/bootstrap_cache"), + OsString::from("--rewards-address"), + OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"), + OsString::from("evm-arbitrum-one"), + ], + autostart: false, + contents: None, + environment: None, + label: "antnode1".parse()?, + program: current_node_bin.to_path_buf(), + username: Some("ant".to_string()), + working_directory: None, + }), + eq(false), + ) + .times(1) + .returning(|_, _| Ok(())); + + // after service restart + mock_service_control + .expect_start() + .with(eq("antnode1"), eq(false)) + .times(1) + .returning(|_, _| Ok(())); + mock_service_control + .expect_wait() + .with(eq(3000)) + .times(1) + .returning(|_| ()); + mock_service_control + .expect_get_process_pid() + .with(eq(current_node_bin.to_path_buf().clone())) + .times(1) + .returning(|_| Ok(100)); + + mock_rpc_client.expect_node_info().times(1).returning(|| { + Ok(NodeInfo { + pid: 2000, + peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?, + data_path: PathBuf::from("/var/antctl/services/antnode1"), + log_path: PathBuf::from("/var/log/antnode/antnode1"), + version: target_version.to_string(), + uptime: std::time::Duration::from_secs(1), // the service was just started + wallet_balance: 0, + }) + }); + mock_rpc_client + .expect_network_info() + .times(1) + .returning(|| { + Ok(NetworkInfo { + connected_peers: Vec::new(), + listeners: Vec::new(), + }) + }); + + let mut service_data = NodeServiceData { + auto_restart: false, + connected_peers: None, + data_dir_path: PathBuf::from("/var/antctl/services/antnode1"), + evm_network: EvmNetwork::ArbitrumOne, + home_network: false, + listen_addr: None, + log_dir_path: PathBuf::from("/var/log/antnode/antnode1"), + log_format: None, + max_archived_log_files: None, + max_log_files: None, + metrics_port: None, + node_ip: None, + node_port: None, + number: 1, + owner: None, + peer_id: Some(PeerId::from_str( + "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR", + )?), + peers_args: PeersArgs { + first: false, + addrs: vec![], + network_contacts_url: vec![], + local: false, + disable_mainnet_contacts: false, + ignore_cache: false, + bootstrap_cache_dir: Some(PathBuf::from( + "/var/antctl/services/antnode1/bootstrap_cache", + )), + }, + pid: Some(1000), + rewards_address: RewardsAddress::from_str( + "0x03B770D9cD32077cC0bF330c13C114a87643B124", + )?, + reward_balance: Some(AttoTokens::zero()), + rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081), + antnode_path: current_node_bin.to_path_buf(), + service_name: "antnode1".to_string(), + status: ServiceStatus::Running, + upnp: false, + user: Some("ant".to_string()), + user_mode: false, + version: current_version.to_string(), + }; + let service = NodeService::new(&mut service_data, Box::new(mock_rpc_client)); + + let mut service_manager = ServiceManager::new( + service, + Box::new(mock_service_control), + VerbosityLevel::Normal, + ); + + service_manager + .upgrade(UpgradeOptions { + auto_restart: false, + env_variables: None, + force: false, + start_service: true, + target_bin_path: target_node_bin.to_path_buf(), + target_version: Version::parse(target_version).unwrap(), + }) + .await?; + + assert_eq!( + service_manager + .service + .service_data + .peers_args + .bootstrap_cache_dir, + Some(PathBuf::from( + "/var/antctl/services/antnode1/bootstrap_cache" + )) + ); + + Ok(()) + } + #[tokio::test] async fn upgrade_should_retain_the_upnp_flag() -> Result<()> { let current_version = "0.1.0"; diff --git a/ant-node-manager/src/local.rs b/ant-node-manager/src/local.rs index 9b8b61e4e3..9bfc06eee9 100644 --- a/ant-node-manager/src/local.rs +++ b/ant-node-manager/src/local.rs @@ -447,6 +447,7 @@ pub async fn run_node( local: true, disable_mainnet_contacts: true, ignore_cache: true, + bootstrap_cache_dir: None, }, pid: Some(node_info.pid), rewards_address: run_options.rewards_address, diff --git a/ant-service-management/src/node.rs b/ant-service-management/src/node.rs index e1b5378bbc..d9a91eeb12 100644 --- a/ant-service-management/src/node.rs +++ b/ant-service-management/src/node.rs @@ -424,4 +424,8 @@ pub fn push_arguments_from_peers_args(peers_args: &PeersArgs, args: &mut Vec