diff --git a/Cargo.lock b/Cargo.lock index b8f89b29..d9162d27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,7 +14,7 @@ dependencies = [ "merkle-log 0.0.4", "rand 0.8.5", "ring 0.16.20", - "serde 1.0.192", + "serde 1.0.193", "sha3", "time 0.3.30", "tracing", @@ -47,7 +47,7 @@ dependencies = [ "rocksdb", "rug", "rust-crypto", - "serde 1.0.192", + "serde 1.0.193", "serde_json", "sha3", "tokio", @@ -57,6 +57,8 @@ dependencies = [ "tracing", "tracing-futures", "tracing-subscriber", + "trust-dns-resolver", + "url", "warp", ] @@ -228,15 +230,15 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0c4a4f319e45986f347ee47fef8bf5e81c9abc3f6f58dc2391439f30df65f0" +checksum = "fc5ea910c42e5ab19012bab31f53cb4d63d54c3a27730f9a833a88efcf4bb52d" dependencies = [ - "async-lock 2.8.0", + "async-lock 3.1.1", "async-task", "concurrent-queue", "fastrand 2.0.1", - "futures-lite 1.13.0", + "futures-lite 2.0.1", "slab", ] @@ -286,9 +288,9 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.1.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb2ab2aa8a746e221ab826c73f48bc6ba41be6763f0855cb249eb6d154cf1d7" +checksum = "655b9c7fe787d3b25cc0f804a1a8401790f0c5bc395beb5a64dc77d8de079105" dependencies = [ "event-listener 3.1.0", "event-listener-strategy", @@ -428,7 +430,7 @@ version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" dependencies = [ - "serde 1.0.192", + "serde 1.0.193", ] [[package]] @@ -496,7 +498,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ "async-channel 2.1.0", - "async-lock 3.1.0", + "async-lock 3.1.1", "async-task", "fastrand 2.0.1", "futures-io", @@ -535,7 +537,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" dependencies = [ - "serde 1.0.192", + "serde 1.0.193", ] [[package]] @@ -555,16 +557,16 @@ version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ - "serde 1.0.192", + "serde 1.0.193", ] [[package]] name = "cargo-platform" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12024c4645c97566567129c204f65d5815a8c9aecf30fcbe682b2fe034996d36" +checksum = "e34637b3140142bdf929fb439e8aa4ebad7651ebf7b1080b3930aa16ac1459ff" dependencies = [ - "serde 1.0.192", + "serde 1.0.193", ] [[package]] @@ -576,7 +578,7 @@ dependencies = [ "camino", "cargo-platform", "semver", - "serde 1.0.192", + "serde 1.0.193", "serde_json", ] @@ -687,7 +689,7 @@ dependencies = [ "lazy_static", "nom 5.1.3", "rust-ini", - "serde 1.0.192", + "serde 1.0.193", "serde-hjson", "serde_json", "toml", @@ -858,6 +860,18 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "enum-as-inner" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" +dependencies = [ + "heck", + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 2.0.39", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -1015,7 +1029,11 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3831c2651acb5177cbd83943f3d9c8912c5ad03c76afcc0e9511ba568ec5ebb" dependencies = [ + "fastrand 2.0.1", "futures-core", + "futures-io", + "memchr", + "parking", "pin-project-lite", ] @@ -1202,6 +1220,12 @@ dependencies = [ "http", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1223,6 +1247,17 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi 0.3.9", +] + [[package]] name = "http" version = "0.2.11" @@ -1344,6 +1379,24 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2 0.5.5", + "widestring", + "windows-sys 0.48.0", + "winreg", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + [[package]] name = "itoa" version = "1.0.9" @@ -1525,6 +1578,15 @@ dependencies = [ "value-bag", ] +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map 0.5.6", +] + [[package]] name = "lz4-sys" version = "1.9.4" @@ -1544,6 +1606,12 @@ dependencies = [ "libc", ] +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + [[package]] name = "matchers" version = "0.0.1" @@ -1630,7 +1698,7 @@ dependencies = [ "positioned-io", "rand 0.7.3", "rayon", - "serde 1.0.192", + "serde 1.0.193", "tempdir", "tempfile", "typenum", @@ -2273,6 +2341,16 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + [[package]] name = "ring" version = "0.16.20" @@ -2376,9 +2454,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.24" +version = "0.38.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ad981d6c340a49cdc40a1028d9c6084ec7e9fa33fcb839cab656a267071e234" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ "bitflags 2.4.1", "errno", @@ -2402,9 +2480,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.8" +version = "0.21.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446e14c5cda4f3f30fe71863c34ec70f5ac79d6087097ad0bb433e1be5edf04c" +checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" dependencies = [ "log", "ring 0.17.5", @@ -2499,7 +2577,7 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" dependencies = [ - "serde 1.0.192", + "serde 1.0.193", ] [[package]] @@ -2510,9 +2588,9 @@ checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" [[package]] name = "serde" -version = "1.0.192" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] @@ -2532,9 +2610,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", @@ -2549,7 +2627,7 @@ checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", - "serde 1.0.192", + "serde 1.0.193", ] [[package]] @@ -2570,7 +2648,7 @@ dependencies = [ "form_urlencoded", "itoa", "ryu", - "serde 1.0.192", + "serde 1.0.193", ] [[package]] @@ -2747,7 +2825,7 @@ dependencies = [ "cfg-if 1.0.0", "fastrand 2.0.1", "redox_syscall", - "rustix 0.38.24", + "rustix 0.38.25", "windows-sys 0.48.0", ] @@ -2808,7 +2886,7 @@ checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" dependencies = [ "deranged", "powerfmt", - "serde 1.0.192", + "serde 1.0.193", "time-core", ] @@ -2880,7 +2958,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.8", + "rustls 0.21.9", "tokio", ] @@ -2943,7 +3021,7 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ - "serde 1.0.192", + "serde 1.0.193", ] [[package]] @@ -3012,7 +3090,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" dependencies = [ - "serde 1.0.192", + "serde 1.0.193", "tracing-core", ] @@ -3027,7 +3105,7 @@ dependencies = [ "lazy_static", "matchers", "regex", - "serde 1.0.192", + "serde 1.0.193", "serde_json", "sharded-slab", "smallvec", @@ -3044,6 +3122,52 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee8098afad3fb0c54a9007aab6804558410503ad676d4633f9c2559a00ac0f" +[[package]] +name = "trust-dns-proto" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3119112651c157f4488931a01e586aa459736e9d6046d3bd9105ffb69352d374" +dependencies = [ + "async-trait", + "cfg-if 1.0.0", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna", + "ipnet", + "once_cell", + "rand 0.8.5", + "smallvec", + "thiserror", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "trust-dns-resolver" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a3e6c3aff1718b3c73e395d1f35202ba2ffa847c6a62eea0db8fb4cfe30be6" +dependencies = [ + "cfg-if 1.0.0", + "futures-util", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot", + "rand 0.8.5", + "resolv-conf", + "smallvec", + "thiserror", + "tokio", + "tracing", + "trust-dns-proto", +] + [[package]] name = "try-lock" version = "0.2.4" @@ -3158,9 +3282,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "uuid" -version = "1.5.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" dependencies = [ "getrandom 0.2.11", ] @@ -3240,7 +3364,7 @@ dependencies = [ "pin-project", "rustls-pemfile", "scoped-tls", - "serde 1.0.192", + "serde 1.0.193", "serde_json", "serde_urlencoded", "tokio", @@ -3356,6 +3480,12 @@ dependencies = [ "untrusted 0.7.1", ] +[[package]] +name = "widestring" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" + [[package]] name = "winapi" version = "0.2.8" @@ -3531,6 +3661,16 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if 1.0.0", + "windows-sys 0.48.0", +] + [[package]] name = "yaml-rust" version = "0.4.5" @@ -3542,9 +3682,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12a3946ecfc929b583800f4629b6c25b88ac6e92a40ea5670f77112a85d40a8b" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" [[package]] name = "zstd-sys" diff --git a/Cargo.toml b/Cargo.toml index 3ce71bac..e080414c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,6 +41,8 @@ tracing = "0.1.13" tracing-subscriber = "0.2.3" tracing-futures = "0.2.3" warp = { version = "0.3.1", features = ["tls"] } +url = "2.4.1" +trust-dns-resolver = "0.23.2" [features] mock = [] diff --git a/src/active_raft.rs b/src/active_raft.rs index af4d5f18..0c10cc1f 100644 --- a/src/active_raft.rs +++ b/src/active_raft.rs @@ -1,4 +1,3 @@ -use crate::configurations::NodeSpec; use crate::db_utils::{SimpleDb, SimpleDbError}; use crate::raft::{ CommitReceiver, RaftCmd, RaftCmdSender, RaftCommit, RaftCommitData, RaftData, @@ -39,7 +38,7 @@ impl ActiveRaft { /// Create ActiveRaft, need to spawn the raft loop to use raft. pub fn new( node_idx: usize, - node_specs: &[NodeSpec], + node_specs: &[SocketAddr], use_raft: bool, tick_timeout_duration: Duration, raft_db: SimpleDb, @@ -50,7 +49,7 @@ impl ActiveRaft { let peer_addr_vec: Vec<(u64, SocketAddr)> = peers .iter() .zip(node_specs.iter()) - .map(|(idx, spec)| (*idx, spec.address)) + .map(|(idx, spec)| (*idx, spec.clone())) .filter(|(idx, _)| use_raft || *idx == peer_id) .collect(); diff --git a/src/bin/node/compute.rs b/src/bin/node/compute.rs index b1e56842..6ad3d786 100644 --- a/src/bin/node/compute.rs +++ b/src/bin/node/compute.rs @@ -209,6 +209,7 @@ fn load_settings(matches: &clap::ArgMatches) -> config::Config { .unwrap(); settings.set_default("compute_api_port", 3002).unwrap(); settings.set_default("compute_api_use_tls", true).unwrap(); + settings.set_default("jurisdiction", "US").unwrap(); settings.set_default("compute_node_idx", 0).unwrap(); settings.set_default("compute_raft", 0).unwrap(); @@ -229,6 +230,7 @@ fn load_settings(matches: &clap::ArgMatches) -> config::Config { settings .merge(config::File::with_name(setting_file)) .unwrap(); + settings .merge(config::File::with_name(intial_block_setting_file)) .unwrap(); diff --git a/src/bin/node_settings_local_raft_1.toml b/src/bin/node_settings_local_raft_1.toml index cb858a71..f71d1b61 100644 --- a/src/bin/node_settings_local_raft_1.toml +++ b/src/bin/node_settings_local_raft_1.toml @@ -40,5 +40,5 @@ address = "127.0.0.1:12340" [[user_nodes]] address = "127.0.0.1:12360" -[[user_nodes]] -address = "127.0.0.1:12361" +#[[user_nodes]] +#"address"="127.0.0.1:12361" diff --git a/src/compute.rs b/src/compute.rs index 0538d3a1..9de9c320 100644 --- a/src/compute.rs +++ b/src/compute.rs @@ -16,7 +16,7 @@ use crate::raft::RaftCommit; use crate::threaded_call::{ThreadedCallChannel, ThreadedCallSender}; use crate::tracked_utxo::TrackedUtxoSet; use crate::utils::{ - apply_mining_tx, check_druid_participants, create_item_asset_tx_from_sig, + apply_mining_tx, check_druid_participants, create_item_asset_tx_from_sig, create_socket_addr, format_parition_pow_address, generate_pow_random_num, to_api_keys, to_route_pow_infos, validate_pow_block, validate_pow_for_address, ApiKeys, LocalEvent, LocalEventChannel, LocalEventSender, ResponseResult, RoutesPoWInfo, StringError, @@ -175,16 +175,26 @@ impl ComputeNode { /// * `config` - ComputeNodeConfig for the current compute node containing compute nodes and storage nodes /// * `extra` - additional parameter for construction pub async fn new(config: ComputeNodeConfig, mut extra: ExtraNodeParams) -> Result { - let addr = config + let raw_addr = config .compute_nodes .get(config.compute_node_idx) - .ok_or(ComputeError::ConfigError("Invalid compute index"))? - .address; - let storage_addr = config + .ok_or(ComputeError::ConfigError("Invalid compute index"))?; + let addr = create_socket_addr(&raw_addr.address).await.or_else(|_| { + Err(ComputeError::ConfigError( + "Invalid compute node address in config file", + )) + })?; + + let raw_storage_addr = config .storage_nodes .get(config.compute_node_idx) - .ok_or(ComputeError::ConfigError("Invalid storage index"))? - .address; + .ok_or(ComputeError::ConfigError("Invalid storage index"))?; + let storage_addr = create_socket_addr(&raw_storage_addr.address).await.or_else(|_| { + Err(ComputeError::ConfigError( + "Invalid storage node address in config file", + )) + })?; + let tcp_tls_config = TcpTlsConfig::from_tls_spec(addr, &config.tls_config)?; let api_addr = SocketAddr::new(addr.ip(), config.compute_api_port); let api_tls_info = config diff --git a/src/compute_raft.rs b/src/compute_raft.rs index d8d41936..0860a7ab 100644 --- a/src/compute_raft.rs +++ b/src/compute_raft.rs @@ -12,8 +12,8 @@ use crate::raft_util::{RaftContextKey, RaftInFlightProposals}; use crate::tracked_utxo::TrackedUtxoSet; use crate::unicorn::{UnicornFixedParam, UnicornInfo}; use crate::utils::{ - calculate_reward, get_total_coinbase_tokens, make_utxo_set_from_seed, BackupCheck, - UtxoReAlignCheck, + calculate_reward, create_socket_addr_for_list, get_total_coinbase_tokens, + make_utxo_set_from_seed, BackupCheck, UtxoReAlignCheck, }; use a_block_chain::crypto::sha3_256; use a_block_chain::primitives::asset::TokenAmount; @@ -239,9 +239,15 @@ impl ComputeRaft { if config.backup_restore.unwrap_or(false) { db_utils::restore_file_backup(config.compute_db_mode, &DB_SPEC, None).unwrap(); } + let raw_node_ips = config + .compute_nodes + .clone() + .into_iter() + .map(|v| v.address.clone()) + .collect::>(); let raft_active = ActiveRaft::new( config.compute_node_idx, - &config.compute_nodes, + &create_socket_addr_for_list(&raw_node_ips).await.unwrap_or_default(), use_raft, Duration::from_millis(config.compute_raft_tick_timeout as u64), db_utils::new_db(config.compute_db_mode, &DB_SPEC, raft_db, None), @@ -1593,7 +1599,7 @@ fn take_first_n(n: usize, from: &mut BTreeMap) -> BTree mod test { use super::*; use crate::configurations::{DbMode, NodeSpec, TxOutSpec}; - use crate::utils::{create_valid_transaction, get_test_common_unicorn}; + use crate::utils::{create_socket_addr, create_valid_transaction, get_test_common_unicorn}; use a_block_chain::crypto::sign_ed25519 as sign; use a_block_chain::primitives::asset::TokenAmount; use rug::Integer; @@ -1881,9 +1887,7 @@ mod test { } async fn new_test_node(seed_utxo: &[&str]) -> ComputeRaft { - let compute_node = NodeSpec { - address: "0.0.0.0:0".parse().unwrap(), - }; + let compute_node = create_socket_addr("0.0.0.0").await.unwrap(); let tx_out = TxOutSpec { public_key: "5371832122a8e804fa3520ec6861c3fa554a7f6fb617e6f0768452090207e07c" .to_owned(), @@ -1895,9 +1899,11 @@ mod test { tls_config: Default::default(), api_keys: Default::default(), compute_unicorn_fixed_param: get_test_common_unicorn(), - compute_nodes: vec![compute_node], + compute_nodes: vec![NodeSpec { + address: compute_node.to_string(), + }], storage_nodes: vec![], - user_nodes: vec![], + user_nodes: Some(vec![]), compute_raft: 0, compute_raft_tick_timeout: 10, compute_mining_event_timeout: 500, diff --git a/src/configurations.rs b/src/configurations.rs index 948dc891..74bdd26e 100644 --- a/src/configurations.rs +++ b/src/configurations.rs @@ -1,3 +1,4 @@ +// use crate::comms_handler::Node; use crate::compute_raft::MinerWhitelist; use crate::db_utils::{CustomDbSpec, SimpleDb}; use crate::wallet::WalletDb; @@ -9,12 +10,6 @@ use std::net::SocketAddr; pub type UtxoSetSpec = BTreeMap>; -/// Configuration info for a node -#[derive(Debug, Clone, Copy, Deserialize)] -pub struct NodeSpec { - pub address: SocketAddr, -} - /// Configuration info for TLS #[derive(Default, Clone, Deserialize)] pub struct TlsSpec { @@ -95,6 +90,12 @@ pub enum DbMode { InMemory, } +/// Configuration info for a node +#[derive(Debug, Clone, Deserialize)] +pub struct NodeSpec { + pub address: String, +} + /// Configuration option for a compute node #[derive(Debug, Clone, Deserialize)] pub struct ComputeNodeConfig { @@ -113,7 +114,7 @@ pub struct ComputeNodeConfig { /// All storage nodes addresses: only use first pub storage_nodes: Vec, /// All user nodes addresses - pub user_nodes: Vec, + pub user_nodes: Option>, /// Whether compute node will use raft or act independently (0) pub compute_raft: usize, /// API port @@ -204,7 +205,7 @@ pub struct StorageNodeConfig { #[derive(Debug, Clone, Deserialize)] pub struct MinerNodeConfig { /// Socket Address of this miner node - pub miner_address: SocketAddr, + pub miner_address: String, /// Use specific database pub miner_db_mode: DbMode, /// Configuration for handling TLS @@ -239,7 +240,7 @@ pub struct MinerNodeConfig { #[derive(Debug, Clone, Deserialize)] pub struct UserNodeConfig { /// Socket Address of this User node - pub user_address: SocketAddr, + pub user_address: String, /// Use specific database pub user_db_mode: DbMode, /// Configuration for handling TLS @@ -287,9 +288,9 @@ pub struct PreLaunchNodeConfig { /// Use specific database pub storage_db_mode: DbMode, /// All compute nodes addresses - pub compute_nodes: Vec, + pub compute_nodes: Vec, /// All storage nodes addresses: only use first - pub storage_nodes: Vec, + pub storage_nodes: Vec, /// Limit for the number of peers this node can have pub peer_limit: usize, } diff --git a/src/miner.rs b/src/miner.rs index 8905932f..94afc999 100644 --- a/src/miner.rs +++ b/src/miner.rs @@ -7,7 +7,7 @@ use crate::interfaces::{ use crate::threaded_call::{ThreadedCallChannel, ThreadedCallSender}; use crate::transactor::Transactor; use crate::utils::{ - self, apply_mining_tx, construct_coinbase_tx, format_parition_pow_address, + self, apply_mining_tx, construct_coinbase_tx, create_socket_addr, format_parition_pow_address, generate_pow_for_block, get_paiments_for_wallet, get_paiments_for_wallet_from_utxo, to_api_keys, to_route_pow_infos, try_send_to_ui, ApiKeys, DeserializedBlockchainItem, LocalEvent, LocalEventChannel, LocalEventSender, ResponseResult, RoutesPoWInfo, @@ -176,11 +176,15 @@ impl MinerNode { /// * `extra` - additional parameter for construction pub async fn new(config: MinerNodeConfig, mut extra: ExtraNodeParams) -> Result { let addr = config.miner_address; - let compute_addr = config + let raw_compute_addr = config .compute_nodes .get(config.miner_compute_node_idx) - .ok_or(MinerError::ConfigError("Invalid compute index"))? - .address; + .ok_or(MinerError::ConfigError("Invalid compute index"))?; + let compute_addr = create_socket_addr(&raw_compute_addr.address).await.or_else(|_| { + Err(MinerError::ConfigError( + "Invalid compute node address in config file", + )) + })?; // Restore old keys if backup is present if config.backup_restore.unwrap_or(false) { @@ -194,8 +198,9 @@ impl MinerNode { extra.custom_wallet_spec, )?; let disable_tcp_listener = extra.disable_tcp_listener; - let tcp_tls_config = TcpTlsConfig::from_tls_spec(addr, &config.tls_config)?; - let api_addr = SocketAddr::new(addr.ip(), config.miner_api_port); + let tls_addr = create_socket_addr(&addr).await.unwrap(); + let tcp_tls_config = TcpTlsConfig::from_tls_spec(tls_addr, &config.tls_config)?; + let api_addr = SocketAddr::new(tls_addr.ip(), config.miner_api_port); let api_tls_info = config .miner_api_use_tls .then(|| tcp_tls_config.clone_private_info()); diff --git a/src/pre_launch.rs b/src/pre_launch.rs index bde92e58..531f0c83 100644 --- a/src/pre_launch.rs +++ b/src/pre_launch.rs @@ -1,11 +1,13 @@ use crate::comms_handler::{CommsError, Event, Node, TcpTlsConfig}; use crate::configurations::{ - DbMode, ExtraNodeParams, NodeSpec, PreLaunchNodeConfig, PreLaunchNodeType, TlsSpec, + DbMode, ExtraNodeParams, PreLaunchNodeConfig, PreLaunchNodeType, TlsSpec, }; use crate::db_utils::{self, SimpleDb, SimpleDbSpec}; use crate::interfaces::{DbItem, NodeType, PreLaunchRequest, Response}; use crate::raft_store::{get_presistent_committed, CommittedIndex}; -use crate::utils::{LocalEvent, LocalEventChannel, LocalEventSender, ResponseResult}; +use crate::utils::{ + create_socket_addr_for_list, LocalEvent, LocalEventChannel, LocalEventSender, ResponseResult, +}; use bincode::deserialize; use bytes::Bytes; use std::{collections::BTreeSet, error::Error, fmt, future::Future, net::SocketAddr}; @@ -74,7 +76,7 @@ struct PreLaunchNodeConfigSelected { /// Configuration for handling TLS pub tls_config: TlsSpec, /// All nodes addresses - pub pre_launch_nodes: Vec, + pub pre_launch_nodes: Vec, /// Db spec pub db_spec: SimpleDbSpec, /// Raft db spec @@ -84,13 +86,14 @@ struct PreLaunchNodeConfigSelected { } impl PreLaunchNodeConfigSelected { - fn new(config: PreLaunchNodeConfig) -> Self { + async fn new(config: PreLaunchNodeConfig) -> Self { match config.node_type { PreLaunchNodeType::Compute => Self { pre_launch_node_idx: config.compute_node_idx, pre_launch_db_mode: config.compute_db_mode, tls_config: config.tls_config, - pre_launch_nodes: config.compute_nodes, + pre_launch_nodes: create_socket_addr_for_list(&config.compute_nodes) + .await.unwrap_or_default(), db_spec: crate::compute::DB_SPEC, raft_db_spec: crate::compute_raft::DB_SPEC, peer_limit: config.peer_limit, @@ -99,7 +102,8 @@ impl PreLaunchNodeConfigSelected { pre_launch_node_idx: config.storage_node_idx, pre_launch_db_mode: config.storage_db_mode, tls_config: config.tls_config, - pre_launch_nodes: config.storage_nodes, + pre_launch_nodes: create_socket_addr_for_list(&config.storage_nodes) + .await.unwrap_or_default(), db_spec: crate::storage::DB_SPEC, raft_db_spec: crate::storage_raft::DB_SPEC, peer_limit: config.peer_limit, @@ -131,13 +135,13 @@ impl PreLaunchNode { config: PreLaunchNodeConfig, mut extra: ExtraNodeParams, ) -> Result { - let config = PreLaunchNodeConfigSelected::new(config); + let config = PreLaunchNodeConfigSelected::new(config).await; let addr = config .pre_launch_nodes .get(config.pre_launch_node_idx) - .ok_or(PreLaunchError::ConfigError("Invalid pre-launch index"))? - .address; - let tcp_tls_config = TcpTlsConfig::from_tls_spec(addr, &config.tls_config)?; + .ok_or(PreLaunchError::ConfigError("Invalid pre-launch index"))?; + + let tcp_tls_config = TcpTlsConfig::from_tls_spec(addr.clone(), &config.tls_config)?; let node = Node::new( &tcp_tls_config, @@ -155,9 +159,16 @@ impl PreLaunchNode { db_utils::new_db(config.pre_launch_db_mode, spec, extra.raft_db.take(), None) }; - let pre_launch_nodes = config.pre_launch_nodes.iter().map(|s| s.address); - let shutdown_group: BTreeSet = pre_launch_nodes.clone().collect(); - let pre_launch_nodes: Vec<_> = pre_launch_nodes.filter(|a| *a != addr).collect(); + let pre_launch_nodes = config.pre_launch_nodes.iter().map(|s| s); + let shutdown_group: BTreeSet = pre_launch_nodes + .clone() + .into_iter() + .map(|v| v.clone()) + .collect(); + let pre_launch_nodes: Vec<_> = pre_launch_nodes + .filter(|a| *a != addr) + .map(|v| v.clone()) + .collect(); let raft_db_send = if config.pre_launch_node_idx == 0 { Some(PreLaunchRequest::SendDbItems { diff --git a/src/storage.rs b/src/storage.rs index d8fb82ed..4a600743 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -14,8 +14,9 @@ use crate::raft::RaftCommit; use crate::storage_fetch::{FetchStatus, FetchedBlockChain, StorageFetch}; use crate::storage_raft::{CommittedItem, CompleteBlock, StorageRaft}; use crate::utils::{ - construct_valid_block_pow_hash, get_genesis_tx_in_display, to_api_keys, to_route_pow_infos, - ApiKeys, LocalEvent, LocalEventChannel, LocalEventSender, ResponseResult, RoutesPoWInfo, + construct_valid_block_pow_hash, create_socket_addr, get_genesis_tx_in_display, to_api_keys, + to_route_pow_infos, ApiKeys, LocalEvent, LocalEventChannel, LocalEventSender, ResponseResult, + RoutesPoWInfo, }; use bincode::{deserialize, serialize}; use bytes::Bytes; @@ -151,17 +152,25 @@ impl StorageNode { /// * `config` - StorageNodeConfig object containing the parameters for the new StorageNode /// * `extra` - additional parameter for construction pub async fn new(config: StorageNodeConfig, mut extra: ExtraNodeParams) -> Result { - let addr = config + let raw_addr = config .storage_nodes .get(config.storage_node_idx) - .ok_or(StorageError::ConfigError("Invalid storage index"))? - .address; + .ok_or(StorageError::ConfigError("Invalid storage index"))?; + let addr = create_socket_addr(&raw_addr.address).await.or_else(|_| { + Err(StorageError::ConfigError( + "Invalid storage address supplied", + )) + })?; - let compute_addr = config + let raw_compute_addr = config .compute_nodes .get(config.storage_node_idx) - .ok_or(StorageError::ConfigError("Invalid compute index"))? - .address; + .ok_or(StorageError::ConfigError("Invalid compute index"))?; + let compute_addr = create_socket_addr(&raw_compute_addr.address).await.or_else(|_| { + Err(StorageError::ConfigError( + "Invalid compute address supplied", + )) + })?; let tcp_tls_config = TcpTlsConfig::from_tls_spec(addr, &config.tls_config)?; let api_addr = SocketAddr::new(addr.ip(), config.storage_api_port); @@ -171,8 +180,8 @@ impl StorageNode { let api_keys = to_api_keys(config.api_keys.clone()); let node = Node::new(&tcp_tls_config, config.peer_limit, NodeType::Storage, false).await?; - let node_raft = StorageRaft::new(&config, extra.raft_db.take()); - let catchup_fetch = StorageFetch::new(&config, addr); + let node_raft = StorageRaft::new(&config, extra.raft_db.take()).await; + let catchup_fetch = StorageFetch::new(&config, addr).await; let api_pow_info = to_route_pow_infos(config.routes_pow.clone()); if config.backup_restore.unwrap_or(false) { diff --git a/src/storage_fetch.rs b/src/storage_fetch.rs index e0262249..1004b873 100644 --- a/src/storage_fetch.rs +++ b/src/storage_fetch.rs @@ -1,6 +1,7 @@ use crate::configurations::StorageNodeConfig; use crate::interfaces::{BlockchainItem, BlockchainItemMeta}; use crate::storage::{indexed_block_hash_key, indexed_tx_hash_key}; +use crate::utils::create_socket_addr; use std::fmt; use std::net::SocketAddr; use std::ops::Range; @@ -138,12 +139,26 @@ pub struct StorageFetch { to_receive: Option, } + + impl StorageFetch { /// Initialize with database info - pub fn new(config: &StorageNodeConfig, addr: SocketAddr) -> Self { + pub async fn new(config: &StorageNodeConfig, addr: SocketAddr) -> Self { let timeout_duration = Duration::from_millis(config.storage_catchup_duration as u64); - let storage_nodes = config.storage_nodes.iter().map(|s| s.address); - let storage_nodes = storage_nodes.filter(|a| a != &addr).collect(); + let storage_nodes_filtered = config + .storage_nodes + .iter() + .filter(|v| v.address.clone() != addr.to_string()); + + let mut storage_nodes = Vec::new(); + + for node in storage_nodes_filtered { + let socket_addr = create_socket_addr(&node.address); + if let Ok(socket) = socket_addr.await { + storage_nodes.push(socket); + } + } + Self { timeout_duration, storage_nodes, diff --git a/src/storage_raft.rs b/src/storage_raft.rs index 61283d50..b0f142c4 100644 --- a/src/storage_raft.rs +++ b/src/storage_raft.rs @@ -5,7 +5,7 @@ use crate::db_utils::{self, SimpleDb, SimpleDbError, SimpleDbSpec}; use crate::interfaces::{BlockStoredInfo, CommonBlockInfo, MinedBlockExtraInfo}; use crate::raft::{RaftCommit, RaftCommitData, RaftData, RaftMessageWrapper}; use crate::raft_util::{RaftContextKey, RaftInFlightProposals}; -use crate::utils::BackupCheck; +use crate::utils::{create_socket_addr_for_list, BackupCheck}; use a_block_chain::crypto::sha3_256; use bincode::{deserialize, serialize}; use serde::{Deserialize, Serialize}; @@ -113,15 +113,20 @@ impl StorageRaft { /// /// * `config` - Configuration option for a storage node. /// * `raft_db` - Override raft db to use. - pub fn new(config: &StorageNodeConfig, raft_db: Option) -> Self { + pub async fn new(config: &StorageNodeConfig, raft_db: Option) -> Self { let use_raft = config.storage_raft != 0; if config.backup_restore.unwrap_or(false) { db_utils::restore_file_backup(config.storage_db_mode, &DB_SPEC, None).unwrap(); } + let storage_node_urls = config + .storage_nodes + .iter() + .map(|s| s.address.clone()) + .collect::>(); let raft_active = ActiveRaft::new( config.storage_node_idx, - &config.storage_nodes, + &create_socket_addr_for_list(&storage_node_urls).await.unwrap_or_default(), use_raft, Duration::from_millis(config.storage_raft_tick_timeout as u64), db_utils::new_db(config.storage_db_mode, &DB_SPEC, raft_db, None), diff --git a/src/test_utils.rs b/src/test_utils.rs index d882c4bd..204aec0f 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -104,7 +104,7 @@ pub struct NetworkConfig { /// Node info to create node #[derive(Clone)] pub struct NetworkNodeInfo { - pub node_spec: NodeSpec, + pub node_spec: SocketAddr, pub node_type: NodeType, pub db_mode: DbMode, pub index: usize, @@ -114,10 +114,10 @@ pub struct NetworkNodeInfo { pub struct NetworkInstanceInfo { pub node_infos: BTreeMap, pub socket_name_mapping: BTreeMap, - pub miner_nodes: Vec, - pub compute_nodes: Vec, - pub storage_nodes: Vec, - pub user_nodes: Vec, + pub miner_nodes: Vec, + pub compute_nodes: Vec, + pub storage_nodes: Vec, + pub user_nodes: Vec, } #[derive(Clone, Default)] @@ -360,7 +360,7 @@ impl Network { let dead_addr: BTreeSet<_> = self .dead_nodes .iter() - .map(|n| self.instance_info.node_infos[n].node_spec.address) + .map(|n| self.instance_info.node_infos[n].node_spec) .collect(); connect_all_nodes(&self.arc_nodes, &dead_addr).await; } @@ -770,7 +770,7 @@ pub fn init_instance_info(config: &NetworkConfig) -> NetworkInstanceInfo { .collect(); let socket_name_mapping: BTreeMap<_, _> = node_infos .iter() - .map(|(name, info)| (info.node_spec.address, get_test_tls_name(name, tls_config))) + .map(|(name, info)| (info.node_spec, get_test_tls_name(name, tls_config))) .collect(); let mut nodes: BTreeMap<_, _> = nodes.into_iter().map(|(k, (_, v))| (k, v)).collect(); @@ -787,7 +787,7 @@ pub fn init_instance_info(config: &NetworkConfig) -> NetworkInstanceInfo { ///Return the infos necessary to initialize the node. fn node_infos( node_type: NodeType, - (node_names, node_specs): &(&Vec, Vec), + (node_names, node_specs): &(&Vec, Vec), in_memory_db: bool, ) -> BTreeMap { node_names @@ -803,7 +803,7 @@ fn node_infos( db_mode: if in_memory_db { DbMode::InMemory } else { - DbMode::Test(node_spec.address.port() as usize) + DbMode::Test(node_spec.port() as usize) }, index, }, @@ -813,13 +813,11 @@ fn node_infos( } ///Returns a u16, of the initial_port and node length, and a Vec of node specs -fn node_specs(ip: IpAddr, initial_port: u16, node_len: usize) -> (u16, Vec) { +fn node_specs(ip: IpAddr, initial_port: u16, node_len: usize) -> (u16, Vec) { ( initial_port + node_len as u16, (0..node_len) - .map(|idx| NodeSpec { - address: SocketAddr::new(ip, initial_port + idx as u16), - }) + .map(|idx| SocketAddr::new(ip, initial_port + idx as u16)) .collect(), ) } @@ -1037,12 +1035,19 @@ async fn init_miner( // Create node let node_info = &info.node_infos[name]; let config = MinerNodeConfig { - miner_address: node_info.node_spec.address, + miner_address: node_info.node_spec.to_string(), miner_db_mode: node_info.db_mode, tls_config: config.tls_config.make_tls_spec(&info.socket_name_mapping), api_keys: Default::default(), miner_compute_node_idx, - compute_nodes: info.compute_nodes.clone(), + compute_nodes: info + .compute_nodes + .clone() + .into_iter() + .map(|v| NodeSpec { + address: v.to_string(), + }) + .collect(), passphrase: config.passphrase.clone(), miner_api_port: 3004, miner_api_use_tls: true, @@ -1053,7 +1058,7 @@ async fn init_miner( mining_api_key: config.mining_api_key.clone(), peer_limit: config.peer_limit, }; - let info_str = format!("{} -> {}", name, node_info.node_spec.address); + let info_str = format!("{} -> {}", name, node_info.node_spec); info!("New Miner {}", info_str); Arc::new(Mutex::new( MinerNode::new(config, extra).await.expect(&info_str), @@ -1082,8 +1087,22 @@ async fn init_storage( storage_db_mode: node_info.db_mode, tls_config: config.tls_config.make_tls_spec(&info.socket_name_mapping), api_keys: Default::default(), - compute_nodes: info.compute_nodes.clone(), - storage_nodes: info.storage_nodes.clone(), + compute_nodes: info + .compute_nodes + .clone() + .into_iter() + .map(|v| NodeSpec { + address: v.to_string(), + }) + .collect(), + storage_nodes: info + .storage_nodes + .clone() + .into_iter() + .map(|v| NodeSpec { + address: v.to_string(), + }) + .collect(), storage_raft, storage_api_port: 3001, storage_api_use_tls: true, @@ -1094,7 +1113,7 @@ async fn init_storage( backup_restore: config.backup_restore, peer_limit: config.peer_limit, }; - let info = format!("{} -> {}", name, node_info.node_spec.address); + let info = format!("{} -> {}", name, node_info.node_spec); info!("New Storage {}", info); Arc::new(Mutex::new( StorageNode::new(config, extra).await.expect(&info), @@ -1117,6 +1136,17 @@ async fn init_compute( ) -> ArcComputeNode { let node_info = &info.node_infos[name]; let compute_raft = usize::from(config.compute_raft); + let mut user_nodes = None; + + if info.user_nodes.len() > 0 { + user_nodes = Some( + info.user_nodes.clone().into_iter() + .map(|v| NodeSpec { + address: v.to_string(), + }) + .collect::>(), + ); + } let config = ComputeNodeConfig { compute_db_mode: node_info.db_mode, @@ -1124,9 +1154,23 @@ async fn init_compute( tls_config: config.tls_config.make_tls_spec(&info.socket_name_mapping), api_keys: Default::default(), compute_unicorn_fixed_param: get_test_common_unicorn(), - compute_nodes: info.compute_nodes.clone(), - storage_nodes: info.storage_nodes.clone(), - user_nodes: info.user_nodes.clone(), + compute_nodes: info + .compute_nodes + .clone() + .into_iter() + .map(|v| NodeSpec { + address: v.to_string(), + }) + .collect::>(), + storage_nodes: info + .storage_nodes + .clone() + .into_iter() + .map(|v| NodeSpec { + address: v.to_string(), + }) + .collect::>(), + user_nodes, compute_raft, compute_raft_tick_timeout: 200 / config.test_duration_divider, compute_mining_event_timeout: 500 / config.test_duration_divider, @@ -1147,7 +1191,7 @@ async fn init_compute( compute_miner_whitelist: config.compute_miner_whitelist.clone(), peer_limit: config.peer_limit, }; - let info = format!("{} -> {}", name, node_info.node_spec.address); + let info = format!("{} -> {}", name, node_info.node_spec); info!("New Compute {}", info); Arc::new(Mutex::new( ComputeNode::new(config, extra).await.expect(&info), @@ -1179,12 +1223,19 @@ async fn init_user( }; let config = UserNodeConfig { - user_address: node_info.node_spec.address, + user_address: node_info.node_spec.to_string(), user_db_mode: node_info.db_mode, tls_config: config.tls_config.make_tls_spec(&info.socket_name_mapping), api_keys: Default::default(), user_compute_node_idx: 0, - compute_nodes: info.compute_nodes.clone(), + compute_nodes: info + .compute_nodes + .clone() + .into_iter() + .map(|v| NodeSpec { + address: v.to_string(), + }) + .collect(), user_api_port: 3000, user_api_use_tls: true, user_wallet_seeds, @@ -1196,7 +1247,7 @@ async fn init_user( peer_limit: config.peer_limit, }; - let info = format!("{} -> {}", name, node_info.node_spec.address); + let info = format!("{} -> {}", name, node_info.node_spec); info!("New User {}", info); Arc::new(Mutex::new(UserNode::new(config, extra).await.expect(&info))) } @@ -1229,12 +1280,22 @@ async fn init_pre_launch( tls_config: config.tls_config.make_tls_spec(&info.socket_name_mapping), storage_node_idx: node_info.index, storage_db_mode: node_info.db_mode, - compute_nodes: info.compute_nodes.clone(), - storage_nodes: info.storage_nodes.clone(), + compute_nodes: info + .compute_nodes + .clone() + .into_iter() + .map(|v| v.to_string()) + .collect(), + storage_nodes: info + .storage_nodes + .clone() + .into_iter() + .map(|v| v.to_string()) + .collect(), peer_limit: config.peer_limit, }; - let info = format!("{} -> {}", name, node_info.node_spec.address); + let info = format!("{} -> {}", name, node_info.node_spec); info!("New PreLaunch {}", info); Arc::new(Mutex::new( PreLaunchNode::new(config, extra).await.expect(&info), @@ -1250,7 +1311,7 @@ pub fn remove_all_node_dbs(config: &NetworkConfig) { /// Remove all db for the given instance info pub fn remove_all_node_dbs_in_info(info: &NetworkInstanceInfo) { for node in info.node_infos.values() { - let port = node.node_spec.address.port(); + let port = node.node_spec.port(); use NodeType::*; let db_paths = match node.node_type { Miner | User => { diff --git a/src/user.rs b/src/user.rs index 756300b6..6f4a5d3a 100644 --- a/src/user.rs +++ b/src/user.rs @@ -8,9 +8,9 @@ use crate::threaded_call::{ThreadedCallChannel, ThreadedCallSender}; use crate::transaction_gen::{PendingMap, TransactionGen}; use crate::transactor::Transactor; use crate::utils::{ - generate_half_druid, get_paiments_for_wallet_from_utxo, to_api_keys, to_route_pow_infos, - try_send_to_ui, ApiKeys, LocalEvent, LocalEventChannel, LocalEventSender, ResponseResult, - RoutesPoWInfo, + create_socket_addr, generate_half_druid, get_paiments_for_wallet_from_utxo, to_api_keys, + to_route_pow_infos, try_send_to_ui, ApiKeys, LocalEvent, LocalEventChannel, LocalEventSender, + ResponseResult, RoutesPoWInfo, }; use crate::wallet::{AddressStore, WalletDb, WalletDbError}; use crate::Rs2JsMsg; @@ -148,13 +148,16 @@ impl UserNode { /// * `extra` - additional parameter for construction pub async fn new(config: UserNodeConfig, mut extra: ExtraNodeParams) -> Result { let addr = config.user_address; - let compute_addr = config + let raw_compute_addr = config .compute_nodes .get(config.user_compute_node_idx) - .ok_or(UserError::ConfigError("Invalid compute index"))? - .address; - let tcp_tls_config = TcpTlsConfig::from_tls_spec(addr, &config.tls_config)?; - let api_addr = SocketAddr::new(addr.ip(), config.user_api_port); + .ok_or(UserError::ConfigError("Invalid compute index"))?; + let compute_addr = create_socket_addr(&raw_compute_addr.address) + .await.or_else(|_| Err(UserError::ConfigError("Invalid compute address")))?; + + let tls_addr = create_socket_addr(&addr).await.unwrap(); + let tcp_tls_config = TcpTlsConfig::from_tls_spec(tls_addr, &config.tls_config)?; + let api_addr = SocketAddr::new(tls_addr.ip(), config.user_api_port); let api_tls_info = config .user_api_use_tls .then(|| tcp_tls_config.clone_private_info()); diff --git a/src/utils.rs b/src/utils.rs index e65c8a29..fe57cca5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -32,13 +32,17 @@ use std::fmt; use std::fs::File; use std::future::Future; use std::io::Read; -use std::net::SocketAddr; +use std::net::{IpAddr, SocketAddr}; use std::sync::{Arc, Mutex}; use std::time::Duration; +use tokio::runtime::Runtime; use tokio::sync::{mpsc, oneshot}; use tokio::task; use tokio::time::Instant; use tracing::{trace, warn}; +use trust_dns_resolver::config::*; +use trust_dns_resolver::TokioAsyncResolver; +use url::Url; pub type RoutesPoWInfo = Arc>>; pub type ApiKeys = Arc>>>; @@ -462,6 +466,82 @@ pub fn generate_random_num(len: usize) -> Vec { (0..len).map(|_| rng.gen_range(1, 200)).collect() } +/// Parses a URL string and performs DNS resolution for cases where the passed URL is a domain name +/// +/// ### Arguments +/// +/// * `url_str` - URL string to parse +pub async fn create_socket_addr(url_str: &str) -> Result> { + let thread_url = url_str.to_owned(); + let handle = tokio::task::spawn_blocking(move || { + if let Ok(url) = Url::parse(&thread_url.clone()) { + // println!("url: {:?}", url); + let host_str = match url.host_str() { + Some(v) => v, + None => return None, + }; + // println!("host_str: {:?}", host_str); + let port = url.port().unwrap_or(80); + + // Check if the host is an IP address + if let Ok(ip) = host_str.parse::() { + // Handle as direct IP address + Some(SocketAddr::new(ip, port)) + } else { + let io_loop = Runtime::new().unwrap(); + + // Handle as domain name + let resolver = io_loop.block_on(async { + TokioAsyncResolver::tokio(ResolverConfig::default(), ResolverOpts::default()) + }); + + let lookup_future = resolver.lookup_ip(host_str); + let response = io_loop.block_on(lookup_future).unwrap(); + let ip = match response.iter().next() { + Some(ip) => ip, + None => return None, + }; + Some(SocketAddr::new(ip, port)) + } + } else { + // Handle as direct IP address with optional port + let parts: Vec<&str> = thread_url.split(':').collect(); + let ip = match parts[0].parse::() { + Ok(ip) => ip, + Err(_e) => return None, + }; + let port = if parts.len() > 1 { + match parts[1].parse::() { + Ok(port) => port, + Err(_e) => return None, + } + } else { + 80 + }; + Some(SocketAddr::new(ip, port)) + } + }); + + match handle.await { + Ok(v) => match v { + Some(v) => Ok(v), + None => Err("Failed to parse URL".into()), + }, + Err(_e) => Err("Failed to parse URL".into()), + } +} + +pub async fn create_socket_addr_for_list( + urls: &[String], +) -> Result, Box> { + let mut result = Vec::new(); + for url in urls { + let socket_addr = create_socket_addr(url).await?; + result.push(socket_addr); + } + Ok(result) +} + /// Generates a ProofOfWork for a given address /// /// ### Arguments @@ -1178,3 +1258,44 @@ pub mod rug_integer { Integer::from_str_radix(&value, 16).map_err(serde::de::Error::custom) } } + +/*---- TESTS ----*/ + +#[cfg(test)] +mod util_tests { + use super::*; + use std::net::Ipv4Addr; + + #[tokio::test] + /// Tests whether URL strings can be parsed successfully + async fn test_create_socket_addr() { + let ip_raw = "0.0.0.0".to_string(); + let ip_with_port = "0.0.0.0:12300".to_string(); + let domain = "http://localhost".to_string(); + let domain_with_port = "http://localhost:12300".to_string(); + + let ip_addr = create_socket_addr(&ip_raw).await.unwrap(); + let ip_with_port_addr = create_socket_addr(&ip_with_port).await.unwrap(); + let domain_addr = create_socket_addr(&domain).await.unwrap(); + let domain_with_port_addr = create_socket_addr(&domain_with_port).await.unwrap(); + + assert_eq!( + ip_addr, + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 80) + ); + assert_eq!( + ip_with_port_addr, + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 12300) + ); + + assert_eq!( + domain_addr, + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 80) + ); + + assert_eq!( + domain_with_port_addr, + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 12300) + ); + } +}