Remove airdrop from fullnode

This commit is contained in:
Michael Vines 2018-11-15 17:05:31 -08:00
parent 1576072edb
commit a0dd8617be
6 changed files with 94 additions and 91 deletions

View File

@ -60,6 +60,7 @@ if ((!self_setup)); then
echo " ${here}/setup.sh"
exit 1
}
validator_id_path=$SOLANA_CONFIG_PRIVATE_DIR/validator-id.json
validator_json_path=$SOLANA_CONFIG_VALIDATOR_DIR/validator.json
SOLANA_LEADER_CONFIG_DIR=$SOLANA_CONFIG_VALIDATOR_DIR/leader-config
else
@ -78,6 +79,22 @@ else
SOLANA_LEADER_CONFIG_DIR=$SOLANA_CONFIG_VALIDATOR_DIR/leader-config-x$$
fi
[[ -r $validator_id_path ]] || {
echo "$validator_id_path does not exist"
exit 1
}
# A fullnode requires 2 tokens to function:
# - one token to create an instance of the vote_program with
# - one second token to keep the node identity public key valid.
(
set -x
$solana_wallet \
--keypair "$validator_id_path" \
--network "$leader_address" \
airdrop 2
)
rsync_leader_url=$(rsync_url "$leader")
tune_networking

View File

@ -1,10 +1,13 @@
#[macro_use]
extern crate clap;
extern crate dirs;
extern crate ring;
extern crate serde_json;
extern crate solana;
use clap::{App, Arg};
use ring::rand::SystemRandom;
use ring::signature::Ed25519KeyPair;
use solana::cluster_info::FULLNODE_PORT_RANGE;
use solana::fullnode::Config;
use solana::logger;
@ -67,9 +70,12 @@ fn main() {
};
let pkcs8 = read_pkcs8(id_path).expect("client keypair");
let rnd = SystemRandom::new();
let vote_account_pkcs8 = Ed25519KeyPair::generate_pkcs8(&rnd).unwrap();
// we need all the receiving sockets to be bound within the expected
// port range that we open on aws
let config = Config::new(&bind_addr, pkcs8);
let config = Config::new(&bind_addr, pkcs8, vote_account_pkcs8.to_vec());
let stdout = io::stdout();
serde_json::to_writer(stdout, &config).expect("serialize");
}

View File

