Remove airdrop from fullnode
This commit is contained in:
parent
1576072edb
commit
a0dd8617be
|
@ -60,6 +60,7 @@ if ((!self_setup)); then
|
||||||
echo " ${here}/setup.sh"
|
echo " ${here}/setup.sh"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
validator_id_path=$SOLANA_CONFIG_PRIVATE_DIR/validator-id.json
|
||||||
validator_json_path=$SOLANA_CONFIG_VALIDATOR_DIR/validator.json
|
validator_json_path=$SOLANA_CONFIG_VALIDATOR_DIR/validator.json
|
||||||
SOLANA_LEADER_CONFIG_DIR=$SOLANA_CONFIG_VALIDATOR_DIR/leader-config
|
SOLANA_LEADER_CONFIG_DIR=$SOLANA_CONFIG_VALIDATOR_DIR/leader-config
|
||||||
else
|
else
|
||||||
|
@ -78,6 +79,22 @@ else
|
||||||
SOLANA_LEADER_CONFIG_DIR=$SOLANA_CONFIG_VALIDATOR_DIR/leader-config-x$$
|
SOLANA_LEADER_CONFIG_DIR=$SOLANA_CONFIG_VALIDATOR_DIR/leader-config-x$$
|
||||||
fi
|
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")
|
rsync_leader_url=$(rsync_url "$leader")
|
||||||
|
|
||||||
tune_networking
|
tune_networking
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
extern crate dirs;
|
extern crate dirs;
|
||||||
|
extern crate ring;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate solana;
|
extern crate solana;
|
||||||
|
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
|
use ring::rand::SystemRandom;
|
||||||
|
use ring::signature::Ed25519KeyPair;
|
||||||
use solana::cluster_info::FULLNODE_PORT_RANGE;
|
use solana::cluster_info::FULLNODE_PORT_RANGE;
|
||||||
use solana::fullnode::Config;
|
use solana::fullnode::Config;
|
||||||
use solana::logger;
|
use solana::logger;
|
||||||
|
@ -67,9 +70,12 @@ fn main() {
|
||||||
};
|
};
|
||||||
let pkcs8 = read_pkcs8(id_path).expect("client keypair");
|
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
|
// we need all the receiving sockets to be bound within the expected
|
||||||
// port range that we open on aws
|
// 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();
|
let stdout = io::stdout();
|
||||||
serde_json::to_writer(stdout, &config).expect("serialize");
|
serde_json::to_writer(stdout, &config).expect("serialize");
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ extern crate solana;
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use solana::client::mk_client;
|
use solana::client::mk_client;
|
||||||
use solana::cluster_info::{Node, FULLNODE_PORT_RANGE};
|
use solana::cluster_info::{Node, FULLNODE_PORT_RANGE};
|
||||||
use solana::drone::{request_airdrop_transaction, DRONE_PORT};
|
|
||||||
use solana::fullnode::{Config, Fullnode, FullnodeReturnType};
|
use solana::fullnode::{Config, Fullnode, FullnodeReturnType};
|
||||||
use solana::leader_scheduler::LeaderScheduler;
|
use solana::leader_scheduler::LeaderScheduler;
|
||||||
use solana::logger;
|
use solana::logger;
|
||||||
|
@ -19,6 +18,7 @@ use solana::netutil::find_available_port_in_range;
|
||||||
use solana::signature::{Keypair, KeypairUtil};
|
use solana::signature::{Keypair, KeypairUtil};
|
||||||
use solana::thin_client::poll_gossip_for_leader;
|
use solana::thin_client::poll_gossip_for_leader;
|
||||||
use solana::vote_program::VoteProgram;
|
use solana::vote_program::VoteProgram;
|
||||||
|
use solana::vote_transaction::VoteTransaction;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::net::{Ipv4Addr, SocketAddr};
|
use std::net::{Ipv4Addr, SocketAddr};
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
@ -61,12 +61,16 @@ fn main() {
|
||||||
.help("Custom RPC port for this node"),
|
.help("Custom RPC port for this node"),
|
||||||
).get_matches();
|
).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();
|
let path = i.to_string();
|
||||||
if let Ok(file) = File::open(path.clone()) {
|
if let Ok(file) = File::open(path.clone()) {
|
||||||
let parse: serde_json::Result<Config> = serde_json::from_reader(file);
|
let parse: serde_json::Result<Config> = serde_json::from_reader(file);
|
||||||
if let Ok(data) = parse {
|
if let Ok(data) = parse {
|
||||||
(data.keypair(), data.node_info.ncp)
|
(
|
||||||
|
data.keypair(),
|
||||||
|
data.vote_account_keypair(),
|
||||||
|
data.node_info.ncp,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
eprintln!("failed to parse {}", path);
|
eprintln!("failed to parse {}", path);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -76,7 +80,7 @@ fn main() {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(Keypair::new(), socketaddr!(0, 8000))
|
(Keypair::new(), Keypair::new(), socketaddr!(0, 8000))
|
||||||
};
|
};
|
||||||
|
|
||||||
let ledger_path = matches.value_of("ledger").unwrap();
|
let ledger_path = matches.value_of("ledger").unwrap();
|
||||||
|
@ -91,7 +95,7 @@ fn main() {
|
||||||
// save off some stuff for airdrop
|
// save off some stuff for airdrop
|
||||||
let mut node_info = node.info.clone();
|
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 vote_account_id = vote_account_keypair.pubkey();
|
||||||
let keypair = Arc::new(keypair);
|
let keypair = Arc::new(keypair);
|
||||||
let pubkey = keypair.pubkey();
|
let pubkey = keypair.pubkey();
|
||||||
|
@ -133,7 +137,7 @@ fn main() {
|
||||||
node,
|
node,
|
||||||
ledger_path,
|
ledger_path,
|
||||||
keypair.clone(),
|
keypair.clone(),
|
||||||
vote_account_keypair,
|
vote_account_keypair.clone(),
|
||||||
network,
|
network,
|
||||||
false,
|
false,
|
||||||
leader_scheduler,
|
leader_scheduler,
|
||||||
|
@ -141,66 +145,43 @@ fn main() {
|
||||||
);
|
);
|
||||||
let mut client = mk_client(&leader);
|
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);
|
let balance = client.poll_get_balance(&pubkey).unwrap_or(0);
|
||||||
info!("balance is {}", balance);
|
info!("balance is {}", balance);
|
||||||
|
if balance < 1 {
|
||||||
if balance >= 50 {
|
error!("insufficient tokens");
|
||||||
info!("good to go!");
|
exit(1);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("requesting airdrop from {}", drone_addr);
|
// 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 {
|
loop {
|
||||||
let last_id = client.get_last_id();
|
let last_id = client.get_last_id();
|
||||||
if let Ok(transaction) = request_airdrop_transaction(&drone_addr, &pubkey, 50, last_id)
|
let transaction =
|
||||||
{
|
VoteTransaction::vote_account_new(&keypair, vote_account_id, last_id, 1);
|
||||||
let signature = client.transfer_signed(&transaction).unwrap();
|
if client.transfer_signed(&transaction).is_err() {
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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));
|
sleep(Duration::from_secs(2));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let balance = client.poll_get_balance(&vote_account_id).unwrap_or(0);
|
let balance = client.poll_get_balance(&vote_account_id).unwrap_or(0);
|
||||||
|
|
||||||
if balance > 0 {
|
if balance > 0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep(Duration::from_secs(2));
|
sleep(Duration::from_secs(2));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Register the vote account to this node
|
// Register the vote account to this node
|
||||||
loop {
|
loop {
|
||||||
let last_id = client.get_last_id();
|
let last_id = client.get_last_id();
|
||||||
if client
|
let transaction =
|
||||||
.register_vote_account(&keypair, vote_account_id, &last_id)
|
VoteTransaction::vote_account_register(&keypair, vote_account_id, last_id, 0);
|
||||||
.is_err()
|
if client.transfer_signed(&transaction).is_err() {
|
||||||
{
|
|
||||||
sleep(Duration::from_secs(2));
|
sleep(Duration::from_secs(2));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,13 @@ use std::error;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::Path;
|
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>> {
|
fn main() -> Result<(), Box<error::Error>> {
|
||||||
let matches = App::new("solana-genesis")
|
let matches = App::new("solana-genesis")
|
||||||
.version(crate_version!())
|
.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 num_tokens = value_t_or_exit!(matches, "num_tokens", u64);
|
||||||
let file = File::open(Path::new(&matches.value_of("mint").unwrap())).unwrap();
|
let file = File::open(Path::new(&matches.value_of("mint").unwrap())).unwrap();
|
||||||
let pkcs8: Vec<u8> = serde_json::from_reader(&file)?;
|
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
|
// Write the ledger entries
|
||||||
let ledger_path = matches.value_of("ledger").unwrap();
|
let ledger_path = matches.value_of("ledger").unwrap();
|
||||||
|
|
|
@ -110,20 +110,29 @@ pub struct Fullnode {
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub node_info: NodeInfo,
|
pub node_info: NodeInfo,
|
||||||
pkcs8: Vec<u8>,
|
pkcs8: Vec<u8>,
|
||||||
|
vote_account_pkcs8: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
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 =
|
let keypair =
|
||||||
Keypair::from_pkcs8(Input::from(&pkcs8)).expect("from_pkcs8 in fullnode::Config new");
|
Keypair::from_pkcs8(Input::from(&pkcs8)).expect("from_pkcs8 in fullnode::Config new");
|
||||||
let pubkey = keypair.pubkey();
|
let pubkey = keypair.pubkey();
|
||||||
let node_info = NodeInfo::new_with_pubkey_socketaddr(pubkey, bind_addr);
|
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 {
|
pub fn keypair(&self) -> Keypair {
|
||||||
Keypair::from_pkcs8(Input::from(&self.pkcs8))
|
Keypair::from_pkcs8(Input::from(&self.pkcs8))
|
||||||
.expect("from_pkcs8 in fullnode::Config keypair")
|
.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 {
|
impl Fullnode {
|
||||||
|
|
|
@ -29,7 +29,6 @@ use std::time::Instant;
|
||||||
use system_transaction::SystemTransaction;
|
use system_transaction::SystemTransaction;
|
||||||
use timing;
|
use timing;
|
||||||
use transaction::Transaction;
|
use transaction::Transaction;
|
||||||
use vote_transaction::VoteTransaction;
|
|
||||||
|
|
||||||
use influx_db_client as influxdb;
|
use influx_db_client as influxdb;
|
||||||
use metrics;
|
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.
|
/// Creates, signs, and processes a Transaction. Useful for writing unit-tests.
|
||||||
pub fn transfer(
|
pub fn transfer(
|
||||||
&self,
|
&self,
|
||||||
|
@ -445,6 +421,7 @@ mod tests {
|
||||||
use std::fs::remove_dir_all;
|
use std::fs::remove_dir_all;
|
||||||
use system_program::SystemProgram;
|
use system_program::SystemProgram;
|
||||||
use vote_program::VoteProgram;
|
use vote_program::VoteProgram;
|
||||||
|
use vote_transaction::VoteTransaction;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_thin_client() {
|
fn test_thin_client() {
|
||||||
|
@ -650,20 +627,21 @@ mod tests {
|
||||||
let validator_vote_account_keypair = Keypair::new();
|
let validator_vote_account_keypair = Keypair::new();
|
||||||
let vote_account_id = validator_vote_account_keypair.pubkey();
|
let vote_account_id = validator_vote_account_keypair.pubkey();
|
||||||
let last_id = client.get_last_id();
|
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());
|
assert!(client.poll_for_signature(&signature).is_ok());
|
||||||
|
|
||||||
let balance = retry_get_balance(&mut client, &vote_account_id, Some(1))
|
let balance = retry_get_balance(&mut client, &vote_account_id, Some(1))
|
||||||
.expect("Expected balance for new account to exist");
|
.expect("Expected balance for new account to exist");
|
||||||
assert_eq!(balance, 1);
|
assert_eq!(balance, 1);
|
||||||
|
|
||||||
// Register the vote account to the validator
|
// Register the vote account to the validator
|
||||||
let last_id = client.get_last_id();
|
let last_id = client.get_last_id();
|
||||||
let signature = client
|
let transaction =
|
||||||
.register_vote_account(&validator_keypair, vote_account_id, &last_id)
|
VoteTransaction::vote_account_register(&validator_keypair, vote_account_id, last_id, 0);
|
||||||
.unwrap();
|
let signature = client.transfer_signed(&transaction).unwrap();
|
||||||
assert!(client.poll_for_signature(&signature).is_ok());
|
assert!(client.poll_for_signature(&signature).is_ok());
|
||||||
|
|
||||||
const LAST: usize = 30;
|
const LAST: usize = 30;
|
||||||
|
|
Loading…
Reference in New Issue