diff --git a/.gitignore b/.gitignore index 38ce39afa..4cc388b00 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,9 @@ target/ /makefile-target /makefile-target-opt-level3 -# git shouldn't see the proof files. Bc big. +# git shouldn't see the proof files, or block files. Bc big. /test_data/*.proof +/test_data/blk*.dat # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html diff --git a/src/lib.rs b/src/lib.rs index b741f5b9c..f68c0b4f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,9 +44,7 @@ pub mod util_types; #[cfg_attr(coverage_nightly, coverage(off))] pub mod tests; -use std::collections::HashMap; use std::env; -use std::net::SocketAddr; use std::path::PathBuf; use anyhow::Context; @@ -62,8 +60,8 @@ use futures::StreamExt; use models::blockchain::block::Block; use models::blockchain::shared::Hash; use models::peer::handshake_data::HandshakeData; -use models::peer::peer_info::PeerInfo; use models::state::wallet::wallet_file::WalletFileContext; +use models::state::GlobalState; use prelude::tasm_lib; use prelude::triton_vm; use prelude::twenty_first; @@ -88,11 +86,6 @@ use crate::models::channel::MinerToMain; use crate::models::channel::PeerTaskToMain; use crate::models::channel::RPCServerToMain; use crate::models::state::archival_state::ArchivalState; -use crate::models::state::blockchain_state::BlockchainArchivalState; -use crate::models::state::blockchain_state::BlockchainState; -use crate::models::state::light_state::LightState; -use crate::models::state::mempool::Mempool; -use crate::models::state::networking_state::NetworkingState; use crate::models::state::wallet::wallet_state::WalletState; use crate::models::state::GlobalStateLock; use crate::rpc_server::RPC; @@ -125,54 +118,13 @@ pub async fn initialize(cli_args: cli_args::Args) -> Result { DataDirectory::create_dir_if_not_exists(&data_directory.root_dir_path()).await?; info!("Data directory is {}", data_directory); - // Get wallet object, create various wallet secret files - let wallet_dir = data_directory.wallet_directory_path(); - DataDirectory::create_dir_if_not_exists(&wallet_dir).await?; - let wallet_file_context = - WalletFileContext::read_from_file_or_create(&data_directory.wallet_directory_path())?; - info!("Now getting wallet state. This may take a while if the database needs pruning."); - let wallet_state = - WalletState::try_new_from_context(&data_directory, wallet_file_context, &cli_args).await?; - info!("Got wallet state."); - - // Connect to or create databases for block index, peers, mutator set, block sync - let block_index_db = ArchivalState::initialize_block_index_database(&data_directory).await?; - info!("Got block index database"); - - let peer_databases = NetworkingState::initialize_peer_databases(&data_directory).await?; - info!("Got peer database"); - - let archival_mutator_set = ArchivalState::initialize_mutator_set(&data_directory).await?; - info!("Got archival mutator set"); - - let archival_block_mmr = ArchivalState::initialize_archival_block_mmr(&data_directory).await?; - info!("Got archival block MMR"); - - let archival_state = ArchivalState::new( - data_directory.clone(), - block_index_db, - archival_mutator_set, - archival_block_mmr, - cli_args.network, - ) - .await; - - // Get latest block. Use hardcoded genesis block if nothing is in database. - let latest_block: Block = archival_state.get_tip().await; - - // Bind socket to port on this machine, to handle incoming connections from peers - let incoming_peer_listener = if let Some(incoming_peer_listener) = cli_args.own_listen_port() { - let ret = TcpListener::bind((cli_args.listen_addr, incoming_peer_listener)) - .await - .with_context(|| format!("Failed to bind to local TCP port {}:{}. Is an instance of this program already running?", cli_args.listen_addr, incoming_peer_listener))?; - info!("Now listening for incoming peer-connections"); - ret - } else { - info!("Not accepting incoming peer-connections"); - TcpListener::bind("127.0.0.1:0").await? - }; - - let peer_map: HashMap = HashMap::new(); + let (rpc_server_to_main_tx, rpc_server_to_main_rx) = + mpsc::channel::(RPC_CHANNEL_CAPACITY); + let genesis = Block::genesis(cli_args.network); + let global_state = + GlobalState::try_new(data_directory.clone(), genesis, cli_args.clone()).await?; + let mut global_state_lock = + GlobalStateLock::from_global_state(global_state, rpc_server_to_main_tx.clone()); // Construct the broadcast channel to communicate from the main task to peer tasks let (main_to_peer_broadcast_tx, _main_to_peer_broadcast_rx) = @@ -182,32 +134,6 @@ pub async fn initialize(cli_args: cli_args::Args) -> Result { let (peer_task_to_main_tx, peer_task_to_main_rx) = mpsc::channel::(PEER_CHANNEL_CAPACITY); - let networking_state = NetworkingState::new(peer_map, peer_databases); - - let light_state: LightState = LightState::from(latest_block); - let blockchain_archival_state = BlockchainArchivalState { - light_state, - archival_state, - }; - let blockchain_state = BlockchainState::Archival(Box::new(blockchain_archival_state)); - let mempool = Mempool::new( - cli_args.max_mempool_size, - cli_args.max_mempool_num_tx, - blockchain_state.light_state().hash(), - ); - - let (rpc_server_to_main_tx, rpc_server_to_main_rx) = - mpsc::channel::(RPC_CHANNEL_CAPACITY); - - let mut global_state_lock = GlobalStateLock::new( - wallet_state, - blockchain_state, - networking_state, - cli_args, - mempool, - rpc_server_to_main_tx.clone(), - ); - if let Some(bootstrap_directory) = global_state_lock.cli().bootstrap_from_directory.clone() { info!( "Bootstrapping from directory \"{}\"", @@ -232,6 +158,18 @@ pub async fn initialize(cli_args: cli_args::Args) -> Result { .await?; info!("UTXO restoration check complete"); + // Bind socket to port on this machine, to handle incoming connections from peers + let incoming_peer_listener = if let Some(incoming_peer_listener) = cli_args.own_listen_port() { + let ret = TcpListener::bind((cli_args.listen_addr, incoming_peer_listener)) + .await + .with_context(|| format!("Failed to bind to local TCP port {}:{}. Is an instance of this program already running?", cli_args.listen_addr, incoming_peer_listener))?; + info!("Now listening for incoming peer-connections"); + ret + } else { + info!("Not accepting incoming peer-connections"); + TcpListener::bind("127.0.0.1:0").await? + }; + // Connect to peers, and provide each peer task with a thread-safe copy of the state let own_handshake_data: HandshakeData = global_state_lock.lock_guard().await.get_own_handshakedata(); diff --git a/src/main_loop/proof_upgrader.rs b/src/main_loop/proof_upgrader.rs index 609d3c4c6..58f353a07 100644 --- a/src/main_loop/proof_upgrader.rs +++ b/src/main_loop/proof_upgrader.rs @@ -901,12 +901,11 @@ mod tests { // expiry of timelock). Rando is not premine recipient. let cli_args = cli_args::Args { min_gobbling_fee: NativeCurrencyAmount::from_nau(5), - network: Network::Main, + network, ..Default::default() }; let alice = - mock_genesis_global_state(network, 2, WalletEntropy::devnet_wallet(), cli_args.clone()) - .await; + mock_genesis_global_state(2, WalletEntropy::devnet_wallet(), cli_args.clone()).await; let pc_tx_low_fee = transaction_from_state( alice.clone(), 512777439428, @@ -916,13 +915,8 @@ mod tests { .await; for tx_origin in [TransactionOrigin::Own, TransactionOrigin::Foreign] { - let mut rando = mock_genesis_global_state( - network, - 2, - WalletEntropy::new_random(), - cli_args.clone(), - ) - .await; + let mut rando = + mock_genesis_global_state(2, WalletEntropy::new_random(), cli_args.clone()).await; let mut rando = rando.lock_guard_mut().await; rando .mempool_insert(pc_tx_low_fee.clone().into(), tx_origin) diff --git a/src/mine_loop.rs b/src/mine_loop.rs index a4d333f02..d0d466680 100644 --- a/src/mine_loop.rs +++ b/src/mine_loop.rs @@ -1156,10 +1156,9 @@ pub(crate) mod tests { let mut rng = rand::rng(); let network = Network::RegTest; let global_state_lock = mock_genesis_global_state( - network, 2, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; @@ -1224,11 +1223,12 @@ pub(crate) mod tests { let guesser_fee_fraction = 0.0; let cli_args = cli_args::Args { guesser_fraction: guesser_fee_fraction, + network, ..Default::default() }; let global_state_lock = - mock_genesis_global_state(network, 2, WalletEntropy::devnet_wallet(), cli_args).await; + mock_genesis_global_state(2, WalletEntropy::devnet_wallet(), cli_args).await; let tick = std::time::SystemTime::now(); let (transaction, _coinbase_utxo_info) = make_coinbase_transaction_from_state( &genesis_block, @@ -1259,10 +1259,9 @@ pub(crate) mod tests { // Verify that a block template made with transaction from the mempool is a valid block let network = Network::Main; let mut alice = mock_genesis_global_state( - network, 2, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let genesis_block = Block::genesis(network); @@ -1439,11 +1438,11 @@ pub(crate) mod tests { // force SingleProof capability. let cli = cli_args::Args { tx_proving_capability: Some(TxProvingCapability::SingleProof), + network, ..Default::default() }; - let mut alice = - mock_genesis_global_state(network, 2, WalletEntropy::devnet_wallet(), cli).await; + let mut alice = mock_genesis_global_state(2, WalletEntropy::devnet_wallet(), cli).await; let genesis_block = Block::genesis(network); let mocked_now = genesis_block.header().timestamp + Timestamp::months(7); @@ -1502,10 +1501,11 @@ pub(crate) mod tests { let network = Network::Main; let cli_args = cli_args::Args { guesser_fraction: 0.0, + network, ..Default::default() }; let global_state_lock = - mock_genesis_global_state(network, 2, WalletEntropy::devnet_wallet(), cli_args).await; + mock_genesis_global_state(2, WalletEntropy::devnet_wallet(), cli_args).await; let tip_block_orig = Block::genesis(network); let launch_date = tip_block_orig.header().timestamp; let (worker_task_tx, worker_task_rx) = oneshot::channel::(); @@ -1574,10 +1574,11 @@ pub(crate) mod tests { let network = Network::Main; let cli_args = cli_args::Args { guesser_fraction: 0.0, + network, ..Default::default() }; let global_state_lock = - mock_genesis_global_state(network, 2, WalletEntropy::devnet_wallet(), cli_args).await; + mock_genesis_global_state(2, WalletEntropy::devnet_wallet(), cli_args).await; let (worker_task_tx, worker_task_rx) = oneshot::channel::(); let tip_block_orig = global_state_lock @@ -1682,10 +1683,9 @@ pub(crate) mod tests { ) -> Result<()> { let network = Network::RegTest; let global_state_lock = mock_genesis_global_state( - network, 2, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; @@ -1905,11 +1905,11 @@ pub(crate) mod tests { let cli_args = cli_args::Args { guesser_fraction: 0.0, fee_notification: notification_policy, + network, ..Default::default() }; let global_state_lock = - mock_genesis_global_state(network, 2, WalletEntropy::devnet_wallet(), cli_args) - .await; + mock_genesis_global_state(2, WalletEntropy::devnet_wallet(), cli_args).await; let genesis_block = Block::genesis(network); let launch_date = genesis_block.header().timestamp; @@ -2035,12 +2035,13 @@ pub(crate) mod tests { let cli_args = cli_args::Args { guesser_fraction, fee_notification: notification_policy, + network, ..Default::default() }; let global_state_lock = - mock_genesis_global_state(network, 2, WalletEntropy::devnet_wallet(), cli_args) + mock_genesis_global_state(2, WalletEntropy::devnet_wallet(), cli_args.clone()) .await; - let genesis_block = Block::genesis(network); + let genesis_block = Block::genesis(cli_args.network); let launch_date = genesis_block.header().timestamp; let (transaction, expected_utxos) = make_coinbase_transaction_from_state( @@ -2150,11 +2151,11 @@ pub(crate) mod tests { let network = Network::Main; let cli_args = cli_args::Args { compose: true, + network, ..Default::default() }; let global_state_lock = - mock_genesis_global_state(network, 2, WalletEntropy::devnet_wallet(), cli_args.clone()) - .await; + mock_genesis_global_state(2, WalletEntropy::devnet_wallet(), cli_args.clone()).await; let (cancel_job_tx, cancel_job_rx) = tokio::sync::watch::channel(()); @@ -2221,10 +2222,11 @@ pub(crate) mod tests { let network = Network::Main; let cli_args = cli_args::Args { compose: true, + network, ..Default::default() }; let global_state_lock = - mock_genesis_global_state(network, 2, WalletEntropy::devnet_wallet(), cli_args).await; + mock_genesis_global_state(2, WalletEntropy::devnet_wallet(), cli_args).await; let (miner_to_main_tx, _miner_to_main_rx) = mpsc::channel::(MINER_CHANNEL_CAPACITY); @@ -2345,10 +2347,9 @@ pub(crate) mod tests { // obtain global state let global_state_lock = mock_genesis_global_state( - network, 2, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; diff --git a/src/models/blockchain/block/mod.rs b/src/models/blockchain/block/mod.rs index c3ab8d837..e02f0c426 100644 --- a/src/models/blockchain/block/mod.rs +++ b/src/models/blockchain/block/mod.rs @@ -1156,7 +1156,7 @@ pub(crate) mod tests { #[cfg(test)] impl Block { - fn with_difficulty(mut self, difficulty: Difficulty) -> Self { + pub(crate) fn with_difficulty(mut self, difficulty: Difficulty) -> Self { self.kernel.header.difficulty = difficulty; self.unset_digest(); self @@ -1495,11 +1495,11 @@ pub(crate) mod tests { let alice_wallet = WalletEntropy::devnet_wallet(); let mut alice = mock_genesis_global_state( - network, 3, alice_wallet.clone(), cli_args::Args { guesser_fraction: 0.5, + network, ..Default::default() }, ) @@ -1531,10 +1531,9 @@ pub(crate) mod tests { for i in 0..10 { println!("i: {i}"); alice = mock_genesis_global_state( - network, 3, alice_wallet.clone(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; alice.set_new_tip(block1.clone()).await.unwrap(); @@ -1862,9 +1861,12 @@ pub(crate) mod tests { let alice_wallet = WalletEntropy::devnet_wallet(); let alice_key = alice_wallet.nth_generation_spending_key(0); let alice_address = alice_key.to_address(); - let mut alice = - mock_genesis_global_state(network, 0, alice_wallet, cli_args::Args::default()) - .await; + let mut alice = mock_genesis_global_state( + 0, + alice_wallet, + cli_args::Args::default_with_network(network), + ) + .await; let output = TxOutput::offchain_native_currency( NativeCurrencyAmount::coins(4), @@ -1952,8 +1954,12 @@ pub(crate) mod tests { let mut rng = StdRng::seed_from_u64(893423984854); let network = Network::Main; let devnet_wallet = WalletEntropy::devnet_wallet(); - let mut alice = - mock_genesis_global_state(network, 0, devnet_wallet, cli_args::Args::default()).await; + let mut alice = mock_genesis_global_state( + 0, + devnet_wallet, + cli_args::Args::default_with_network(network), + ) + .await; let job_queue = TritonVmJobQueue::get_instance(); diff --git a/src/models/blockchain/block/validity/block_program.rs b/src/models/blockchain/block/validity/block_program.rs index 998dab215..3ff97643c 100644 --- a/src/models/blockchain/block/validity/block_program.rs +++ b/src/models/blockchain/block/validity/block_program.rs @@ -496,10 +496,9 @@ pub(crate) mod tests { let mut rng: StdRng = SeedableRng::seed_from_u64(2225550001); let alice_wallet = WalletEntropy::devnet_wallet(); let alice = mock_genesis_global_state( - network, 3, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; diff --git a/src/models/proof_abstractions/tasm/program.rs b/src/models/proof_abstractions/tasm/program.rs index 891d4a862..28101ce5d 100644 --- a/src/models/proof_abstractions/tasm/program.rs +++ b/src/models/proof_abstractions/tasm/program.rs @@ -176,32 +176,28 @@ pub mod tests { use std::fs::create_dir_all; use std::fs::File; use std::io::stdout; - use std::io::Read; use std::io::Write; use std::panic::catch_unwind; use std::path::Path; use std::path::PathBuf; - use std::time::Duration; use std::time::SystemTime; use itertools::Itertools; use macro_rules_attr::apply; - use rand::seq::SliceRandom; use tasm_lib::triton_vm; use tracing::debug; - use tracing::Span; use super::*; use crate::models::blockchain::shared::Hash; use crate::models::blockchain::transaction::transaction_proof::TransactionProofType; use crate::models::proof_abstractions::tasm::environment; use crate::models::state::tx_proving_capability::TxProvingCapability; + use crate::tests::shared::test_helper_data_dir; + use crate::tests::shared::try_fetch_file_from_server; + use crate::tests::shared::try_load_file_from_disk; use crate::tests::shared_tokio_runtime; use crate::triton_vm::stark::Stark; - const TEST_DATA_DIR: &str = "test_data"; - const TEST_NAME_HTTP_HEADER_KEY: &str = "Test-Name"; - impl From for TritonVmProofJobOptions { fn from(job_priority: TritonVmJobPriority) -> Self { let job_settings = ProverJobSettings { @@ -349,13 +345,31 @@ pub mod tests { fn proof_path(claim: &Claim) -> PathBuf { let name = proof_filename(claim); - let mut path = PathBuf::new(); - path.push(TEST_DATA_DIR); + let mut path = test_helper_data_dir(); path.push(Path::new(&name)); path } + /// Tries to load a proof for the claim from the test data directory + fn try_load_proof_from_disk(claim: &Claim) -> Option { + let file_path = proof_path(claim); + let file_contents = try_load_file_from_disk(&file_path)?; + + let mut proof_data = vec![]; + for ch in file_contents.chunks(8) { + if let Ok(eight_bytes) = TryInto::<[u8; 8]>::try_into(ch) { + proof_data.push(BFieldElement::new(u64::from_be_bytes(eight_bytes))); + } else { + debug!("cannot cast chunk to eight bytes"); + return None; + } + } + + let proof = Proof::from(proof_data); + Some(proof) + } + /// First, attempt to load the proof from disk. If it does not exist, /// attempt to fetch it online. If that also fails, run the prover and /// save the proof before returning it. @@ -395,66 +409,6 @@ pub mod tests { } } - /// Tries to load a proof for the claim from the test data directory - fn try_load_proof_from_disk(claim: &Claim) -> Option { - let path = proof_path(claim); - let Ok(mut input_file) = File::open(path.clone()) else { - debug!("cannot open file '{}' -- might not exist", path.display()); - return None; - }; - let mut file_contents = vec![]; - if input_file.read_to_end(&mut file_contents).is_err() { - debug!("cannot read file '{}'", path.display()); - return None; - } - let mut proof_data = vec![]; - for ch in file_contents.chunks(8) { - if let Ok(eight_bytes) = TryInto::<[u8; 8]>::try_into(ch) { - proof_data.push(BFieldElement::new(u64::from_be_bytes(eight_bytes))); - } else { - debug!("cannot cast chunk to eight bytes"); - return None; - } - } - let proof = Proof::from(proof_data); - Some(proof) - } - - /// Load a list of proof-servers from test data directory - fn load_servers() -> Vec { - let mut server_list_path = PathBuf::new(); - server_list_path.push(TEST_DATA_DIR); - server_list_path.push(Path::new("proof_servers").with_extension("txt")); - let Ok(mut input_file) = File::open(server_list_path.clone()) else { - debug!( - "cannot proof-server list '{}' -- file might not exist", - server_list_path.display() - ); - return vec![]; - }; - let mut file_contents = vec![]; - if input_file.read_to_end(&mut file_contents).is_err() { - debug!("cannot read file '{}'", server_list_path.display()); - return vec![]; - } - let Ok(file_as_string) = String::from_utf8(file_contents) else { - debug!( - "cannot parse file '{}' -- is it valid utf8?", - server_list_path.display() - ); - return vec![]; - }; - file_as_string.lines().map(|s| s.to_string()).collect() - } - - #[test] - fn test_load_servers() { - let servers = load_servers(); - for server in servers { - println!("read server: {}", server); - } - } - /// Queries known servers for proofs. /// /// The proof-servers file is located in `proof_servers.txt` test data @@ -481,113 +435,21 @@ pub mod tests { /// not store the proof to disk. /// TODO: Consider making this async. fn try_fetch_from_server_inner(filename: String) -> Option<(Proof, String)> { - fn get_test_name_from_tracing() -> String { - match Span::current().metadata().map(|x| x.name()) { - Some(test_name) => test_name.to_owned(), - None => "unknown".to_owned(), - } - } - - fn attempt_to_get_test_name() -> String { - let thread = std::thread::current(); - match thread.name() { - Some(test_name) => { - if test_name.eq("tokio-runtime-worker") { - get_test_name_from_tracing() - } else { - test_name.to_owned() - } - } - None => get_test_name_from_tracing(), - } - } - - let mut servers = load_servers(); - servers.shuffle(&mut rand::rng()); - - // Add test name to request allow server to see which test requires a proof - let mut headers = clienter::HttpHeaders::default(); - headers.insert( - TEST_NAME_HTTP_HEADER_KEY.to_string(), - attempt_to_get_test_name(), - ); + let (file_contents, server) = try_fetch_file_from_server(filename)?; - for server in servers { - let server_ = server.clone(); - let filename_ = filename.clone(); - let headers_ = headers.clone(); - let handle = std::thread::spawn(move || { - let url = format!("{}{}", server_, filename_); - - debug!("requesting: <{url}>"); - - let uri: clienter::Uri = url.into(); - - let mut http_client = clienter::HttpClient::new(); - http_client.timeout = Some(Duration::from_secs(10)); - http_client.headers = headers_; - let request = http_client.request(clienter::HttpMethod::GET, uri); - - // note: send() blocks - let Ok(mut response) = http_client.send(&request) else { - println!( - "server '{}' failed for file '{}'; trying next ...", - server_.clone(), - filename_ - ); - - return None; - }; - - // only retrieve body if we got a 2xx code. - // addresses #477 - // https://github.com/Neptune-Crypto/neptune-core/issues/477 - let body = if response.status.is_success() { - response.body() - } else { - Ok(vec![]) - }; - - Some((response.status, body)) - }); - - let Some((status_code, body)) = handle.join().unwrap() else { - eprintln!("Could not connect to server {server}."); - continue; - }; - - if !status_code.is_success() { - eprintln!("{server} responded with {status_code}"); - continue; - } - - let Ok(file_contents) = body else { - eprintln!( - "error reading file '{}' from server '{}'; trying next ...", - filename, server - ); - - continue; - }; - - let mut proof_data = vec![]; - for ch in file_contents.chunks(8) { - if let Ok(eight_bytes) = TryInto::<[u8; 8]>::try_into(ch) { - proof_data.push(BFieldElement::new(u64::from_be_bytes(eight_bytes))); - } else { - eprintln!("cannot cast chunk to eight bytes. Server was: {server}"); - } + let mut proof_data = vec![]; + for ch in file_contents.chunks(8) { + if let Ok(eight_bytes) = TryInto::<[u8; 8]>::try_into(ch) { + proof_data.push(BFieldElement::new(u64::from_be_bytes(eight_bytes))); + } else { + eprintln!("cannot cast chunk to eight bytes. Server was: {server}"); } - - let proof = Proof::from(proof_data); - println!("got proof."); - - return Some((proof, server)); } - println!("No known servers serve file `{}`", filename); + let proof = Proof::from(proof_data); + println!("got proof."); - None + Some((proof, server)) } #[apply(shared_tokio_runtime)] @@ -622,10 +484,9 @@ pub mod tests { nondeterminism: NonDeterminism, ) -> Proof { let name = proof_filename(claim); - let mut path = PathBuf::new(); - path.push(TEST_DATA_DIR); + let mut path = test_helper_data_dir(); create_dir_all(&path) - .unwrap_or_else(|_| panic!("cannot create '{TEST_DATA_DIR}' directory")); + .unwrap_or_else(|_| panic!("cannot create '{}' directory", path.to_string_lossy())); path.push(Path::new(&name)); let proof: Proof = triton_vm::prove(Stark::default(), claim, program, nondeterminism) diff --git a/src/models/state/archival_state.rs b/src/models/state/archival_state.rs index f933ecc5b..dcfce0c99 100644 --- a/src/models/state/archival_state.rs +++ b/src/models/state/archival_state.rs @@ -18,7 +18,6 @@ pub(crate) mod bootstrap_from_block_files; use super::shared::new_block_file_is_needed; use super::StorageVecBase; use crate::config_models::data_directory::DataDirectory; -use crate::config_models::network::Network; use crate::database::create_db_if_missing; use crate::database::storage::storage_schema::traits::*; use crate::database::NeptuneLevelDb; @@ -96,7 +95,7 @@ impl core::fmt::Debug for ArchivalState { impl ArchivalState { /// Create databases for block persistence - pub(crate) async fn initialize_block_index_database( + async fn initialize_block_index_database( data_dir: &DataDirectory, ) -> Result> { let block_index_db_dir_path = data_dir.block_index_database_dir_path(); @@ -112,9 +111,7 @@ impl ArchivalState { } /// Initialize an `ArchivalMutatorSet` by opening or creating its databases. - pub(crate) async fn initialize_mutator_set( - data_dir: &DataDirectory, - ) -> Result { + async fn initialize_mutator_set(data_dir: &DataDirectory) -> Result { let ms_db_dir_path = data_dir.mutator_set_database_dir_path(); DataDirectory::create_dir_if_not_exists(&ms_db_dir_path).await?; @@ -143,7 +140,7 @@ impl ArchivalState { Ok(archival_set) } - pub(crate) async fn initialize_archival_block_mmr( + async fn initialize_archival_block_mmr( data_dir: &DataDirectory, ) -> Result { let abmmr_dir_path = data_dir.archival_block_mmr_dir_path(); @@ -236,14 +233,11 @@ impl ArchivalState { (leaving, luca, arriving) } - pub(crate) async fn new( - data_dir: DataDirectory, - block_index_db: NeptuneLevelDb, - mut archival_mutator_set: RustyArchivalMutatorSet, - mut archival_block_mmr: RustyArchivalBlockMmr, - network: Network, - ) -> Self { - let genesis_block = Box::new(Block::genesis(network)); + pub(crate) async fn new(data_dir: DataDirectory, genesis_block: Block) -> Self { + let mut archival_mutator_set = ArchivalState::initialize_mutator_set(&data_dir) + .await + .expect("Must be able to initialize archival mutator set"); + debug!("Got archival mutator set"); // If archival mutator set is empty, populate it with the addition records from genesis block // This assumes genesis block doesn't spend anything -- which it can't so that should be OK. @@ -259,6 +253,11 @@ impl ArchivalState { archival_mutator_set.persist().await; } + let mut archival_block_mmr = ArchivalState::initialize_archival_block_mmr(&data_dir) + .await + .expect("Must be able to initialize archival block MMR"); + debug!("Got archival block MMR"); + // Add genesis block digest to archival MMR, if empty. if archival_block_mmr.ammr().is_empty().await { archival_block_mmr @@ -267,6 +266,11 @@ impl ArchivalState { .await; } + let block_index_db = ArchivalState::initialize_block_index_database(&data_dir) + .await + .expect("Must be able to initialize block index database"); + debug!("Got block index database"); + let genesis_block = Box::new(genesis_block); Self { data_dir, block_index_db, @@ -1190,24 +1194,17 @@ pub(super) mod tests { use crate::tests::shared::mock_genesis_archival_state; use crate::tests::shared::mock_genesis_global_state; use crate::tests::shared::mock_genesis_wallet_state; - use crate::tests::shared::unit_test_databases; + use crate::tests::shared::unit_test_data_directory; use crate::tests::shared_tokio_runtime; use crate::triton_vm_job_queue::TritonVmJobPriority; use crate::triton_vm_job_queue::TritonVmJobQueue; use crate::util_types::test_shared::mutator_set::random_removal_record; pub(super) async fn make_test_archival_state(network: Network) -> ArchivalState { - let (block_index_db, _peer_db_lock, data_dir) = unit_test_databases(network).await.unwrap(); - - let ams = ArchivalState::initialize_mutator_set(&data_dir) - .await - .unwrap(); - - let archival_block_mmr = ArchivalState::initialize_archival_block_mmr(&data_dir) - .await - .unwrap(); + let data_dir: DataDirectory = unit_test_data_directory(network).unwrap(); - ArchivalState::new(data_dir, block_index_db, ams, archival_block_mmr, network).await + let genesis_block = Block::genesis(network); + ArchivalState::new(data_dir, genesis_block).await } #[traced_test] @@ -1295,9 +1292,9 @@ pub(super) mod tests { // Verify that a restored archival mutator set is populated with the right `sync_label` let network = Network::Beta; let mut archival_state = make_test_archival_state(network).await; - let cli_args = cli_args::Args::default(); + let cli_args = cli_args::Args::default_with_network(network); let genesis_wallet_state = - mock_genesis_wallet_state(WalletEntropy::devnet_wallet(), network, &cli_args).await; + mock_genesis_wallet_state(WalletEntropy::devnet_wallet(), &cli_args).await; let (mock_block_1, _) = make_mock_block( network, &archival_state.genesis_block, @@ -1337,9 +1334,9 @@ pub(super) mod tests { let mut rng = StdRng::seed_from_u64(107221549301u64); let cli_args = cli_args::Args::default_with_network(network); let alice_wallet = - mock_genesis_wallet_state(WalletEntropy::devnet_wallet(), network, &cli_args).await; + mock_genesis_wallet_state(WalletEntropy::devnet_wallet(), &cli_args).await; let alice_wallet = alice_wallet.wallet_entropy; - let mut alice = mock_genesis_global_state(network, 0, alice_wallet, cli_args).await; + let mut alice = mock_genesis_global_state(0, alice_wallet, cli_args).await; let alice_key = alice .lock_guard() .await @@ -1480,7 +1477,7 @@ pub(super) mod tests { let alice_key = alice_wallet.nth_generation_spending_key_for_tests(0); let alice_address = alice_key.to_address(); let cli_args = cli_args::Args::default_with_network(network); - let mut alice = mock_genesis_global_state(network, 42, alice_wallet, cli_args).await; + let mut alice = mock_genesis_global_state(42, alice_wallet, cli_args).await; let genesis_block = Block::genesis(network); let num_premine_utxos = Block::premine_utxos(network).len(); @@ -1576,7 +1573,7 @@ pub(super) mod tests { let alice_key = alice_wallet.nth_generation_spending_key_for_tests(0); let alice_address = alice_key.to_address(); let cli_args = cli_args::Args::default_with_network(network); - let mut alice = mock_genesis_global_state(network, 42, alice_wallet, cli_args).await; + let mut alice = mock_genesis_global_state(42, alice_wallet, cli_args).await; let mut expected_num_utxos = Block::premine_utxos(network).len(); let mut previous_block = genesis_block.clone(); @@ -1748,16 +1745,16 @@ pub(super) mod tests { async fn allow_multiple_inputs_and_outputs_in_block() { // Test various parts of the state update when a block contains multiple inputs and outputs let network = Network::Main; - let cli_args = cli_args::Args::default(); + let cli_args = cli_args::Args::default_with_network(network); let premine_rec_ws = - mock_genesis_wallet_state(WalletEntropy::devnet_wallet(), network, &cli_args).await; + mock_genesis_wallet_state(WalletEntropy::devnet_wallet(), &cli_args).await; let premine_rec_spending_key = premine_rec_ws.wallet_entropy.nth_generation_spending_key(0); let mut premine_rec = mock_genesis_global_state( - network, 3, premine_rec_ws.wallet_entropy, cli_args::Args { guesser_fraction: 0.0, + network, ..Default::default() }, ) @@ -1778,15 +1775,11 @@ pub(super) mod tests { let mut rng = StdRng::seed_from_u64(41251549301u64); let wallet_secret_alice = WalletEntropy::new_pseudorandom(rng.random()); let alice_spending_key = wallet_secret_alice.nth_generation_spending_key(0); - let mut alice = - mock_genesis_global_state(network, 3, wallet_secret_alice, cli_args::Args::default()) - .await; + let mut alice = mock_genesis_global_state(3, wallet_secret_alice, cli_args.clone()).await; let wallet_secret_bob = WalletEntropy::new_pseudorandom(rng.random()); let bob_spending_key = wallet_secret_bob.nth_generation_spending_key(0); - let mut bob = - mock_genesis_global_state(network, 3, wallet_secret_bob, cli_args::Args::default()) - .await; + let mut bob = mock_genesis_global_state(3, wallet_secret_bob, cli_args.clone()).await; let genesis_block = Block::genesis(network); let launch_date = genesis_block.header().timestamp; diff --git a/src/models/state/mempool.rs b/src/models/state/mempool.rs index 6ef061b6a..09afa18fa 100644 --- a/src/models/state/mempool.rs +++ b/src/models/state/mempool.rs @@ -1050,10 +1050,9 @@ mod tests { let bob_wallet_secret = WalletEntropy::devnet_wallet(); let bob_spending_key = bob_wallet_secret.nth_generation_spending_key_for_tests(0); let bob = mock_genesis_global_state( - network, 2, bob_wallet_secret.clone(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let in_seven_months = genesis_block.kernel.header.timestamp + Timestamp::months(7); @@ -1277,32 +1276,19 @@ mod tests { let network = Network::Main; let bob_wallet_secret = WalletEntropy::devnet_wallet(); let bob_spending_key = bob_wallet_secret.nth_generation_spending_key_for_tests(0); - let mut bob = mock_genesis_global_state( + let cli_args = cli_args::Args { + guesser_fraction: 0.0, network, - 2, - bob_wallet_secret, - cli_args::Args { - guesser_fraction: 0.0, - ..Default::default() - }, - ) - .await; + ..Default::default() + }; + let mut bob = mock_genesis_global_state(2, bob_wallet_secret, cli_args.clone()).await; let bob_address = bob_spending_key.to_address(); let alice_wallet = WalletEntropy::new_pseudorandom(rng.random()); let alice_key = alice_wallet.nth_generation_spending_key_for_tests(0); let alice_address = alice_key.to_address(); - let mut alice = mock_genesis_global_state( - network, - 2, - alice_wallet, - cli_args::Args { - guesser_fraction: 0.0, - ..Default::default() - }, - ) - .await; + let mut alice = mock_genesis_global_state(2, alice_wallet, cli_args.clone()).await; // Ensure that both wallets have a non-zero balance by letting Alice // mine a block. @@ -1654,10 +1640,10 @@ mod tests { let proving_capability = TxProvingCapability::SingleProof; let cli_with_proof_capability = cli_args::Args { tx_proving_capability: Some(proving_capability), + network, ..Default::default() }; - let mut alice = - mock_genesis_global_state(network, 2, alice_wallet, cli_with_proof_capability).await; + let mut alice = mock_genesis_global_state(2, alice_wallet, cli_with_proof_capability).await; let mut rng: StdRng = StdRng::seed_from_u64(u64::from_str_radix("42", 6).unwrap()); let bob_wallet_secret = WalletEntropy::new_pseudorandom(rng.random()); @@ -1797,10 +1783,9 @@ mod tests { // Create a global state object, controlled by a preminer who receives a premine-UTXO. let network = Network::Main; let mut preminer = mock_genesis_global_state( - network, 2, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let premine_spending_key = preminer @@ -2022,10 +2007,9 @@ mod tests { let bob_wallet_secret = WalletEntropy::devnet_wallet(); let bob_spending_key = bob_wallet_secret.nth_generation_spending_key_for_tests(0); let bob = mock_genesis_global_state( - network, 2, bob_wallet_secret.clone(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let in_seven_months = genesis_block.kernel.header.timestamp + Timestamp::months(7); diff --git a/src/models/state/mod.rs b/src/models/state/mod.rs index 94ff58c8a..62e8b6795 100644 --- a/src/models/state/mod.rs +++ b/src/models/state/mod.rs @@ -31,8 +31,10 @@ use anyhow::bail; use anyhow::ensure; use anyhow::Result; use block_proposal::BlockProposal; +use blockchain_state::BlockchainArchivalState; use blockchain_state::BlockchainState; use itertools::Itertools; +use light_state::LightState; use mempool::Mempool; use mempool::TransactionOrigin; use mining_state::MiningState; @@ -67,6 +69,7 @@ use super::peer::SyncChallengeResponse; use super::proof_abstractions::timestamp::Timestamp; use crate::api; use crate::config_models::cli_args; +use crate::config_models::data_directory::DataDirectory; use crate::database::storage::storage_schema::traits::StorageWriter as SW; use crate::database::storage::storage_vec::traits::*; use crate::database::storage::storage_vec::Index; @@ -77,6 +80,7 @@ use crate::main_loop::proof_upgrader::UpdateMutatorSetDataJob; use crate::mine_loop::composer_parameters::ComposerParameters; use crate::models::blockchain::block::block_header::BlockHeaderWithBlockHashWitness; use crate::models::blockchain::block::mutator_set_update::MutatorSetUpdate; +use crate::models::peer::peer_info::PeerInfo; use crate::models::peer::SYNC_CHALLENGE_POW_WITNESS_LENGTH; use crate::models::state::block_proposal::BlockProposalRejectError; use crate::models::state::wallet::expected_utxo::ExpectedUtxo; @@ -91,6 +95,7 @@ use crate::util_types::mutator_set::removal_record::RemovalRecord; use crate::ArchivalState; use crate::Hash; use crate::RPCServerToMain; +use crate::WalletFileContext; use crate::VERSION; /// `GlobalStateLock` holds a [`tokio::AtomicRw`](crate::locks::tokio::AtomicRw) @@ -161,21 +166,17 @@ pub struct GlobalStateLock { } impl GlobalStateLock { - /// the key to the watery kingdom. - pub fn new( - wallet_state: WalletState, - chain: BlockchainState, - net: NetworkingState, - cli: cli_args::Args, - mempool: Mempool, + pub fn from_global_state( + global_state: GlobalState, rpc_server_to_main_tx: tokio::sync::mpsc::Sender, ) -> Self { - let global_state = GlobalState::new(wallet_state, chain, net, cli.clone(), mempool); + let cli = global_state.cli.clone(); let global_state_lock = sync_tokio::AtomicRw::from(( global_state, Some("GlobalState"), Some(crate::LOG_TOKIO_LOCK_EVENT_CB), )); + Self { global_state_lock, cli, @@ -616,6 +617,49 @@ impl Drop for GlobalState { } impl GlobalState { + pub async fn try_new( + data_directory: DataDirectory, + genesis: Block, + cli: cli_args::Args, + ) -> Result { + // Get wallet object, create various wallet secret files + let wallet_dir = data_directory.wallet_directory_path(); + DataDirectory::create_dir_if_not_exists(&wallet_dir).await?; + let wallet_file_context = + WalletFileContext::read_from_file_or_create(&data_directory.wallet_directory_path())?; + debug!("Now getting wallet state. This may take a while if the database needs pruning."); + let wallet_state = + WalletState::try_new_from_context(&data_directory, wallet_file_context, &cli, &genesis) + .await?; + debug!("Got wallet state."); + + let archival_state = ArchivalState::new(data_directory.clone(), genesis).await; + debug!("Got archival state"); + + // Get latest block. Use hardcoded genesis block if nothing is in database. + let latest_block: Block = archival_state.get_tip().await; + + let peer_map: HashMap = HashMap::new(); + let peer_databases = NetworkingState::initialize_peer_databases(&data_directory).await?; + debug!("Got peer databases"); + + let net = NetworkingState::new(peer_map, peer_databases); + + let light_state: LightState = LightState::from(latest_block); + let chain = BlockchainArchivalState { + light_state, + archival_state, + }; + let chain = BlockchainState::Archival(Box::new(chain)); + let mempool = Mempool::new( + cli.max_mempool_size, + cli.max_mempool_num_tx, + chain.light_state().hash(), + ); + + Ok(Self::new(wallet_state, chain, net, cli, mempool)) + } + pub fn new( wallet_state: WalletState, chain: BlockchainState, @@ -1883,10 +1927,9 @@ mod tests { #[apply(shared_tokio_runtime)] async fn generating_own_handshake_doesnt_crash() { mock_genesis_global_state( - Network::Main, 2, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(Network::Main), ) .await .lock_guard() @@ -1899,10 +1942,9 @@ mod tests { async fn handshakes_listen_port_is_some_when_max_peers_is_default() { let network = Network::Main; let bob = mock_genesis_global_state( - network, 2, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; @@ -1919,10 +1961,9 @@ mod tests { async fn handshakes_listen_port_is_none_when_max_peers_is_zero() { let network = Network::Main; let mut bob = mock_genesis_global_state( - network, 2, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let no_incoming_connections = cli_args::Args { @@ -1944,10 +1985,9 @@ mod tests { async fn set_new_tip_clears_block_proposal_related_data() { let network = Network::Main; let mut bob = mock_genesis_global_state( - network, 2, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let mut bob = bob.global_state_lock.lock_guard_mut().await; @@ -1977,10 +2017,9 @@ mod tests { let alice = WalletEntropy::new_pseudorandom(rng.random()); let bob = mock_genesis_global_state( - network, 2, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; assert!( @@ -2357,7 +2396,6 @@ mod tests { let mut rng = rand::rng(); let network = Network::RegTest; let mut alice_state_lock = mock_genesis_global_state( - network, 2, WalletEntropy::devnet_wallet(), cli_args::Args::default_with_network(network), @@ -2416,10 +2454,9 @@ mod tests { let mut rng = rand::rng(); let mut alice = mock_genesis_global_state( - network, 2, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let mut alice = alice.lock_guard_mut().await; @@ -2677,10 +2714,9 @@ mod tests { let network = Network::Main; let mut rng = rand::rng(); let mut alice = mock_genesis_global_state( - network, 2, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let mut alice = alice.lock_guard_mut().await; @@ -2882,10 +2918,11 @@ mod tests { let cli_args = cli_args::Args { guesser_fraction: 0.0, + network, ..Default::default() }; let mut premine_receiver = - mock_genesis_global_state(network, 3, WalletEntropy::devnet_wallet(), cli_args).await; + mock_genesis_global_state(3, WalletEntropy::devnet_wallet(), cli_args.clone()).await; let genesis_spending_key = premine_receiver .lock_guard() .await @@ -2895,15 +2932,11 @@ mod tests { let wallet_secret_alice = WalletEntropy::new_pseudorandom(rng.random()); let alice_spending_key = wallet_secret_alice.nth_generation_spending_key_for_tests(0); - let mut alice = - mock_genesis_global_state(network, 3, wallet_secret_alice, cli_args::Args::default()) - .await; + let mut alice = mock_genesis_global_state(3, wallet_secret_alice, cli_args.clone()).await; let wallet_secret_bob = WalletEntropy::new_pseudorandom(rng.random()); let bob_spending_key = wallet_secret_bob.nth_generation_spending_key_for_tests(0); - let mut bob = - mock_genesis_global_state(network, 3, wallet_secret_bob, cli_args::Args::default()) - .await; + let mut bob = mock_genesis_global_state(3, wallet_secret_bob, cli_args.clone()).await; let genesis_block = Block::genesis(network); let in_seven_months = genesis_block.kernel.header.timestamp + Timestamp::months(7); @@ -3287,10 +3320,9 @@ mod tests { let network = Network::Main; let mut global_state_lock = mock_genesis_global_state( - network, 2, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let genesis_block = Block::genesis(network); @@ -3351,7 +3383,6 @@ mod tests { let network = Network::Main; let mut global_state_lock_small = mock_genesis_global_state( - network, 2, WalletEntropy::devnet_wallet(), cli_args::Args { @@ -3362,7 +3393,6 @@ mod tests { ) .await; let global_state_lock_big = mock_genesis_global_state( - network, 2, WalletEntropy::devnet_wallet(), cli_args::Args { @@ -3574,10 +3604,9 @@ mod tests { let spending_key = wallet_secret.nth_generation_spending_key(0); let mut global_state_lock = mock_genesis_global_state( - network, 2, wallet_secret.clone(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; @@ -3646,10 +3675,9 @@ mod tests { let wallet_secret = WalletEntropy::new_random(); let mut alice = mock_genesis_global_state( - network, 2, wallet_secret.clone(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; @@ -3701,10 +3729,9 @@ mod tests { let network = Network::Main; let wallet_secret = WalletEntropy::new_random(); let mut alice = mock_genesis_global_state( - network, 2, wallet_secret.clone(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let mut alice = alice.global_state_lock.lock_guard_mut().await; @@ -3770,10 +3797,9 @@ mod tests { for depth in 1..=4 { let mut alice = mock_genesis_global_state( - network, 2, wallet_secret.clone(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let mut alice = alice.global_state_lock.lock_guard_mut().await; @@ -3831,8 +3857,7 @@ mod tests { for claim_composer_fees in [false, true] { let mut global_state_lock = - mock_genesis_global_state(network, 2, wallet_secret.clone(), cli_args.clone()) - .await; + mock_genesis_global_state(2, wallet_secret.clone(), cli_args.clone()).await; let mut global_state = global_state_lock.lock_guard_mut().await; if claim_composer_fees { @@ -3932,10 +3957,9 @@ mod tests { for claim_cb in [false, true] { let expected_num_mutxos = if claim_cb { 3 } else { 1 }; let mut global_state_lock = mock_genesis_global_state( - network, 2, wallet_secret.clone(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let mut global_state = global_state_lock.lock_guard_mut().await; @@ -3969,7 +3993,13 @@ mod tests { } mod bootstrap_from_raw_block_files { + use std::fs::File; + use std::io::Write; + use super::*; + use crate::tests::shared::mock_genesis_global_state_with_block; + use crate::tests::shared::test_helper_data_dir; + use crate::tests::shared::try_fetch_file_from_server; async fn state_with_three_big_mocked_blocks(network: Network) -> GlobalStateLock { // Ensure more than one file is used to store blocks. @@ -3984,10 +4014,9 @@ mod tests { let peer_count = 0; let mut state = mock_genesis_global_state( - network, peer_count, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; { @@ -4008,10 +4037,9 @@ mod tests { let old_state = old_state.lock_guard().await; let mut new_state = mock_genesis_global_state( - network, 0, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let mut new_state = new_state.lock_guard_mut().await; @@ -4037,10 +4065,9 @@ mod tests { // Build the new state from the block directory of old state. let mut new_state = mock_genesis_global_state( - network, 0, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let mut new_state = new_state.lock_guard_mut().await; @@ -4071,6 +4098,75 @@ mod tests { "Restored wallet state must agree with original state" ); } + + #[traced_test] + #[apply(shared_tokio_runtime)] + async fn can_restore_from_real_mainnet_data_with_reorganizations() { + let expected_blk_files = ["blk0.dat"]; + let network = Network::Main; + + // We need to override difficulty since it's different when the + // test flag is set. We need the real main net block. + let mainnets_real_genesis_block = + Block::genesis(network).with_difficulty(network.genesis_difficulty()); + + // Use at least four MPs per UTXO, otherwise they get unsynced. + let cli = cli_args::Args { + network, + number_of_mps_per_utxo: 4, + ..Default::default() + }; + let peer_count = 0; + + let mut state = mock_genesis_global_state_with_block( + peer_count, + WalletEntropy::devnet_wallet(), + cli, + mainnets_real_genesis_block, + ) + .await; + let mut state = state.lock_guard_mut().await; + + // Are the required blk files present on disk? If not, fetch them + // from a server. + let test_data_dir = test_helper_data_dir(); + for blk_file_name in expected_blk_files { + let mut path = test_data_dir.clone(); + path.push(blk_file_name); + if File::open(&path).is_err() { + // Try fetching file from server and write it to disk. + let (file, _server) = try_fetch_file_from_server(blk_file_name.to_owned()) + .unwrap_or_else(|| { + panic!("File {blk_file_name} must be available from a server") + }); + let mut f = File::create_new(&path).unwrap(); + f.write_all(&file).unwrap(); + } + } + + let validate_blocks = true; + state + .bootstrap_from_directory(&test_data_dir, validate_blocks) + .await + .unwrap(); + let restored_block_height = state.chain.light_state().header().height; + assert_eq!( + BlockHeight::new(bfe!(113)), + restored_block_height, + "Expected block height not reached in state-recovery" + ); + + let wallet_status = state.get_wallet_status_for_tip().await; + let balance = state.wallet_state.confirmed_available_balance( + &wallet_status, + network.launch_date() + Timestamp::months(7), + ); + assert_eq!( + NativeCurrencyAmount::coins(20), + balance, + "Expected balance must be available after state-recovery" + ); + } } // note: removed test have_to_specify_change_policy() @@ -4193,25 +4289,20 @@ mod tests { let alice_to_bob_fee = NativeCurrencyAmount::coins(1); // init global state for alice bob - let mut alice_state_lock = mock_genesis_global_state( - network, - 3, - WalletEntropy::devnet_wallet(), - cli_args::Args::default(), - ) - .await; + let cli_args = cli_args::Args::default_with_network(network); + let mut alice_state_lock = + mock_genesis_global_state(3, WalletEntropy::devnet_wallet(), cli_args.clone()) + .await; let mut bob_state_lock = mock_genesis_global_state( - network, 3, WalletEntropy::new_pseudorandom(rng.random()), - cli_args::Args::default(), + cli_args.clone(), ) .await; let charlie_state_lock = mock_genesis_global_state( - network, 3, WalletEntropy::new_pseudorandom(rng.random()), - cli_args::Args::default(), + cli_args.clone(), ) .await; @@ -4387,10 +4478,9 @@ mod tests { { // devnet_wallet() stands in for alice's seed. let mut alice_restored_state_lock = mock_genesis_global_state( - network, 3, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; diff --git a/src/models/state/wallet/mod.rs b/src/models/state/wallet/mod.rs index 0b85ce998..4a0f4162d 100644 --- a/src/models/state/wallet/mod.rs +++ b/src/models/state/wallet/mod.rs @@ -86,7 +86,7 @@ mod tests { for network in Network::iter() { let cli_args = cli_args::Args::default_with_network(network); let mut alice = - mock_genesis_wallet_state(WalletEntropy::devnet_wallet(), network, &cli_args).await; + mock_genesis_wallet_state(WalletEntropy::devnet_wallet(), &cli_args).await; let alice_wallet = get_monitored_utxos(&alice).await; assert_eq!( 1, @@ -101,7 +101,7 @@ mod tests { ); let bob_wallet = WalletEntropy::new_pseudorandom(rng.random()); - let bob_wallet = mock_genesis_wallet_state(bob_wallet, network, &cli_args).await; + let bob_wallet = mock_genesis_wallet_state(bob_wallet, &cli_args).await; let bob_mutxos = get_monitored_utxos(&bob_wallet).await; assert!( bob_mutxos.is_empty(), @@ -152,10 +152,9 @@ mod tests { async fn wallet_state_correctly_updates_monitored_and_expected_utxos() { let mut rng = rand::rng(); let network = Network::RegTest; - let cli_args = cli_args::Args::default(); + let cli_args = cli_args::Args::default_with_network(network); let alice_wallet = WalletEntropy::new_random(); - let mut alice_wallet = - mock_genesis_wallet_state(alice_wallet.clone(), network, &cli_args).await; + let mut alice_wallet = mock_genesis_wallet_state(alice_wallet.clone(), &cli_args).await; let bob_wallet = WalletEntropy::new_random(); let bob_key = bob_wallet.nth_generation_spending_key_for_tests(0); @@ -275,9 +274,8 @@ mod tests { let network = Network::Main; let alice_wallet_secret = WalletEntropy::new_random(); - let mut alice = - mock_genesis_global_state(network, 1, alice_wallet_secret, cli_args::Args::default()) - .await; + let cli_args = cli_args::Args::default_with_network(network); + let mut alice = mock_genesis_global_state(1, alice_wallet_secret, cli_args).await; let alice_key = alice .lock_guard() .await @@ -518,12 +516,12 @@ mod tests { let cli_args = cli_args::Args { guesser_fraction: 0.0, number_of_mps_per_utxo: 20, + network, ..Default::default() }; let mut rng: StdRng = StdRng::seed_from_u64(456416); let alice_wallet_secret = WalletEntropy::new_pseudorandom(rng.random()); - let mut alice = - mock_genesis_global_state(network, 2, alice_wallet_secret, cli_args.clone()).await; + let mut alice = mock_genesis_global_state(2, alice_wallet_secret, cli_args.clone()).await; let alice_key = alice .lock_guard() .await @@ -532,12 +530,11 @@ mod tests { .nth_generation_spending_key_for_tests(0); let alice_address = alice_key.to_address(); let genesis_block = Block::genesis(network); - let bob_wallet = - mock_genesis_wallet_state(WalletEntropy::devnet_wallet(), network, &cli_args) - .await - .wallet_entropy; + let bob_wallet = mock_genesis_wallet_state(WalletEntropy::devnet_wallet(), &cli_args) + .await + .wallet_entropy; let mut bob_global_lock = - mock_genesis_global_state(network, 2, bob_wallet.clone(), cli_args.clone()).await; + mock_genesis_global_state(2, bob_wallet.clone(), cli_args.clone()).await; let mut tx_initiator_internal = bob_global_lock.api().tx_initiator_internal(); let in_seven_months = genesis_block.kernel.header.timestamp + Timestamp::months(7); @@ -1020,11 +1017,11 @@ mod tests { let genesis_block = Block::genesis(network); let in_seven_months = genesis_block.kernel.header.timestamp + Timestamp::months(7); let bob = mock_genesis_global_state( - network, 42, WalletEntropy::devnet_wallet(), cli_args::Args { guesser_fraction: 0.0, + network, ..Default::default() }, ) @@ -1261,14 +1258,14 @@ mod tests { #[apply(shared_tokio_runtime)] async fn verify_premine_receipt_works_with_test_addresses() { let network = Network::Main; - let cli = cli_args::Args::default(); + let cli = cli_args::Args::default_with_network(network); let genesis_block = Block::genesis(network); let seven_months_after_launch = genesis_block.header().timestamp + Timestamp::months(7); for seed_phrase in worker::test_seed_phrases() { let wallet_secret = WalletEntropy::from_phrase(&seed_phrase) .expect("legacy seed phrase must still be valid"); let premine_recipient = - mock_genesis_global_state(network, 0, wallet_secret, cli.clone()).await; + mock_genesis_global_state(0, wallet_secret, cli.clone()).await; let gs = premine_recipient.global_state_lock.lock_guard().await; let wallet_status = gs .wallet_state diff --git a/src/models/state/wallet/transaction_output.rs b/src/models/state/wallet/transaction_output.rs index 492455754..2d0c10dbb 100644 --- a/src/models/state/wallet/transaction_output.rs +++ b/src/models/state/wallet/transaction_output.rs @@ -707,11 +707,11 @@ mod tests { #[apply(shared_tokio_runtime)] async fn test_utxoreceiver_auto_not_owned_output() { + let network = Network::RegTest; let global_state_lock = mock_genesis_global_state( - Network::RegTest, 2, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; @@ -756,11 +756,11 @@ mod tests { #[apply(shared_tokio_runtime)] async fn test_utxoreceiver_auto_owned_output() { + let network = Network::RegTest; let mut global_state_lock = mock_genesis_global_state( - Network::RegTest, 2, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; diff --git a/src/models/state/wallet/wallet_state.rs b/src/models/state/wallet/wallet_state.rs index f87c33b16..0885ab60f 100644 --- a/src/models/state/wallet/wallet_state.rs +++ b/src/models/state/wallet/wallet_state.rs @@ -283,6 +283,7 @@ impl WalletState { data_dir: &DataDirectory, wallet_file_context: WalletFileContext, cli_args: &Args, + genesis: &Block, ) -> Result { let database_is_new = !tokio::fs::try_exists(&data_dir.wallet_database_dir_path()).await?; info!( @@ -300,13 +301,14 @@ impl WalletState { configuration.enable_scan_mode(); } - Self::try_new(configuration, wallet_entropy).await + Self::try_new(configuration, wallet_entropy, genesis).await } /// Construct a `WalletState` object. pub(crate) async fn try_new( configuration: WalletConfiguration, wallet_entropy: WalletEntropy, + genesis: &Block, ) -> anyhow::Result { const NUM_PREMINE_KEYS: usize = 10; @@ -431,10 +433,7 @@ impl WalletState { } wallet_state - .update_wallet_state_with_new_block( - &MutatorSetAccumulator::default(), - &Block::genesis(configuration.network()), - ) + .update_wallet_state_with_new_block(&MutatorSetAccumulator::default(), genesis) .await?; // No db-persisting here, as all of state should preferably be @@ -2035,7 +2034,10 @@ pub(crate) mod tests { cli_args: &Args, ) -> Self { let configuration = WalletConfiguration::new(data_dir).absorb_options(cli_args); - Self::try_new(configuration, wallet_entropy).await.unwrap() + let genesis_block = Block::genesis(configuration.network()); + Self::try_new(configuration, wallet_entropy, &genesis_block) + .await + .unwrap() } } @@ -2045,7 +2047,7 @@ pub(crate) mod tests { let network = Network::Testnet; let cli_args = cli_args::Args::default_with_network(network); let alice_global_lock = - mock_genesis_global_state(network, 0, WalletEntropy::devnet_wallet(), cli_args).await; + mock_genesis_global_state(0, WalletEntropy::devnet_wallet(), cli_args).await; let premine_utxo = { let wallet = &alice_global_lock.lock_guard().await.wallet_state; @@ -2095,10 +2097,9 @@ pub(crate) mod tests { let network = Network::Main; let mut alice_global_lock = mock_genesis_global_state( - network, 0, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; @@ -2203,12 +2204,12 @@ pub(crate) mod tests { network: Network, ) -> (Block, GlobalStateLock, GenerationSpendingKey) { let mut rng = rand::rng(); - let cli = cli_args::Args::default(); + let cli = cli_args::Args::default_with_network(network); let bob_wallet_secret = WalletEntropy::new_random(); let bob_key = bob_wallet_secret.nth_generation_spending_key_for_tests(0); let mut bob_global_lock = - mock_genesis_global_state(network, 0, bob_wallet_secret, cli.clone()).await; + mock_genesis_global_state(0, bob_wallet_secret, cli.clone()).await; // `bob` both composes and guesses the PoW solution of this block. let (block1, composer_fee_eutxos) = make_mock_block( @@ -2232,11 +2233,11 @@ pub(crate) mod tests { #[traced_test] async fn test_update_wallet_state_repeated_addition_records() { let network = Network::Main; - let cli = cli_args::Args::default(); + let cli = cli_args::Args::default_with_network(network); let alice_wallet_secret = WalletEntropy::new_random(); let alice_key = alice_wallet_secret.nth_generation_spending_key_for_tests(0); - let mut alice = mock_genesis_global_state(network, 0, alice_wallet_secret, cli).await; + let mut alice = mock_genesis_global_state(0, alice_wallet_secret, cli).await; let (block1, mut bob, bob_key) = bob_mines_one_block(network).await; @@ -2342,12 +2343,12 @@ pub(crate) mod tests { #[traced_test] async fn test_invalid_type_script_states() { let network = Network::Main; - let cli = cli_args::Args::default(); + let cli = cli_args::Args::default_with_network(network); let (block1, bob, bob_key) = bob_mines_one_block(network).await; let alice_wallet_secret = WalletEntropy::new_random(); let alice_key = alice_wallet_secret.nth_generation_spending_key_for_tests(0); - let mut alice = mock_genesis_global_state(network, 0, alice_wallet_secret, cli).await; + let mut alice = mock_genesis_global_state(0, alice_wallet_secret, cli).await; alice .lock_guard_mut() .await @@ -2442,11 +2443,11 @@ pub(crate) mod tests { #[traced_test] async fn test_unrecognized_type_script() { let network = Network::Main; - let cli = cli_args::Args::default(); + let cli = cli_args::Args::default_with_network(network); let alice_wallet_secret = WalletEntropy::new_random(); let alice_key = alice_wallet_secret.nth_generation_spending_key_for_tests(0); - let mut alice = mock_genesis_global_state(network, 0, alice_wallet_secret, cli).await; + let mut alice = mock_genesis_global_state(0, alice_wallet_secret, cli).await; let (block1, bob, bob_key) = bob_mines_one_block(network).await; @@ -2548,10 +2549,9 @@ pub(crate) mod tests { let bob_wallet_secret = WalletEntropy::new_random(); let bob_key = bob_wallet_secret.nth_generation_spending_key_for_tests(0); let mut bob_global_lock = mock_genesis_global_state( - network, 0, bob_wallet_secret.clone(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; @@ -2657,9 +2657,12 @@ pub(crate) mod tests { let network = Network::Main; let bob_wallet_secret = WalletEntropy::new_random(); let bob_key = bob_wallet_secret.nth_generation_spending_key_for_tests(0); - let mut bob_global_lock = - mock_genesis_global_state(network, 0, bob_wallet_secret, cli_args::Args::default()) - .await; + let mut bob_global_lock = mock_genesis_global_state( + 0, + bob_wallet_secret, + cli_args::Args::default_with_network(network), + ) + .await; let mut bob = bob_global_lock.lock_guard_mut().await; let genesis_block = Block::genesis(network); @@ -2746,9 +2749,12 @@ pub(crate) mod tests { let network = Network::RegTest; let bob_wallet_secret = WalletEntropy::new_random(); let bob_spending_key = bob_wallet_secret.nth_generation_spending_key_for_tests(0); - let mut bob_global_lock = - mock_genesis_global_state(network, 0, bob_wallet_secret, cli_args::Args::default()) - .await; + let mut bob_global_lock = mock_genesis_global_state( + 0, + bob_wallet_secret, + cli_args::Args::default_with_network(network), + ) + .await; let mut bob = bob_global_lock.lock_guard_mut().await; let genesis_block = Block::genesis(network); let monitored_utxos_count_init = bob.wallet_state.wallet_db.monitored_utxos().len().await; @@ -2930,7 +2936,7 @@ pub(crate) mod tests { let genesis_block = Block::genesis(network); let cli_args = cli_args::Args::default_with_network(network); - let wallet_state = mock_genesis_wallet_state(wallet, network, &cli_args).await; + let wallet_state = mock_genesis_wallet_state(wallet, &cli_args).await; // are we synchronized to the genesis block? assert_eq!( @@ -2985,7 +2991,6 @@ pub(crate) mod tests { let network = Network::Main; let genesis_block = Block::genesis(network); let mut bob = mock_genesis_global_state( - network, 3, WalletEntropy::new_random(), cli_args::Args::default_with_network(network), @@ -3257,9 +3262,9 @@ pub(crate) mod tests { async fn guesser_fee_scanner_finds_guesser_fee_iff_present() { let network = Network::Main; let mut rng = rng(); - let cli_args = cli_args::Args::default(); + let cli_args = cli_args::Args::default_with_network(network); let wallet_state = - mock_genesis_wallet_state(WalletEntropy::new_random(), network, &cli_args).await; + mock_genesis_wallet_state(WalletEntropy::new_random(), &cli_args).await; let composer_key = wallet_state.wallet_entropy.nth_generation_spending_key(0); let genesis_block = Block::genesis(network); let (mut incoming_block, _) = @@ -3318,10 +3323,9 @@ pub(crate) mod tests { let network = Network::Main; let mut rng = StdRng::seed_from_u64(664505904); let mut global_state_lock = mock_genesis_global_state( - network, 0, WalletEntropy::new_pseudorandom(rng.random()), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let change_key = global_state_lock @@ -3475,10 +3479,9 @@ pub(crate) mod tests { let mut rng = rand::rng(); let alice_wallet = WalletEntropy::new_pseudorandom(rng.random()); let mut alice = mock_genesis_global_state( - network, 0, alice_wallet.clone(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; @@ -3612,7 +3615,6 @@ pub(crate) mod tests { mod worker { use super::*; use crate::database::storage::storage_schema::traits::StorageWriter; - use crate::tests::shared::mock_genesis_wallet_state_with_data_dir; use crate::tests::shared::unit_test_data_directory; /// tests that all known keys are unique for a given key-type @@ -3625,13 +3627,10 @@ pub(crate) mod tests { info!("key_type: {}", key_type); // 1. Generate a mock WalletState - let cli_args = cli_args::Args::default(); - let mut wallet = mock_genesis_wallet_state( - WalletEntropy::new_random(), - Network::RegTest, - &cli_args, - ) - .await; + let network = Network::RegTest; + let cli_args = cli_args::Args::default_with_network(network); + let mut wallet = + mock_genesis_wallet_state(WalletEntropy::new_random(), &cli_args).await; let num_known_keys = wallet.get_known_addressable_spending_keys(key_type).count(); let num_to_derive = 20; @@ -3676,11 +3675,11 @@ pub(crate) mod tests { // 2. record wallet counter and known-keys // 3. persist wallet. // 4. forget wallet (dropped) - let cli_args = cli_args::Args::default(); + let cli_args = cli_args::Args::default_with_network(network); let (orig_counter, orig_known_keys) = { - let mut wallet = mock_genesis_wallet_state_with_data_dir( - wallet_secret.clone(), + let mut wallet = WalletState::new_from_wallet_entropy( &data_dir, + wallet_secret.clone(), &cli_args, ) .await; @@ -3701,8 +3700,7 @@ pub(crate) mod tests { // 5. instantiate 2nd wallet instance with same data_dir and secret as the first let wallet = - mock_genesis_wallet_state_with_data_dir(wallet_secret, &data_dir, &cli_args) - .await; + WalletState::new_from_wallet_entropy(&data_dir, wallet_secret, &cli_args).await; let persisted_counter = wallet.spending_key_counter(key_type); let persisted_known_keys = wallet @@ -3733,10 +3731,10 @@ pub(crate) mod tests { #[traced_test] #[apply(shared_tokio_runtime)] async fn insert_and_scan() { - let cli_args = cli_args::Args::default(); + let network = Network::RegTest; + let cli_args = cli_args::Args::default_with_network(network); let mut wallet = - mock_genesis_wallet_state(WalletEntropy::new_random(), Network::RegTest, &cli_args) - .await; + mock_genesis_wallet_state(WalletEntropy::new_random(), &cli_args).await; assert!(wallet.wallet_db.expected_utxos().is_empty().await); assert!(wallet.wallet_db.expected_utxos().len().await.is_zero()); @@ -3790,10 +3788,10 @@ pub(crate) mod tests { #[traced_test] #[apply(shared_tokio_runtime)] async fn prune_stale() { - let cli_args = cli_args::Args::default(); + let network = Network::RegTest; + let cli_args = cli_args::Args::default_with_network(network); let mut wallet = - mock_genesis_wallet_state(WalletEntropy::new_random(), Network::RegTest, &cli_args) - .await; + mock_genesis_wallet_state(WalletEntropy::new_random(), &cli_args).await; let mock_utxo = Utxo::new_native_currency( LockScript::anyone_can_spend(), @@ -3870,7 +3868,6 @@ pub(crate) mod tests { mod worker { use super::*; use crate::database::storage::storage_schema::traits::StorageWriter; - use crate::tests::shared::mock_genesis_wallet_state_with_data_dir; use crate::tests::shared::unit_test_data_directory; /// implements a test with 2 variations via `persist` param. @@ -3894,9 +3891,9 @@ pub(crate) mod tests { let cli_args = cli_args::Args::default(); // create initial wallet in a new directory - let mut wallet = mock_genesis_wallet_state_with_data_dir( - wallet_secret.clone(), + let mut wallet = WalletState::new_from_wallet_entropy( &data_dir, + wallet_secret.clone(), &cli_args, ) .await; @@ -3931,8 +3928,7 @@ pub(crate) mod tests { // re-create wallet state from same seed and same directory let restored_wallet = - mock_genesis_wallet_state_with_data_dir(wallet_secret, &data_dir, &cli_args) - .await; + WalletState::new_from_wallet_entropy(&data_dir, wallet_secret, &cli_args).await; // if wallet state was persisted to DB then we should have // 1 (restored) ExpectedUtxo, else 0. @@ -3998,10 +3994,9 @@ pub(crate) mod tests { let network = Network::Main; let alice_wallet = WalletEntropy::devnet_wallet(); let mut alice_global_lock = mock_genesis_global_state( - network, 0, alice_wallet.clone(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let genesis = Block::genesis(network); @@ -4114,10 +4109,9 @@ pub(crate) mod tests { let mut rng = rand::rng(); let alice_wallet = WalletEntropy::new_pseudorandom(rng.random()); let mut alice_global_lock = mock_genesis_global_state( - network, 0, alice_wallet.clone(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let genesis = Block::genesis(network); @@ -4209,10 +4203,9 @@ pub(crate) mod tests { // generate events let genesis_block = Block::genesis(network); let premine_receiver = mock_genesis_global_state( - network, 0, WalletEntropy::devnet_wallet(), - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let premine_change_key = premine_receiver @@ -4529,13 +4522,13 @@ pub(crate) mod tests { fee_notification: FeeNotificationPolicy::OffChain, scan_blocks: Some(0..=10), compose: true, + network, ..Default::default() }; dbg!(seed); let mut rng = StdRng::from_seed(seed); let wallet_secret = WalletEntropy::new_pseudorandom(rng.random()); - let mut rando = - mock_genesis_global_state(network, 2, wallet_secret.clone(), cli_args).await; + let mut rando = mock_genesis_global_state(2, wallet_secret.clone(), cli_args).await; println!("(ignore all log messages above this line)"); @@ -4662,13 +4655,14 @@ pub(crate) mod tests { let seed: [u8; 32] = random(); let cli_args = cli_args::Args { fee_notification: compose_fee_notification_policy, + network, ..Default::default() }; dbg!(seed); let mut rng = StdRng::from_seed(seed); let wallet_secret = WalletEntropy::new_pseudorandom(rng.random()); let mut global_state_lock = - mock_genesis_global_state(network, 2, wallet_secret.clone(), cli_args).await; + mock_genesis_global_state(2, wallet_secret.clone(), cli_args).await; println!("(ignore all log messages above this line)"); @@ -4794,11 +4788,11 @@ pub(crate) mod tests { let network = Network::Main; let cli_args = cli_args::Args { tx_proving_capability: Some(TxProvingCapability::SingleProof), + network, ..Default::default() }; let wallet_secret = WalletEntropy::devnet_wallet(); - let mut alice = - mock_genesis_global_state(network, 2, wallet_secret.clone(), cli_args).await; + let mut alice = mock_genesis_global_state(2, wallet_secret.clone(), cli_args).await; let genesis_block = Block::genesis(network); println!("(ignore all log messages above this line)"); @@ -4852,11 +4846,11 @@ pub(crate) mod tests { tx_proving_capability: Some(TxProvingCapability::SingleProof), // necessary to allow proof-collection -> single-proof upgrades for foreign transactions compose: true, + network, ..Default::default() }; let mut rando = - mock_genesis_global_state(network, 2, rando_wallet_secret.clone(), rando_cli_args) - .await; + mock_genesis_global_state(2, rando_wallet_secret.clone(), rando_cli_args).await; let upgrade_job_one = UpgradeJob::ProofCollectionToSingleProof { kernel: proof_collection_transaction.kernel.clone(), proof: proof_collection_transaction @@ -5029,11 +5023,15 @@ pub(crate) mod tests { let db_dir = configuration.data_directory().wallet_database_dir_path(); // instantiate WalletState to create a new DB and obtain schema version - let schema_version = - WalletState::try_new(configuration.clone(), wallet_entropy.clone()) - .await? - .wallet_db - .schema_version(); + let genesis_block = Block::genesis(configuration.network()); + let schema_version = WalletState::try_new( + configuration.clone(), + wallet_entropy.clone(), + &genesis_block, + ) + .await? + .wallet_db + .schema_version(); // perform db backup let backup_dir = WalletState::backup_database(&configuration, schema_version).await?; @@ -5053,10 +5051,11 @@ pub(crate) mod tests { std::fs::rename(&backup_dir, &db_dir)?; // load backup database into a new WalletState and obtain schema version - let schema_version_from_backup = WalletState::try_new(configuration, wallet_entropy) - .await? - .wallet_db - .schema_version(); + let schema_version_from_backup = + WalletState::try_new(configuration, wallet_entropy, &genesis_block) + .await? + .wallet_db + .schema_version(); // verify that schema version from backup DB matches original DB. assert_eq!(schema_version, schema_version_from_backup); diff --git a/src/peer_loop.rs b/src/peer_loop.rs index e36966379..f9c568e32 100644 --- a/src/peer_loop.rs +++ b/src/peer_loop.rs @@ -3719,9 +3719,12 @@ mod tests { ) -> Transaction { let wallet_secret = WalletEntropy::devnet_wallet(); let alice_key = wallet_secret.nth_generation_spending_key_for_tests(0); - let alice_gsl = - mock_genesis_global_state(network, 1, wallet_secret, cli_args::Args::default()) - .await; + let alice_gsl = mock_genesis_global_state( + 1, + wallet_secret, + cli_args::Args::default_with_network(network), + ) + .await; let alice = alice_gsl.lock_guard().await; let genesis_block = alice.chain.light_state(); let in_seven_months = genesis_block.header().timestamp + Timestamp::months(7); diff --git a/src/rpc_server.rs b/src/rpc_server.rs index a0c3ad508..0312a459c 100644 --- a/src/rpc_server.rs +++ b/src/rpc_server.rs @@ -3680,15 +3680,14 @@ mod tests { use crate::Block; async fn test_rpc_server( - network: Network, wallet_entropy: WalletEntropy, peer_count: u8, cli: cli_args::Args, ) -> NeptuneRPCServer { let global_state_lock = - mock_genesis_global_state(network, peer_count, wallet_entropy, cli).await; + mock_genesis_global_state(peer_count, wallet_entropy, cli.clone()).await; - let data_directory = unit_test_data_directory(network).unwrap(); + let data_directory = unit_test_data_directory(cli.network).unwrap(); let valid_tokens: Vec = vec![rpc_auth::Cookie::try_new(&data_directory) .await @@ -3717,13 +3716,9 @@ mod tests { // Verify that a wallet not receiving a premine is empty at startup for network in Network::iter() { let rpc_server = test_rpc_server( - network, WalletEntropy::new_random(), 2, - cli_args::Args { - network, - ..Default::default() - }, + cli_args::Args::default_with_network(network), ) .await; assert_eq!(network, rpc_server.network(context::current()).await?); @@ -3742,10 +3737,9 @@ mod tests { let mut rng = StdRng::seed_from_u64(123456789088u64); let rpc_server = test_rpc_server( - network, WalletEntropy::new_pseudorandom(rng.random()), 2, - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let token = cookie_token(&rpc_server).await; @@ -3889,10 +3883,9 @@ mod tests { async fn balance_is_zero_at_init() -> Result<()> { // Verify that a wallet not receiving a premine is empty at startup let rpc_server = test_rpc_server( - Network::Beta, WalletEntropy::new_random(), 2, - cli_args::Args::default(), + cli_args::Args::default_with_network(Network::Beta), ) .await; let token = cookie_token(&rpc_server).await; @@ -3909,10 +3902,9 @@ mod tests { #[apply(shared_tokio_runtime)] async fn clear_ip_standing_test() -> Result<()> { let mut rpc_server = test_rpc_server( - Network::Beta, WalletEntropy::new_random(), 2, - cli_args::Args::default(), + cli_args::Args::default_with_network(Network::Beta), ) .await; let token = cookie_token(&rpc_server).await; @@ -4068,10 +4060,9 @@ mod tests { async fn clear_all_standings_test() -> Result<()> { // Create initial conditions let mut rpc_server = test_rpc_server( - Network::Beta, WalletEntropy::new_random(), 2, - cli_args::Args::default(), + cli_args::Args::default_with_network(Network::Beta), ) .await; let token = cookie_token(&rpc_server).await; @@ -4197,10 +4188,9 @@ mod tests { #[apply(shared_tokio_runtime)] async fn utxo_digest_test() { let rpc_server = test_rpc_server( - Network::Beta, WalletEntropy::new_random(), 2, - cli_args::Args::default(), + cli_args::Args::default_with_network(Network::Beta), ) .await; let token = cookie_token(&rpc_server).await; @@ -4237,10 +4227,9 @@ mod tests { async fn block_info_test() { let network = Network::RegTest; let rpc_server = test_rpc_server( - network, WalletEntropy::new_random(), 2, - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let token = cookie_token(&rpc_server).await; @@ -4349,10 +4338,9 @@ mod tests { async fn public_announcements_in_block_test() { let network = Network::Main; let mut rpc_server = test_rpc_server( - network, WalletEntropy::new_random(), 2, - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let mut rng = rand::rng(); @@ -4417,10 +4405,9 @@ mod tests { async fn block_digest_test() { let network = Network::RegTest; let rpc_server = test_rpc_server( - network, WalletEntropy::new_random(), 2, - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let token = cookie_token(&rpc_server).await; @@ -4501,10 +4488,9 @@ mod tests { // the RPC call returns `None`, so we only verify that the call doesn't // crash the host machine, we don't verify that any value is returned. let rpc_server = test_rpc_server( - Network::Beta, WalletEntropy::new_random(), 2, - cli_args::Args::default(), + cli_args::Args::default_with_network(Network::Beta), ) .await; let token = cookie_token(&rpc_server).await; @@ -4526,10 +4512,11 @@ mod tests { // set flag on, verify non-initiation let cli_on = cli_args::Args { no_transaction_initiation: true, + network, ..Default::default() }; - let rpc_server = test_rpc_server(network, WalletEntropy::new_random(), 2, cli_on).await; + let rpc_server = test_rpc_server(WalletEntropy::new_random(), 2, cli_on).await; let token = cookie_token(&rpc_server).await; let output: OutputFormat = (address.into(), amount).into(); @@ -4583,10 +4570,9 @@ mod tests { async fn provide_solution_when_no_proposal_known() { let network = Network::Main; let bob = test_rpc_server( - network, WalletEntropy::new_random(), 2, - cli_args::Args::default(), + cli_args::Args::default_with_network(network), ) .await; let bob_token = cookie_token(&bob).await; @@ -4612,7 +4598,12 @@ mod tests { async fn cached_exported_proposals_are_stored_correctly() { let network = Network::Main; let bob = WalletEntropy::new_random(); - let mut bob = test_rpc_server(network, bob.clone(), 2, cli_args::Args::default()).await; + let mut bob = test_rpc_server( + bob.clone(), + 2, + cli_args::Args::default_with_network(network), + ) + .await; let genesis = Block::genesis(network); let block1 = invalid_empty_block(network, &genesis); @@ -4672,7 +4663,12 @@ mod tests { async fn exported_pow_puzzle_is_consistent_with_block_hash() { let network = Network::Main; let bob = WalletEntropy::new_random(); - let mut bob = test_rpc_server(network, bob.clone(), 2, cli_args::Args::default()).await; + let mut bob = test_rpc_server( + bob.clone(), + 2, + cli_args::Args::default_with_network(network), + ) + .await; let bob_token = cookie_token(&bob).await; let genesis = Block::genesis(network); @@ -4845,9 +4841,12 @@ mod tests { // bob's node let (pay_to_bob_outputs, bob_rpc_server, bob_token) = { - let rpc_server = - test_rpc_server(network, WalletEntropy::new_random(), 2, Args::default()) - .await; + let rpc_server = test_rpc_server( + WalletEntropy::new_random(), + 2, + Args::default_with_network(network), + ) + .await; let token = cookie_token(&rpc_server).await; let receiving_address_generation = rpc_server @@ -4883,10 +4882,10 @@ mod tests { let wallet_entropy = WalletEntropy::new_random(); let cli_args = cli_args::Args { tx_proving_capability: Some(TxProvingCapability::ProofCollection), + network, ..Default::default() }; - let mut rpc_server = - test_rpc_server(network, wallet_entropy.clone(), 2, cli_args).await; + let mut rpc_server = test_rpc_server(wallet_entropy.clone(), 2, cli_args).await; let token = cookie_token(&rpc_server).await; let genesis_block = Block::genesis(network); @@ -5040,9 +5039,10 @@ mod tests { let bob_wallet = WalletEntropy::new_random(); let cli_args = cli_args::Args { tx_proving_capability: Some(TxProvingCapability::ProofCollection), + network, ..Default::default() }; - let mut bob = test_rpc_server(network, bob_wallet.clone(), 2, cli_args).await; + let mut bob = test_rpc_server(bob_wallet.clone(), 2, cli_args).await; let bob_token = cookie_token(&bob).await; let bob_key = bob_wallet.nth_generation_spending_key(0); @@ -5221,15 +5221,11 @@ mod tests { let network = Network::Main; let cli_args = cli_args::Args { tx_proving_capability: Some(TxProvingCapability::ProofCollection), + network, ..Default::default() }; - let rpc_server = test_rpc_server( - network, - WalletEntropy::new_pseudorandom(rng.random()), - 2, - cli_args, - ) - .await; + let rpc_server = + test_rpc_server(WalletEntropy::new_pseudorandom(rng.random()), 2, cli_args).await; let token = cookie_token(&rpc_server).await; let ctx = context::current(); @@ -5296,10 +5292,10 @@ mod tests { let network = Network::Main; let cli_args = cli_args::Args { tx_proving_capability: Some(TxProvingCapability::SingleProof), + network, ..Default::default() }; - let mut rpc_server = - test_rpc_server(network, WalletEntropy::devnet_wallet(), 2, cli_args).await; + let mut rpc_server = test_rpc_server(WalletEntropy::devnet_wallet(), 2, cli_args).await; let ctx = context::current(); let token = cookie_token(&rpc_server).await; @@ -5368,15 +5364,12 @@ mod tests { let network = Network::Main; let cli_args = cli_args::Args { tx_proving_capability: Some(TxProvingCapability::ProofCollection), + network, ..Default::default() }; - let mut rpc_server = test_rpc_server( - network, - WalletEntropy::new_pseudorandom(rng.random()), - 2, - cli_args, - ) - .await; + let mut rpc_server = + test_rpc_server(WalletEntropy::new_pseudorandom(rng.random()), 2, cli_args) + .await; let token = cookie_token(&rpc_server).await; // --- Init. get wallet spending key --- diff --git a/src/tests/shared.rs b/src/tests/shared.rs index 3367b277e..e68786c37 100644 --- a/src/tests/shared.rs +++ b/src/tests/shared.rs @@ -1,11 +1,14 @@ use std::collections::HashMap; use std::env; use std::fmt::Debug; +use std::fs::File; +use std::io::Read; use std::net::SocketAddr; use std::path::Path; use std::path::PathBuf; use std::pin::Pin; use std::str::FromStr; +use std::time::Duration; use std::time::SystemTime; use anyhow::bail; @@ -28,6 +31,7 @@ use rand::distr::Alphanumeric; use rand::distr::SampleString; use rand::random; use rand::rngs::StdRng; +use rand::seq::SliceRandom; use rand::Rng; use rand::RngCore; use rand::SeedableRng; @@ -40,6 +44,8 @@ use tokio_serde::formats::SymmetricalBincode; use tokio_serde::Serializer; use tokio_util::codec::Encoder; use tokio_util::codec::LengthDelimitedCodec; +use tracing::debug; +use tracing::Span; use twenty_first::math::b_field_element::BFieldElement; use twenty_first::math::digest::Digest; use twenty_first::util_types::mmr::mmr_trait::Mmr; @@ -49,7 +55,6 @@ use crate::config_models::data_directory::DataDirectory; use crate::config_models::fee_notification_policy::FeeNotificationPolicy; use crate::config_models::network::Network; use crate::database::storage::storage_vec::traits::StorageVecBase; -use crate::database::NeptuneLevelDb; use crate::mine_loop::composer_parameters::ComposerParameters; use crate::mine_loop::make_coinbase_transaction_stateless; use crate::mine_loop::prepare_coinbase_transaction_stateless; @@ -81,8 +86,6 @@ use crate::models::blockchain::type_scripts::native_currency_amount::NativeCurre use crate::models::blockchain::type_scripts::time_lock::neptune_arbitrary::arbitrary_primitive_witness_with_expired_timelocks; use crate::models::channel::MainToPeerTask; use crate::models::channel::PeerTaskToMain; -use crate::models::database::BlockIndexKey; -use crate::models::database::BlockIndexValue; use crate::models::database::PeerDatabases; use crate::models::peer::handshake_data::VersionString; use crate::models::peer::peer_info::PeerConnectionInfo; @@ -103,8 +106,10 @@ use crate::models::state::wallet::address::generation_address::GenerationReceivi use crate::models::state::wallet::expected_utxo::ExpectedUtxo; use crate::models::state::wallet::expected_utxo::UtxoNotifier; use crate::models::state::wallet::transaction_output::TxOutputList; +use crate::models::state::wallet::wallet_configuration::WalletConfiguration; use crate::models::state::wallet::wallet_entropy::WalletEntropy; use crate::models::state::wallet::wallet_state::WalletState; +use crate::models::state::GlobalState; use crate::models::state::GlobalStateLock; use crate::prelude::twenty_first; use crate::triton_vm_job_queue::TritonVmJobQueue; @@ -121,23 +126,6 @@ pub fn get_peer_map() -> HashMap { HashMap::new() } -// Return empty database objects, and root directory for this unit test instantiation's -/// data directory. -pub async fn unit_test_databases( - network: Network, -) -> Result<( - NeptuneLevelDb, - PeerDatabases, - DataDirectory, -)> { - let data_dir: DataDirectory = unit_test_data_directory(network)?; - - let block_db = ArchivalState::initialize_block_index_database(&data_dir).await?; - let peer_db = NetworkingState::initialize_peer_databases(&data_dir).await?; - - Ok((block_db, peer_db, data_dir)) -} - pub fn get_dummy_socket_address(count: u8) -> SocketAddr { std::net::SocketAddr::from_str(&format!("127.0.0.{}:8080", count)).unwrap() } @@ -201,38 +189,35 @@ pub(crate) fn get_dummy_peer_connection_data_genesis( (handshake, socket_address) } -/// Get a global state object for unit test purposes. This global state -/// populated with state from the genesis block, e.g. in the archival mutator -/// set and the wallet. -/// +/// Get a global state object for unit test purposes. This global state is +/// populated with state from a caller-defined genesis block. /// All contained peers represent outgoing connections. -pub(crate) async fn mock_genesis_global_state( - // TODO: Remove network and read it from CLI arguments instead - network: Network, +pub(crate) async fn mock_genesis_global_state_with_block( peer_count: u8, wallet: WalletEntropy, cli: cli_args::Args, + genesis_block: Block, ) -> GlobalStateLock { - let (archival_state, peer_db, _data_dir) = mock_genesis_archival_state(network).await; + let data_dir: DataDirectory = unit_test_data_directory(cli.network).unwrap(); + let archival_state = ArchivalState::new(data_dir.clone(), genesis_block.clone()).await; + let peer_db = NetworkingState::initialize_peer_databases(&data_dir) + .await + .unwrap(); let mut peer_map: HashMap = get_peer_map(); for i in 0..peer_count { let peer_address = std::net::SocketAddr::from_str(&format!("123.123.123.{}:8080", i)).unwrap(); peer_map.insert(peer_address, get_dummy_peer_outgoing(peer_address)); } - let networking_state = NetworkingState::new(peer_map, peer_db); - let genesis_block = archival_state.get_tip().await; + let net = NetworkingState::new(peer_map, peer_db); // Sanity check assert_eq!(archival_state.genesis_block().hash(), genesis_block.hash()); + assert_eq!(archival_state.get_tip().await.hash(), genesis_block.hash()); let light_state: LightState = LightState::from(genesis_block.to_owned()); - println!( - "Genesis light state MSA hash: {}", - light_state.mutator_set_accumulator_after().hash() - ); - let blockchain_state = BlockchainState::Archival(Box::new(BlockchainArchivalState { + let chain = BlockchainState::Archival(Box::new(BlockchainArchivalState { light_state, archival_state, })); @@ -242,7 +227,10 @@ pub(crate) async fn mock_genesis_global_state( genesis_block.hash(), ); - let wallet_state = mock_genesis_wallet_state(wallet, network, &cli).await; + let configuration = WalletConfiguration::new(&data_dir).absorb_options(&cli); + let wallet_state = WalletState::try_new(configuration, wallet, &genesis_block) + .await + .unwrap(); // dummy channel let (rpc_to_main_tx, mut rpc_to_main_rx) = tokio::sync::mpsc::channel::(5); @@ -252,14 +240,23 @@ pub(crate) async fn mock_genesis_global_state( } }); - GlobalStateLock::new( - wallet_state, - blockchain_state, - networking_state, - cli.clone(), - mempool, - rpc_to_main_tx, - ) + let global_state = GlobalState::new(wallet_state, chain, net, cli, mempool); + + GlobalStateLock::from_global_state(global_state, rpc_to_main_tx) +} + +/// Get a global state object for unit test purposes. This global state is +/// populated with state from the genesis block, e.g. in the archival mutator +/// set and the wallet. +/// +/// All contained peers represent outgoing connections. +pub(crate) async fn mock_genesis_global_state( + peer_count: u8, + wallet: WalletEntropy, + cli: cli_args::Args, +) -> GlobalStateLock { + let genesis_block = Block::genesis(cli.network); + mock_genesis_global_state_with_block(peer_count, wallet, cli, genesis_block).await } /// A state with a premine UTXO and self-mined blocks. Both composing and @@ -270,11 +267,11 @@ pub(crate) async fn state_with_premine_and_self_mined_blocks( rng: &mut T, num_blocks_mined: usize, ) -> GlobalStateLock { + let network = cli_args.network; let wallet = WalletEntropy::devnet_wallet(); let own_key = wallet.nth_generation_spending_key_for_tests(0); - let network = cli_args.network; let mut global_state_lock = - mock_genesis_global_state(network, 2, wallet.clone(), cli_args).await; + mock_genesis_global_state(2, wallet.clone(), cli_args.clone()).await; let mut previous_block = Block::genesis(network); for _ in 0..num_blocks_mined { @@ -324,7 +321,7 @@ pub(crate) async fn get_test_genesis_setup( let (to_main_tx, to_main_rx) = mpsc::channel::(PEER_CHANNEL_CAPACITY); let devnet_wallet = WalletEntropy::devnet_wallet(); - let state = mock_genesis_global_state(network, peer_count, devnet_wallet, cli).await; + let state = mock_genesis_global_state(peer_count, devnet_wallet, cli).await; Ok(( peer_broadcast_tx, from_main_rx, @@ -456,6 +453,160 @@ impl stream::Stream for Mock { } } +/// Return path for the directory containing test data, like proofs and block +/// data. +pub(crate) fn test_helper_data_dir() -> PathBuf { + const TEST_DATA_DIR_NAME: &str = "test_data/"; + let mut path = PathBuf::new(); + path.push(TEST_DATA_DIR_NAME); + path +} + +/// Load a list of proof-servers from test data directory +fn load_servers() -> Vec { + let mut server_list_path = test_helper_data_dir(); + server_list_path.push(Path::new("proof_servers").with_extension("txt")); + let Ok(mut input_file) = File::open(server_list_path.clone()) else { + debug!( + "cannot proof-server list '{}' -- file might not exist", + server_list_path.display() + ); + return vec![]; + }; + let mut file_contents = vec![]; + if input_file.read_to_end(&mut file_contents).is_err() { + debug!("cannot read file '{}'", server_list_path.display()); + return vec![]; + } + let Ok(file_as_string) = String::from_utf8(file_contents) else { + debug!( + "cannot parse file '{}' -- is it valid utf8?", + server_list_path.display() + ); + return vec![]; + }; + file_as_string.lines().map(|s| s.to_string()).collect() +} + +/// Tries to load a file from disk, returns the bytes if successful. +pub(crate) fn try_load_file_from_disk(path: &Path) -> Option> { + let Ok(mut input_file) = File::open(path) else { + debug!("cannot open file '{}' -- might not exist", path.display()); + return None; + }; + + let mut file_contents = vec![]; + if input_file.read_to_end(&mut file_contents).is_err() { + debug!("cannot read file '{}'", path.display()); + return None; + } + + Some(file_contents) +} + +/// Return the specified file from a server, along with the name of the server +/// providing the result. +pub(crate) fn try_fetch_file_from_server(filename: String) -> Option<(Vec, String)> { + const TEST_NAME_HTTP_HEADER_KEY: &str = "Test-Name"; + + fn get_test_name_from_tracing() -> String { + match Span::current().metadata().map(|x| x.name()) { + Some(test_name) => test_name.to_owned(), + None => "unknown".to_owned(), + } + } + + fn attempt_to_get_test_name() -> String { + let thread = std::thread::current(); + match thread.name() { + Some(test_name) => { + if test_name.eq("tokio-runtime-worker") { + get_test_name_from_tracing() + } else { + test_name.to_owned() + } + } + None => get_test_name_from_tracing(), + } + } + + let mut servers = load_servers(); + servers.shuffle(&mut rand::rng()); + + // Add test name to request allow server to see which test requires this + // file. + let mut headers = clienter::HttpHeaders::default(); + headers.insert( + TEST_NAME_HTTP_HEADER_KEY.to_string(), + attempt_to_get_test_name(), + ); + + for server in servers { + let server_ = server.clone(); + let filename_ = filename.clone(); + let headers_ = headers.clone(); + let handle = std::thread::spawn(move || { + let url = format!("{}{}", server_, filename_); + + debug!("requesting: <{url}>"); + + let uri: clienter::Uri = url.into(); + + let mut http_client = clienter::HttpClient::new(); + http_client.timeout = Some(Duration::from_secs(10)); + http_client.headers = headers_; + let request = http_client.request(clienter::HttpMethod::GET, uri); + + // note: send() blocks + let Ok(mut response) = http_client.send(&request) else { + println!( + "server '{}' failed for file '{}'; trying next ...", + server_.clone(), + filename_ + ); + + return None; + }; + + // only retrieve body if we got a 2xx code. + // addresses #477 + // https://github.com/Neptune-Crypto/neptune-core/issues/477 + let body = if response.status.is_success() { + response.body() + } else { + Ok(vec![]) + }; + + Some((response.status, body)) + }); + + let Some((status_code, body)) = handle.join().unwrap() else { + eprintln!("Could not connect to server {server}."); + continue; + }; + + if !status_code.is_success() { + eprintln!("{server} responded with {status_code}"); + continue; + } + + let Ok(file_contents) = body else { + eprintln!( + "error reading file '{}' from server '{}'; trying next ...", + filename, server + ); + + continue; + }; + + return Some((file_contents, server)); + } + + println!("No known servers serve file `{}`", filename); + + None +} + pub fn pseudorandom_option(seed: [u8; 32], thing: T) -> Option { let mut rng: StdRng = SeedableRng::from_seed(seed); if rng.next_u32() % 2 == 0 { @@ -886,48 +1037,26 @@ pub(crate) async fn make_mock_block_with_inputs_and_outputs( .await } -/// Return a dummy-wallet used for testing. The returned wallet is populated with -/// whatever UTXOs are present in the genesis block. -pub async fn mock_genesis_wallet_state( +pub(crate) async fn mock_genesis_wallet_state( wallet_entropy: WalletEntropy, - network: Network, cli_args: &cli_args::Args, ) -> WalletState { - let data_dir = unit_test_data_directory(network).unwrap(); - mock_genesis_wallet_state_with_data_dir(wallet_entropy, &data_dir, cli_args).await -} - -pub async fn mock_genesis_wallet_state_with_data_dir( - wallet_entropy: WalletEntropy, - data_dir: &DataDirectory, - cli_args: &cli_args::Args, -) -> WalletState { - WalletState::new_from_wallet_entropy(data_dir, wallet_entropy, cli_args).await + let data_dir = unit_test_data_directory(cli_args.network).unwrap(); + WalletState::new_from_wallet_entropy(&data_dir, wallet_entropy, cli_args).await } /// Return an archival state populated with the genesis block pub(crate) async fn mock_genesis_archival_state( network: Network, ) -> (ArchivalState, PeerDatabases, DataDirectory) { - let (block_index_db, peer_db, data_dir) = unit_test_databases(network).await.unwrap(); + let data_dir: DataDirectory = unit_test_data_directory(network).unwrap(); - let ams = ArchivalState::initialize_mutator_set(&data_dir) + let genesis = Block::genesis(network); + let archival_state = ArchivalState::new(data_dir.clone(), genesis).await; + let peer_db = NetworkingState::initialize_peer_databases(&data_dir) .await .unwrap(); - let archival_block_mmr = ArchivalState::initialize_archival_block_mmr(&data_dir) - .await - .unwrap(); - - let archival_state = ArchivalState::new( - data_dir.clone(), - block_index_db, - ams, - archival_block_mmr, - network, - ) - .await; - (archival_state, peer_db, data_dir) } @@ -1351,3 +1480,15 @@ where } Ok(()) } + +mod tests { + use super::*; + + #[test] + fn test_load_servers() { + let servers = load_servers(); + for server in servers { + println!("read server: {}", server); + } + } +} diff --git a/src/util_types/mutator_set/chunk.rs b/src/util_types/mutator_set/chunk.rs index fd6395257..21f9000ef 100644 --- a/src/util_types/mutator_set/chunk.rs +++ b/src/util_types/mutator_set/chunk.rs @@ -132,16 +132,20 @@ impl<'a> Arbitrary<'a> for Chunk { #[cfg(test)] #[cfg_attr(coverage_nightly, coverage(off))] mod tests { - use std::collections::{HashMap, HashSet}; + use std::collections::HashMap; + use std::collections::HashSet; use num_traits::Zero; - use rand::{rng, RngCore}; - use statrs::distribution::{ContinuousCDF, Normal}; + use rand::rng; + use rand::RngCore; + use statrs::distribution::ContinuousCDF; + use statrs::distribution::Normal; use twenty_first::math::b_field_element::BFieldElement; - use crate::util_types::mutator_set::shared::{BATCH_SIZE, NUM_TRIALS, WINDOW_SIZE}; - use super::*; + use crate::util_types::mutator_set::shared::BATCH_SIZE; + use crate::util_types::mutator_set::shared::NUM_TRIALS; + use crate::util_types::mutator_set::shared::WINDOW_SIZE; #[test] fn chunk_is_reversible_bloom_filter() {