@ -10,7 +10,6 @@ extern crate solana;
use clap::{App, Arg};
use solana::client::mk_client;
use solana::cluster_info::{Node, FULLNODE_PORT_RANGE};
use solana::drone::{request_airdrop_transaction, DRONE_PORT};
use solana::fullnode::{Config, Fullnode, FullnodeReturnType};
use solana::leader_scheduler::LeaderScheduler;
use solana::logger;
@ -19,6 +18,7 @@ use solana::netutil::find_available_port_in_range;
use solana::signature::{Keypair, KeypairUtil};
use solana::thin_client::poll_gossip_for_leader;
use solana::vote_program::VoteProgram;
use solana::vote_transaction::VoteTransaction;
use std::fs::File;
use std::net::{Ipv4Addr, SocketAddr};
use std::process::exit;
@ -61,12 +61,16 @@ fn main() {
.help("Custom RPC port for this node"),
).get_matches();
let (keypair, ncp) = if let Some(i) = matches.value_of("identity") {
let (keypair, vote_account_keypair, ncp) = if let Some(i) = matches.value_of("identity") {
let path = i.to_string();
if let Ok(file) = File::open(path.clone()) {
let parse: serde_json::Result<Config> = serde_json::from_reader(file);
if let Ok(data) = parse {
(data.keypair(), data.node_info.ncp)
(
data.keypair(),
data.vote_account_keypair(),
data.node_info.ncp,
)
} else {
eprintln!("failed to parse {}", path);
exit(1);
@ -76,7 +80,7 @@ fn main() {
exit(1);
}
} else {
(Keypair::new(), socketaddr!(0, 8000))
(Keypair::new(), Keypair::new(), socketaddr!(0, 8000))
};
let ledger_path = matches.value_of("ledger").unwrap();
@ -91,7 +95,7 @@ fn main() {
// save off some stuff for airdrop
let mut node_info = node.info.clone();
let vote_account_keypair = Arc::new(Keypair::new());
let vote_account_keypair = Arc::new(vote_account_keypair);
let vote_account_id = vote_account_keypair.pubkey();
let keypair = Arc::new(keypair);
let pubkey = keypair.pubkey();
@ -133,7 +137,7 @@ fn main() {
node,
ledger_path,
keypair.clone(),
vote_account_keypair,
vote_account_keypair.clone(),
network,
false,
leader_scheduler,
@ -141,66 +145,43 @@ fn main() {
);
let mut client = mk_client(&leader);
// 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),
};
loop {
let balance = client.poll_get_balance(&pubkey).unwrap_or(0);
info!("balance is {}", balance);
if balance >= 50 {
info!("good to go!");
break;
}
info!("requesting airdrop from {}", drone_addr);
loop {
let last_id = client.get_last_id();
if let Ok(transaction) = request_airdrop_transaction(&drone_addr, &pubkey, 50, last_id)
{
let signature = client.transfer_signed(&transaction).unwrap();
if client.poll_for_signature(&signature).is_ok() {
break;
}
}
info!(
"airdrop request, is the drone address correct {:?}, drone running?",
drone_addr
);
sleep(Duration::from_secs(2));
}
let balance = client.poll_get_balance(&pubkey).unwrap_or(0);
info!("balance is {}", balance);
if balance < 1 {
error!("insufficient tokens");
exit(1);
}
// 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()
{
// Create the vote account if necessary
if client.poll_get_balance(&vote_account_id).unwrap_or(0) == 0 {
// Need at least two tokens as one token will be spent on a vote_account_new() transaction
if balance < 2 {
error!("insufficient tokens");
exit(1);
}
loop {
let last_id = client.get_last_id();
let transaction =
VoteTransaction::vote_account_new(&keypair, vote_account_id, last_id, 1);
if client.transfer_signed(&transaction).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));
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()
{
let transaction =
VoteTransaction::vote_account_register(&keypair, vote_account_id, last_id, 0);
if client.transfer_signed(&transaction).is_err() {
sleep(Duration::from_secs(2));
continue;
}

View File

@ -16,6 +16,13 @@ use std::error;
use std::fs::File;
use std::path::Path;
/**
* Bootstrap leader gets two tokens:
* - one token to create an instance of the vote_program with
* - one second token to keep the node identity public key valid
*/
pub const BOOTSTRAP_LEADER_TOKENS: u64 = 2;
fn main() -> Result<(), Box<error::Error>> {
let matches = App::new("solana-genesis")
.version(crate_version!())
@ -62,7 +69,12 @@ fn main() -> Result<(), Box<error::Error>> {
let num_tokens = value_t_or_exit!(matches, "num_tokens", u64);
let file = File::open(Path::new(&matches.value_of("mint").unwrap())).unwrap();
let pkcs8: Vec<u8> = serde_json::from_reader(&file)?;
let mint = Mint::new_with_pkcs8(num_tokens, pkcs8, leader_keypair.pubkey(), 1);
let mint = Mint::new_with_pkcs8(
num_tokens,
pkcs8,
leader_keypair.pubkey(),
BOOTSTRAP_LEADER_TOKENS,
);
// Write the ledger entries
let ledger_path = matches.value_of("ledger").unwrap();

View File

@ -110,20 +110,29 @@ pub struct Fullnode {
pub struct Config {
pub node_info: NodeInfo,
pkcs8: Vec<u8>,
vote_account_pkcs8: Vec<u8>,
}
impl Config {
pub fn new(bind_addr: &SocketAddr, pkcs8: Vec<u8>) -> Self {
pub fn new(bind_addr: &SocketAddr, pkcs8: Vec<u8>, vote_account_pkcs8: Vec<u8>) -> Self {
let keypair =
Keypair::from_pkcs8(Input::from(&pkcs8)).expect("from_pkcs8 in fullnode::Config new");
let pubkey = keypair.pubkey();
let node_info = NodeInfo::new_with_pubkey_socketaddr(pubkey, bind_addr);
Config { node_info, pkcs8 }
Config {
node_info,
pkcs8,
vote_account_pkcs8,
}
}
pub fn keypair(&self) -> Keypair {
Keypair::from_pkcs8(Input::from(&self.pkcs8))
.expect("from_pkcs8 in fullnode::Config keypair")
}
pub fn vote_account_keypair(&self) -> Keypair {
Keypair::from_pkcs8(Input::from(&self.vote_account_pkcs8))
.expect("from_pkcs8 in fullnode::Config vote_account_keypair")
}
}
impl Fullnode {

View File

@ -29,7 +29,6 @@ use std::time::Instant;
use system_transaction::SystemTransaction;
use timing;
use transaction::Transaction;
use vote_transaction::VoteTransaction;
use influx_db_client as influxdb;
use metrics;
@ -99,29 +98,6 @@ impl ThinClient {
))
}
pub fn create_vote_account(
&self,
node_keypair: &Keypair,
vote_account_id: Pubkey,
last_id: &Hash,
num_tokens: u64,
) -> io::Result<Signature> {
let tx =
Transaction::vote_account_new(&node_keypair, vote_account_id, *last_id, num_tokens);
self.transfer_signed(&tx)
}
/// Creates, signs, and processes a vote Transaction. Useful for writing unit-tests.
pub fn register_vote_account(
&self,
node_keypair: &Keypair,
vote_account_id: Pubkey,
last_id: &Hash,
) -> io::Result<Signature> {
let tx = Transaction::vote_account_register(node_keypair, vote_account_id, *last_id, 0);
self.transfer_signed(&tx)
}
/// Creates, signs, and processes a Transaction. Useful for writing unit-tests.
pub fn transfer(
&self,
@ -445,6 +421,7 @@ mod tests {
use std::fs::remove_dir_all;
use system_program::SystemProgram;
use vote_program::VoteProgram;
use vote_transaction::VoteTransaction;
#[test]
fn test_thin_client() {
@ -650,20 +627,21 @@ mod tests {
let validator_vote_account_keypair = Keypair::new();
let vote_account_id = validator_vote_account_keypair.pubkey();
let last_id = client.get_last_id();
let signature = client
.create_vote_account(&validator_keypair, vote_account_id, &last_id, 1)
.unwrap();
let transaction =
VoteTransaction::vote_account_new(&validator_keypair, vote_account_id, last_id, 1);
let signature = client.transfer_signed(&transaction).unwrap();
assert!(client.poll_for_signature(&signature).is_ok());
let balance = retry_get_balance(&mut client, &vote_account_id, Some(1))
.expect("Expected balance for new account to exist");
assert_eq!(balance, 1);
// Register the vote account to the validator
let last_id = client.get_last_id();
let signature = client
.register_vote_account(&validator_keypair, vote_account_id, &last_id)
.unwrap();
let transaction =
VoteTransaction::vote_account_register(&validator_keypair, vote_account_id, last_id, 0);
let signature = client.transfer_signed(&transaction).unwrap();
assert!(client.poll_for_signature(&signature).is_ok());
const LAST: usize = 30;