2018-08-06 20:51:12 -07:00
|
|
|
#[macro_use]
|
2018-07-09 18:04:49 -07:00
|
|
|
extern crate clap;
|
2018-04-09 11:28:54 -07:00
|
|
|
extern crate getopts;
|
2018-08-31 00:10:39 -07:00
|
|
|
#[macro_use]
|
2018-06-18 15:49:41 -07:00
|
|
|
extern crate log;
|
2018-03-03 23:13:40 -08:00
|
|
|
extern crate serde_json;
|
2018-08-31 00:10:39 -07:00
|
|
|
#[macro_use]
|
2018-03-27 15:24:05 -07:00
|
|
|
extern crate solana;
|
2018-02-28 17:04:35 -08:00
|
|
|
|
2018-07-09 18:04:49 -07:00
|
|
|
use clap::{App, Arg};
|
2018-07-31 22:07:53 -07:00
|
|
|
use solana::client::mk_client;
|
2018-10-08 19:55:54 -07:00
|
|
|
use solana::cluster_info::Node;
|
2018-07-31 22:07:53 -07:00
|
|
|
use solana::drone::DRONE_PORT;
|
2018-09-14 01:53:18 -07:00
|
|
|
use solana::fullnode::{Config, Fullnode, FullnodeReturnType};
|
2018-10-10 16:49:41 -07:00
|
|
|
use solana::leader_scheduler::LeaderScheduler;
|
2018-07-27 21:37:53 -07:00
|
|
|
use solana::logger;
|
2018-07-17 10:48:46 -07:00
|
|
|
use solana::metrics::set_panic_hook;
|
2018-08-09 07:56:04 -07:00
|
|
|
use solana::signature::{Keypair, KeypairUtil};
|
2018-08-31 00:10:39 -07:00
|
|
|
use solana::thin_client::poll_gossip_for_leader;
|
2018-10-25 16:58:40 -07:00
|
|
|
use solana::vote_program::VoteProgram;
|
2018-07-31 22:07:53 -07:00
|
|
|
use solana::wallet::request_airdrop;
|
2018-05-23 13:03:19 -07:00
|
|
|
use std::fs::File;
|
2018-08-31 00:10:39 -07:00
|
|
|
use std::net::{Ipv4Addr, SocketAddr};
|
2018-04-19 07:06:19 -07:00
|
|
|
use std::process::exit;
|
2018-10-25 16:58:40 -07:00
|
|
|
use std::sync::Arc;
|
2018-08-31 00:10:39 -07:00
|
|
|
use std::thread::sleep;
|
2018-08-25 18:24:25 -07:00
|
|
|
use std::time::Duration;
|
2018-02-28 17:04:35 -08:00
|
|
|
|
2018-10-25 16:58:40 -07:00
|
|
|
fn main() {
|
2018-07-27 21:37:53 -07:00
|
|
|
logger::setup();
|
2018-07-17 11:00:01 -07:00
|
|
|
set_panic_hook("fullnode");
|
2018-07-09 18:04:49 -07:00
|
|
|
let matches = App::new("fullnode")
|
2018-08-06 20:51:12 -07:00
|
|
|
.version(crate_version!())
|
2018-07-09 18:04:49 -07:00
|
|
|
.arg(
|
|
|
|
Arg::with_name("identity")
|
2018-07-12 15:45:41 -07:00
|
|
|
.short("i")
|
|
|
|
.long("identity")
|
2018-09-14 15:32:57 -07:00
|
|
|
.value_name("PATH")
|
2018-07-09 18:04:49 -07:00
|
|
|
.takes_value(true)
|
2018-09-14 15:32:57 -07:00
|
|
|
.help("Run with the identity found in FILE"),
|
2018-09-14 16:25:14 -07:00
|
|
|
).arg(
|
2018-08-31 00:10:39 -07:00
|
|
|
Arg::with_name("network")
|
|
|
|
.short("n")
|
|
|
|
.long("network")
|
2018-07-09 18:04:49 -07:00
|
|
|
.value_name("HOST:PORT")
|
|
|
|
.takes_value(true)
|
2018-09-14 15:32:57 -07:00
|
|
|
.help("Rendezvous with the network at this gossip entry point"),
|
2018-09-14 16:25:14 -07:00
|
|
|
).arg(
|
2018-07-12 14:29:36 -07:00
|
|
|
Arg::with_name("ledger")
|
2018-08-03 11:06:06 -07:00
|
|
|
.short("l")
|
2018-07-12 14:29:36 -07:00
|
|
|
.long("ledger")
|
2018-08-03 11:06:06 -07:00
|
|
|
.value_name("DIR")
|
2018-07-09 18:04:49 -07:00
|
|
|
.takes_value(true)
|
2018-08-03 11:06:06 -07:00
|
|
|
.required(true)
|
|
|
|
.help("use DIR as persistent ledger location"),
|
2018-09-14 16:25:14 -07:00
|
|
|
).get_matches();
|
2018-04-21 06:12:57 -07:00
|
|
|
|
2018-08-31 00:10:39 -07:00
|
|
|
let (keypair, ncp) = if let Some(i) = matches.value_of("identity") {
|
2018-07-12 15:45:41 -07:00
|
|
|
let path = i.to_string();
|
2018-05-30 07:17:04 -07:00
|
|
|
if let Ok(file) = File::open(path.clone()) {
|
2018-07-05 12:01:40 -07:00
|
|
|
let parse: serde_json::Result<Config> = serde_json::from_reader(file);
|
|
|
|
if let Ok(data) = parse {
|
2018-08-31 00:10:39 -07:00
|
|
|
(data.keypair(), data.node_info.contact_info.ncp)
|
2018-05-30 07:17:04 -07:00
|
|
|
} else {
|
2018-06-16 09:35:30 -07:00
|
|
|
eprintln!("failed to parse {}", path);
|
|
|
|
exit(1);
|
2018-05-30 07:17:04 -07:00
|
|
|
}
|
2018-06-15 15:29:43 -07:00
|
|
|
} else {
|
2018-06-16 09:35:30 -07:00
|
|
|
eprintln!("failed to read {}", path);
|
|
|
|
exit(1);
|
2018-05-24 23:18:41 -07:00
|
|
|
}
|
2018-08-31 00:10:39 -07:00
|
|
|
} else {
|
|
|
|
(Keypair::new(), socketaddr!(0, 8000))
|
|
|
|
};
|
2018-07-31 22:07:53 -07:00
|
|
|
|
2018-08-03 11:06:06 -07:00
|
|
|
let ledger_path = matches.value_of("ledger").unwrap();
|
2018-07-12 14:29:36 -07:00
|
|
|
|
2018-08-31 00:10:39 -07:00
|
|
|
// socketaddr that is initial pointer into the network's gossip (ncp)
|
|
|
|
let network = matches
|
|
|
|
.value_of("network")
|
|
|
|
.map(|network| network.parse().expect("failed to parse network address"));
|
|
|
|
|
|
|
|
let node = Node::new_with_external_ip(keypair.pubkey(), &ncp);
|
|
|
|
|
|
|
|
// save off some stuff for airdrop
|
|
|
|
let node_info = node.info.clone();
|
|
|
|
|
|
|
|
let leader = match network {
|
|
|
|
Some(network) => {
|
|
|
|
poll_gossip_for_leader(network, None).expect("can't find leader on network")
|
|
|
|
}
|
|
|
|
None => node_info,
|
2018-08-25 10:24:16 -07:00
|
|
|
};
|
|
|
|
|
2018-10-25 16:58:40 -07:00
|
|
|
let vote_account_keypair = Arc::new(Keypair::new());
|
|
|
|
let vote_account_id = vote_account_keypair.pubkey();
|
|
|
|
let keypair = Arc::new(keypair);
|
|
|
|
let pubkey = keypair.pubkey();
|
|
|
|
|
2018-10-10 16:49:41 -07:00
|
|
|
let mut fullnode = Fullnode::new(
|
|
|
|
node,
|
|
|
|
ledger_path,
|
2018-10-25 16:58:40 -07:00
|
|
|
keypair.clone(),
|
|
|
|
vote_account_keypair,
|
2018-10-10 16:49:41 -07:00
|
|
|
network,
|
|
|
|
false,
|
|
|
|
LeaderScheduler::from_bootstrap_leader(leader.id),
|
|
|
|
);
|
2018-08-31 00:10:39 -07:00
|
|
|
let mut client = mk_client(&leader);
|
2018-07-31 22:07:53 -07:00
|
|
|
|
2018-08-31 00:10:39 -07:00
|
|
|
// TODO: maybe have the drone put itself in gossip somewhere instead of hardcoding?
|
|
|
|
let drone_addr = match network {
|
|
|
|
Some(network) => SocketAddr::new(network.ip(), DRONE_PORT),
|
|
|
|
None => SocketAddr::new(ncp.ip(), DRONE_PORT),
|
|
|
|
};
|
2018-07-31 22:07:53 -07:00
|
|
|
|
2018-08-31 00:10:39 -07:00
|
|
|
loop {
|
|
|
|
let balance = client.poll_get_balance(&pubkey).unwrap_or(0);
|
|
|
|
info!("balance is {}", balance);
|
2018-07-31 22:07:53 -07:00
|
|
|
|
2018-08-31 00:10:39 -07:00
|
|
|
if balance >= 50 {
|
|
|
|
info!("good to go!");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
info!("requesting airdrop from {}", drone_addr);
|
|
|
|
loop {
|
|
|
|
if request_airdrop(&drone_addr, &pubkey, 50).is_ok() {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
info!(
|
|
|
|
"airdrop request, is the drone address correct {:?}, drone running?",
|
|
|
|
drone_addr
|
|
|
|
);
|
|
|
|
sleep(Duration::from_secs(2));
|
|
|
|
}
|
2018-07-31 22:07:53 -07:00
|
|
|
}
|
|
|
|
|
2018-10-25 16:58:40 -07:00
|
|
|
// Create the vote account
|
|
|
|
loop {
|
|
|
|
let last_id = client.get_last_id();
|
|
|
|
if client
|
|
|
|
.create_vote_account(&keypair, vote_account_id, &last_id, 1)
|
|
|
|
.is_err()
|
|
|
|
{
|
|
|
|
sleep(Duration::from_secs(2));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
let balance = client.poll_get_balance(&vote_account_id).unwrap_or(0);
|
|
|
|
|
|
|
|
if balance > 0 {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sleep(Duration::from_secs(2));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register the vote account to this node
|
|
|
|
loop {
|
|
|
|
let last_id = client.get_last_id();
|
|
|
|
if client
|
|
|
|
.register_vote_account(&keypair, vote_account_id, &last_id)
|
|
|
|
.is_err()
|
|
|
|
{
|
|
|
|
sleep(Duration::from_secs(2));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
let account_user_data = client.get_account_userdata(&vote_account_id);
|
|
|
|
if let Ok(Some(account_user_data)) = account_user_data {
|
|
|
|
if let Ok(vote_state) = VoteProgram::deserialize(&account_user_data) {
|
|
|
|
if vote_state.node_id == pubkey {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sleep(Duration::from_secs(2));
|
|
|
|
}
|
|
|
|
|
2018-09-14 00:17:40 -07:00
|
|
|
loop {
|
2018-09-14 01:53:18 -07:00
|
|
|
let status = fullnode.handle_role_transition();
|
|
|
|
match status {
|
2018-10-10 16:49:41 -07:00
|
|
|
Ok(Some(FullnodeReturnType::LeaderToValidatorRotation)) => (),
|
|
|
|
Ok(Some(FullnodeReturnType::ValidatorToLeaderRotation)) => (),
|
2018-09-14 01:53:18 -07:00
|
|
|
_ => {
|
|
|
|
// Fullnode tpu/tvu exited for some unexpected
|
|
|
|
// reason, so exit
|
|
|
|
exit(1);
|
2018-09-12 13:59:19 -07:00
|
|
|
}
|
|
|
|
}
|
2018-09-14 00:17:40 -07:00
|
|
|
}
|
2018-05-23 13:03:19 -07:00
|
|
|
}
|