diff --git a/Cargo.lock b/Cargo.lock index 95073fef4a..b070acd396 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1954,6 +1954,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-logger 0.12.0", "solana-metrics 0.12.0", "solana-sdk 0.12.0", "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/drone/Cargo.toml b/drone/Cargo.toml index dfa0c67aae..e1663cefaf 100644 --- a/drone/Cargo.toml +++ b/drone/Cargo.toml @@ -19,6 +19,7 @@ clap = "2.31" log = "0.4.2" serde = "1.0.84" serde_derive = "1.0.84" +solana-logger = { path = "../logger", version = "0.12.0" } solana-sdk = { path = "../sdk", version = "0.12.0" } solana-metrics = { path = "../metrics", version = "0.12.0" } tokio = "0.1" @@ -31,4 +32,3 @@ crate-type = ["lib"] [[bin]] name = "solana-drone" path = "src/bin/drone.rs" - diff --git a/drone/src/bin/drone.rs b/drone/src/bin/drone.rs index 386f16cb22..b514835f1d 100644 --- a/drone/src/bin/drone.rs +++ b/drone/src/bin/drone.rs @@ -1,7 +1,6 @@ -use byteorder::{ByteOrder, LittleEndian}; -use bytes::Bytes; use clap::{crate_version, App, Arg}; -use solana_drone::drone::{Drone, DroneRequest, DRONE_PORT}; +use log::*; +use solana_drone::drone::{Drone, DRONE_PORT}; use solana_drone::socketaddr; use solana_sdk::signature::read_keypair; use std::error; @@ -14,6 +13,7 @@ use tokio::prelude::*; use tokio_codec::{BytesCodec, Decoder}; fn main() -> Result<(), Box> { + solana_logger::setup(); solana_metrics::set_panic_hook("drone"); let matches = App::new("drone") .version(crate_version!()) @@ -74,7 +74,7 @@ fn main() -> Result<(), Box> { }); let socket = TcpListener::bind(&drone_addr).unwrap(); - println!("Drone started. Listening on: {}", drone_addr); + info!("Drone started. Listening on: {}", drone_addr); let done = socket .incoming() .map_err(|e| println!("failed to accept socket; error = {:?}", e)) @@ -84,40 +84,12 @@ fn main() -> Result<(), Box> { let (writer, reader) = framed.split(); let processor = reader.and_then(move |bytes| { - let req: DroneRequest = bincode::deserialize(&bytes).or_else(|err| { - Err(io::Error::new( - io::ErrorKind::Other, - format!("deserialize packet in drone: {:?}", err), - )) - })?; - - println!("Airdrop transaction requested...{:?}", req); - let res = drone2.lock().unwrap().build_airdrop_transaction(req); - match res { - Ok(tx) => { - let response_vec = bincode::serialize(&tx).or_else(|err| { - Err(io::Error::new( - io::ErrorKind::Other, - format!("deserialize packet in drone: {:?}", err), - )) - })?; - - let mut response_vec_with_length = vec![0; 2]; - LittleEndian::write_u16( - &mut response_vec_with_length, - response_vec.len() as u16, - ); - response_vec_with_length.extend_from_slice(&response_vec); - - let response_bytes = Bytes::from(response_vec_with_length); - println!("Airdrop transaction granted"); - Ok(response_bytes) - } - Err(err) => { - println!("Airdrop transaction failed: {:?}", err); - Err(err) - } - } + let response_bytes = drone2 + .lock() + .unwrap() + .process_drone_request(&bytes) + .unwrap(); + Ok(response_bytes) }); let server = writer .send_all(processor.or_else(|err| { diff --git a/drone/src/drone.rs b/drone/src/drone.rs index 93ab7a70ce..7948da1f53 100644 --- a/drone/src/drone.rs +++ b/drone/src/drone.rs @@ -6,7 +6,7 @@ use bincode::{deserialize, serialize}; use byteorder::{ByteOrder, LittleEndian}; -use bytes::Bytes; +use bytes::{Bytes, BytesMut}; use log::*; use serde_derive::{Deserialize, Serialize}; use solana_metrics; @@ -130,7 +130,7 @@ impl Drone { let create_instruction = SystemInstruction::CreateAccount { tokens, space: 0, - program_id: Pubkey::default(), + program_id: system_program::id(), }; let mut transaction = Transaction::new( &self.mint_keypair, @@ -149,6 +149,39 @@ impl Drone { } } } + pub fn process_drone_request(&mut self, bytes: &BytesMut) -> Result { + let req: DroneRequest = deserialize(bytes).or_else(|err| { + Err(io::Error::new( + io::ErrorKind::Other, + format!("deserialize packet in drone: {:?}", err), + )) + })?; + + info!("Airdrop transaction requested...{:?}", req); + let res = self.build_airdrop_transaction(req); + match res { + Ok(tx) => { + let response_vec = bincode::serialize(&tx).or_else(|err| { + Err(io::Error::new( + io::ErrorKind::Other, + format!("deserialize packet in drone: {:?}", err), + )) + })?; + + let mut response_vec_with_length = vec![0; 2]; + LittleEndian::write_u16(&mut response_vec_with_length, response_vec.len() as u16); + response_vec_with_length.extend_from_slice(&response_vec); + + let response_bytes = Bytes::from(response_vec_with_length); + info!("Airdrop transaction granted"); + Ok(response_bytes) + } + Err(err) => { + warn!("Airdrop transaction failed: {:?}", err); + Err(err) + } + } + } } impl Drop for Drone { @@ -235,42 +268,12 @@ pub fn run_local_drone(mint_keypair: Keypair, sender: Sender) { let (writer, reader) = framed.split(); let processor = reader.and_then(move |bytes| { - let req: DroneRequest = deserialize(&bytes).or_else(|err| { - Err(io::Error::new( - io::ErrorKind::Other, - format!("deserialize packet in drone: {:?}", err), - )) - })?; - - info!("Airdrop requested..."); - let res = drone2.lock().unwrap().build_airdrop_transaction(req); - match res { - Ok(_) => info!("Airdrop sent!"), - Err(_) => info!("Request limit reached for this time slice"), - } - let response = res?; - - info!("Airdrop tx signature: {:?}", response); - let response_vec = serialize(&response).or_else(|err| { - Err(io::Error::new( - io::ErrorKind::Other, - format!("serialize signature in drone: {:?}", err), - )) - })?; - - let mut response_vec_with_length = vec![0; 2]; - LittleEndian::write_u16( - &mut response_vec_with_length, - response_vec.len() as u16, - ); - info!( - "Airdrop response_vec_with_length: {:?}", - response_vec_with_length - ); - response_vec_with_length.extend_from_slice(&response_vec); - - let response_bytes = Bytes::from(response_vec_with_length.clone()); - info!("Airdrop response_bytes: {:?}", response_bytes); + let response_bytes = drone2 + .lock() + .unwrap() + .process_drone_request(&bytes) + .unwrap(); + info!("Airdrop response_bytes: {:?}", response_bytes.to_vec()); Ok(response_bytes) }); let server = writer @@ -290,6 +293,7 @@ pub fn run_local_drone(mint_keypair: Keypair, sender: Sender) { #[cfg(test)] mod tests { use super::*; + use bytes::BufMut; use solana_sdk::signature::{Keypair, KeypairUtil}; use std::time::Duration; @@ -383,4 +387,50 @@ mod tests { let tx = drone.build_airdrop_transaction(request); assert!(tx.is_err()); } + + #[test] + fn test_process_drone_request() { + let to = Keypair::new().pubkey(); + let last_id = Hash::new(&to.as_ref()); + let tokens = 50; + let req = DroneRequest::GetAirdrop { + tokens, + last_id, + to, + }; + let req = serialize(&req).unwrap(); + let mut bytes = BytesMut::with_capacity(req.len()); + bytes.put(&req[..]); + + let keypair = Keypair::new(); + let expected_instruction = SystemInstruction::CreateAccount { + tokens, + space: 0, + program_id: system_program::id(), + }; + let mut expected_tx = Transaction::new( + &keypair, + &[to], + system_program::id(), + &expected_instruction, + last_id, + 0, + ); + expected_tx.sign(&[&keypair], last_id); + let expected_bytes = serialize(&expected_tx).unwrap(); + let mut expected_vec_with_length = vec![0; 2]; + LittleEndian::write_u16(&mut expected_vec_with_length, expected_bytes.len() as u16); + expected_vec_with_length.extend_from_slice(&expected_bytes); + + let mut drone = Drone::new(keypair, None, None); + let response = drone.process_drone_request(&bytes); + assert!(response.is_ok()); + + let response_vec = response.unwrap().to_vec(); + assert_eq!(expected_vec_with_length, response_vec); + + let mut bad_bytes = BytesMut::with_capacity(9); + bad_bytes.put("bad bytes"); + assert!(drone.process_drone_request(&bad_bytes).is_err()); + } }