use blockchain::common::cli_prompts::prompt_hidden_nonempty; use blockchain::common::network_startup::get_connections; use blockchain::env; use blockchain::records::memory::response_channels::generate_uid; use blockchain::standalone_tools::connections::handshake; use blockchain::wallets::structures::Wallet; #[tokio::main] async fn main() { // Command 26 is currently handled by the server as the block-IP command. let rpc_command = 26; // The server owner supplies the IP to block; the wallet key signs the request. let args: Vec = env::args().collect(); if args.len() != 2 { println!("Usage: ./server_owner_block_ip "); return; } let ip = args[1].trim().to_string(); let wallet_key = prompt_hidden_nonempty( "What is your wallet decryption key? ", "Wallet key cannot be empty. Please try again.", ) .await; // Server-side verification expects a signature over the exact IP string. let wallet = match Wallet::try_obtain_wallet(wallet_key.clone(), None).await { Ok(wallet) => wallet, Err(err) => { eprintln!("Wallet decryption failed: {err}"); return; } }; let signature = Wallet::sign_transaction(&ip, &wallet.saved.private_key).await; let payload = format!("{ip}|{signature}"); let connections = get_connections().await; let mut connected = false; for conn in connections { if connected { break; } let socket_address = conn.parse().expect("Failed to parse the socket address"); let result = handshake::connect_and_handshake( socket_address, payload.clone(), rpc_command, handshake::HandshakeWallet::WalletKey(wallet_key.clone()), generate_uid(), ) .await; match result { Ok(response) => { let response_text = String::from_utf8_lossy(&response); let trimmed = response_text.trim(); if !trimmed.is_empty() { println!("{trimmed}"); connected = true; } } Err(_) => connected = false, } } if !connected { eprintln!("failed to connect"); } }