diff --git a/src/bin/replicator.rs b/src/bin/replicator.rs index f78653cd7..d4aa537bb 100644 --- a/src/bin/replicator.rs +++ b/src/bin/replicator.rs @@ -8,11 +8,16 @@ extern crate solana; use clap::{App, Arg}; use solana::chacha::chacha_cbc_encrypt_files; use solana::cluster_info::Node; +use solana::client::mk_client; +use solana::drone::DRONE_PORT; use solana::fullnode::Config; use solana::ledger::LEDGER_DATA_FILE; use solana::logger; use solana::replicator::{sample_file, Replicator}; use solana::signature::{Keypair, KeypairUtil}; +use solana::storage_transaction::StorageTransaction; +use solana::transaction::Transaction; +use solana::wallet::request_airdrop; use std::fs::File; use std::net::{Ipv4Addr, SocketAddr}; use std::path::Path; @@ -90,7 +95,7 @@ fn main() { // TODO: ask network what slice we should store let entry_height = 0; - let replicator = Replicator::new( + let (replicator, leader_info) = Replicator::new( entry_height, 5, &exit, @@ -124,8 +129,22 @@ fn main() { let sampling_offsets = [0, 1, 2, 3]; + let mut client = mk_client(&leader_info); + + let mut drone_addr = leader_info.contact_info.tpu; + drone_addr.set_port(DRONE_PORT); + let airdrop_amount = 5; + if let Err(e) = request_airdrop(&drone_addr, &keypair.pubkey(), airdrop_amount) { + panic!("couldn't get airdrop {}: {}!", airdrop_amount, e); + } + match sample_file(&ledger_data_file_encrypted, &sampling_offsets) { - Ok(hash) => println!("sampled hash: {}", hash), + Ok(hash) => { + let last_id = client.get_last_id(); + println!("sampled hash: {}", hash); + let tx = Transaction::storage_new_mining_proof(&keypair, hash, last_id); + client.transfer_signed(&tx).expect("transfer didn't work!"); + } Err(e) => println!("Error occurred while sampling: {:?}", e), } diff --git a/src/lib.rs b/src/lib.rs index 7bbe93943..5ed4498e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,6 +61,7 @@ pub mod signature; pub mod sigverify; pub mod sigverify_stage; pub mod storage_program; +pub mod storage_transaction; pub mod store_ledger_stage; pub mod streamer; pub mod system_program; diff --git a/src/replicator.rs b/src/replicator.rs index 2c76b0b2b..e9bc33c19 100644 --- a/src/replicator.rs +++ b/src/replicator.rs @@ -22,6 +22,7 @@ use std::thread::JoinHandle; use std::time::Duration; use store_ledger_stage::StoreLedgerStage; use streamer::BlobReceiver; +use thin_client::poll_gossip_for_leader; use window; use window_service::window_service; @@ -49,7 +50,7 @@ pub fn sample_file(in_path: &Path, sample_offsets: &[u64]) -> io::Result { return Err(Error::new(ErrorKind::Other, "offset too large")); } buffer_file.seek(SeekFrom::Start(*offset * sample_size64))?; - info!("sampling @ {} ", *offset); + trace!("sampling @ {} ", *offset); match buffer_file.read(&mut buf) { Ok(size) => { assert_eq!(size, buf.len()); @@ -74,7 +75,7 @@ impl Replicator { node: Node, network_addr: Option, done: Arc, - ) -> Replicator { + ) -> (Replicator, NodeInfo) { let window = window::new_window_from_entries(&[], entry_height, &node.info); let shared_window = Arc::new(RwLock::new(window)); @@ -126,13 +127,19 @@ impl Replicator { exit.clone(), ); - Replicator { - ncp, - fetch_stage, - store_ledger_stage, - t_window, - retransmit_receiver, - } + let leader = + poll_gossip_for_leader(network_addr.unwrap(), Some(10)).expect("couldn't reach leader"); + + ( + Replicator { + ncp, + fetch_stage, + store_ledger_stage, + t_window, + retransmit_receiver, + }, + leader, + ) } pub fn join(self) { @@ -213,7 +220,7 @@ mod tests { info!("starting replicator node"); let replicator_node = Node::new_localhost_with_pubkey(replicator_keypair.pubkey()); - let replicator = Replicator::new( + let (replicator, _leader_info) = Replicator::new( entry_height, 1, &exit, diff --git a/src/storage_program.rs b/src/storage_program.rs index bd175c8cc..dc3565192 100644 --- a/src/storage_program.rs +++ b/src/storage_program.rs @@ -3,13 +3,14 @@ //! and give reward for good proofs. use bincode::deserialize; +use hash::Hash; use solana_program_interface::account::Account; use solana_program_interface::pubkey::Pubkey; use transaction::Transaction; #[derive(Serialize, Deserialize, Debug, Clone)] pub enum StorageProgram { - SubmitMiningProof { sha_state: [u8; 32] }, + SubmitMiningProof { sha_state: Hash }, } pub enum StorageError { @@ -39,7 +40,7 @@ impl StorageProgram { if let Ok(syscall) = deserialize(tx.userdata(pix)) { match syscall { StorageProgram::SubmitMiningProof { sha_state } => { - info!("Mining proof submitted with state {}", sha_state[0]); + info!("Mining proof submitted with state {:?}", sha_state); return Ok(()); } } diff --git a/src/storage_transaction.rs b/src/storage_transaction.rs new file mode 100644 index 000000000..19463154a --- /dev/null +++ b/src/storage_transaction.rs @@ -0,0 +1,24 @@ +use bincode::serialize; +use hash::Hash; +use signature::{Keypair, KeypairUtil}; +use storage_program::StorageProgram; +use transaction::Transaction; + +pub trait StorageTransaction { + fn storage_new_mining_proof(from_keypair: &Keypair, sha_state: Hash, last_id: Hash) -> Self; +} + +impl StorageTransaction for Transaction { + fn storage_new_mining_proof(from_keypair: &Keypair, sha_state: Hash, last_id: Hash) -> Self { + let program = StorageProgram::SubmitMiningProof { sha_state }; + let userdata = serialize(&program).unwrap(); + Transaction::new( + from_keypair, + &[from_keypair.pubkey()], + StorageProgram::id(), + userdata, + last_id, + 0, + ) + } +}