Use vote signer service in fullnode (#2009)
* Use vote signer service in fullnode * Use native types for signature and pubkey, and address other review comments * Start local vote signer if a remote service address is not provided * Rebased to master * Fixes after rebase
This commit is contained in:
parent
71a2b794b4
commit
91bd38504e
|
@ -1806,6 +1806,7 @@ dependencies = [
|
||||||
"solana-netutil 0.12.0",
|
"solana-netutil 0.12.0",
|
||||||
"solana-sdk 0.12.0",
|
"solana-sdk 0.12.0",
|
||||||
"solana-system-program 0.12.0",
|
"solana-system-program 0.12.0",
|
||||||
|
"solana-vote-signer 0.12.0",
|
||||||
"sys-info 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"sys-info 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -57,6 +57,7 @@ solana-native-loader = { path = "programs/native/native_loader", version = "0.12
|
||||||
solana-netutil = { path = "netutil", version = "0.12.0" }
|
solana-netutil = { path = "netutil", version = "0.12.0" }
|
||||||
solana-sdk = { path = "sdk", version = "0.12.0" }
|
solana-sdk = { path = "sdk", version = "0.12.0" }
|
||||||
solana-system-program = { path = "programs/native/system", version = "0.12.0" }
|
solana-system-program = { path = "programs/native/system", version = "0.12.0" }
|
||||||
|
solana-vote-signer = { path = "vote-signer", version = "0.12.0" }
|
||||||
sys-info = "0.5.6"
|
sys-info = "0.5.6"
|
||||||
tokio = "0.1"
|
tokio = "0.1"
|
||||||
tokio-codec = "0.1"
|
tokio-codec = "0.1"
|
||||||
|
|
|
@ -1,12 +1,19 @@
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
use log::*;
|
use log::*;
|
||||||
|
|
||||||
use solana::client::mk_client;
|
use solana::client::mk_client;
|
||||||
use solana::cluster_info::{Node, NodeInfo, FULLNODE_PORT_RANGE};
|
use solana::cluster_info::{Node, NodeInfo, FULLNODE_PORT_RANGE};
|
||||||
|
use solana::create_vote_account;
|
||||||
use solana::fullnode::{Fullnode, FullnodeReturnType};
|
use solana::fullnode::{Fullnode, FullnodeReturnType};
|
||||||
use solana::leader_scheduler::LeaderScheduler;
|
use solana::leader_scheduler::LeaderScheduler;
|
||||||
|
use solana::rpc_request::{RpcClient, RpcRequest};
|
||||||
use solana::socketaddr;
|
use solana::socketaddr;
|
||||||
use solana::thin_client::poll_gossip_for_leader;
|
use solana::thin_client::poll_gossip_for_leader;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||||
use solana_sdk::vote_program::VoteProgram;
|
use solana_sdk::vote_program::VoteProgram;
|
||||||
use solana_sdk::vote_transaction::VoteTransaction;
|
use solana_sdk::vote_transaction::VoteTransaction;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
@ -16,6 +23,7 @@ use std::sync::Arc;
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
#[allow(clippy::cyclomatic_complexity)]
|
||||||
fn main() {
|
fn main() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
solana_metrics::set_panic_hook("fullnode");
|
solana_metrics::set_panic_hook("fullnode");
|
||||||
|
@ -48,6 +56,14 @@ fn main() {
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("Rendezvous with the network at this gossip entry point"),
|
.help("Rendezvous with the network at this gossip entry point"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("signer")
|
||||||
|
.short("s")
|
||||||
|
.long("signer")
|
||||||
|
.value_name("HOST:PORT")
|
||||||
|
.takes_value(true)
|
||||||
|
.help("Rendezvous with the vote signer at this RPC end point"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("ledger")
|
Arg::with_name("ledger")
|
||||||
.short("l")
|
.short("l")
|
||||||
|
@ -69,7 +85,7 @@ fn main() {
|
||||||
let nosigverify = matches.is_present("nosigverify");
|
let nosigverify = matches.is_present("nosigverify");
|
||||||
let use_only_bootstrap_leader = matches.is_present("no-leader-rotation");
|
let use_only_bootstrap_leader = matches.is_present("no-leader-rotation");
|
||||||
|
|
||||||
let (keypair, vote_account_keypair, gossip) = if let Some(i) = matches.value_of("identity") {
|
let (keypair, _vote_account_keypair, gossip) = 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<solana_fullnode_config::Config> =
|
let parse: serde_json::Result<solana_fullnode_config::Config> =
|
||||||
|
@ -106,13 +122,35 @@ fn main() {
|
||||||
.value_of("network")
|
.value_of("network")
|
||||||
.map(|network| network.parse().expect("failed to parse network address"));
|
.map(|network| network.parse().expect("failed to parse network address"));
|
||||||
|
|
||||||
|
let (signer, t_signer, signer_exit) = if let Some(signer_addr) = matches.value_of("signer") {
|
||||||
|
(
|
||||||
|
signer_addr.to_string().parse().expect("Signer IP Address"),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// If a remote vote-signer service is not provided, run a local instance
|
||||||
|
let (signer, t_signer, signer_exit) = create_vote_account::local_vote_signer_service()
|
||||||
|
.expect("Failed to start vote signer service");
|
||||||
|
(signer, Some(t_signer), Some(signer_exit))
|
||||||
|
};
|
||||||
|
|
||||||
let node = Node::new_with_external_ip(keypair.pubkey(), &gossip);
|
let node = Node::new_with_external_ip(keypair.pubkey(), &gossip);
|
||||||
|
|
||||||
// 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(vote_account_keypair);
|
let rpc_client = RpcClient::new_from_socket(signer);
|
||||||
let vote_account_id = vote_account_keypair.pubkey();
|
|
||||||
|
let msg = "Registering a new node";
|
||||||
|
let sig = Signature::new(&keypair.sign(msg.as_bytes()).as_ref());
|
||||||
|
|
||||||
|
let params = json!([keypair.pubkey(), sig, msg.as_bytes()]);
|
||||||
|
let resp = RpcRequest::RegisterNode
|
||||||
|
.make_rpc_request(&rpc_client, 1, Some(params))
|
||||||
|
.unwrap();
|
||||||
|
let vote_account_id: Pubkey = serde_json::from_value(resp).unwrap();
|
||||||
|
info!("New vote account ID is {:?}", vote_account_id);
|
||||||
let keypair = Arc::new(keypair);
|
let keypair = Arc::new(keypair);
|
||||||
let pubkey = keypair.pubkey();
|
let pubkey = keypair.pubkey();
|
||||||
|
|
||||||
|
@ -125,6 +163,11 @@ fn main() {
|
||||||
let port_number = port.to_string().parse().expect("integer");
|
let port_number = port.to_string().parse().expect("integer");
|
||||||
if port_number == 0 {
|
if port_number == 0 {
|
||||||
eprintln!("Invalid RPC port requested: {:?}", port);
|
eprintln!("Invalid RPC port requested: {:?}", port);
|
||||||
|
if let Some(t) = t_signer {
|
||||||
|
if let Some(exit) = signer_exit {
|
||||||
|
create_vote_account::stop_local_vote_signer_service(t, &exit);
|
||||||
|
}
|
||||||
|
}
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
Some(port_number)
|
Some(port_number)
|
||||||
|
@ -153,7 +196,8 @@ fn main() {
|
||||||
node,
|
node,
|
||||||
ledger_path,
|
ledger_path,
|
||||||
keypair.clone(),
|
keypair.clone(),
|
||||||
vote_account_keypair.clone(),
|
&vote_account_id,
|
||||||
|
&signer,
|
||||||
network,
|
network,
|
||||||
nosigverify,
|
nosigverify,
|
||||||
leader_scheduler,
|
leader_scheduler,
|
||||||
|
@ -165,6 +209,11 @@ fn main() {
|
||||||
info!("balance is {}", balance);
|
info!("balance is {}", balance);
|
||||||
if balance < 1 {
|
if balance < 1 {
|
||||||
error!("insufficient tokens");
|
error!("insufficient tokens");
|
||||||
|
if let Some(t) = t_signer {
|
||||||
|
if let Some(exit) = signer_exit {
|
||||||
|
create_vote_account::stop_local_vote_signer_service(t, &exit);
|
||||||
|
}
|
||||||
|
}
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,6 +222,11 @@ fn main() {
|
||||||
// Need at least two tokens as one token will be spent on a vote_account_new() transaction
|
// Need at least two tokens as one token will be spent on a vote_account_new() transaction
|
||||||
if balance < 2 {
|
if balance < 2 {
|
||||||
error!("insufficient tokens");
|
error!("insufficient tokens");
|
||||||
|
if let Some(t) = t_signer {
|
||||||
|
if let Some(exit) = signer_exit {
|
||||||
|
create_vote_account::stop_local_vote_signer_service(t, &exit);
|
||||||
|
}
|
||||||
|
}
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
loop {
|
loop {
|
||||||
|
@ -212,6 +266,11 @@ fn main() {
|
||||||
_ => {
|
_ => {
|
||||||
// Fullnode tpu/tvu exited for some unexpected
|
// Fullnode tpu/tvu exited for some unexpected
|
||||||
// reason, so exit
|
// reason, so exit
|
||||||
|
if let Some(t) = t_signer {
|
||||||
|
if let Some(exit) = signer_exit {
|
||||||
|
create_vote_account::stop_local_vote_signer_service(t, &exit);
|
||||||
|
}
|
||||||
|
}
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,21 @@ impl Transaction {
|
||||||
instructions,
|
instructions,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
pub fn new_unsigned<T: Serialize>(
|
||||||
|
from_pubkey: &Pubkey,
|
||||||
|
transaction_keys: &[Pubkey],
|
||||||
|
program_id: Pubkey,
|
||||||
|
userdata: &T,
|
||||||
|
last_id: Hash,
|
||||||
|
fee: u64,
|
||||||
|
) -> Self {
|
||||||
|
let program_ids = vec![program_id];
|
||||||
|
let accounts = (0..=transaction_keys.len() as u8).collect();
|
||||||
|
let instructions = vec![Instruction::new(0, userdata, accounts)];
|
||||||
|
let mut keys = vec![*from_pubkey];
|
||||||
|
keys.extend_from_slice(transaction_keys);
|
||||||
|
Self::new_with_instructions(&[], &keys[..], last_id, fee, program_ids, instructions)
|
||||||
|
}
|
||||||
/// Create a signed transaction
|
/// Create a signed transaction
|
||||||
/// * `from_keypair` - The key used to sign the transaction. This key is stored as keys[0]
|
/// * `from_keypair` - The key used to sign the transaction. This key is stored as keys[0]
|
||||||
/// * `account_keys` - The keys for the transaction. These are the program state
|
/// * `account_keys` - The keys for the transaction. These are the program state
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::vote_program::{self, Vote, VoteInstruction};
|
||||||
use bincode::deserialize;
|
use bincode::deserialize;
|
||||||
|
|
||||||
pub trait VoteTransaction {
|
pub trait VoteTransaction {
|
||||||
fn vote_new(vote_account: &Keypair, vote: Vote, last_id: Hash, fee: u64) -> Self;
|
fn vote_new(vote_account: &Pubkey, vote: Vote, last_id: Hash, fee: u64) -> Self;
|
||||||
fn vote_account_new(
|
fn vote_account_new(
|
||||||
validator_id: &Keypair,
|
validator_id: &Keypair,
|
||||||
vote_account_id: Pubkey,
|
vote_account_id: Pubkey,
|
||||||
|
@ -23,9 +23,9 @@ pub trait VoteTransaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VoteTransaction for Transaction {
|
impl VoteTransaction for Transaction {
|
||||||
fn vote_new(vote_account: &Keypair, vote: Vote, last_id: Hash, fee: u64) -> Self {
|
fn vote_new(vote_account: &Pubkey, vote: Vote, last_id: Hash, fee: u64) -> Self {
|
||||||
let instruction = VoteInstruction::NewVote(vote);
|
let instruction = VoteInstruction::NewVote(vote);
|
||||||
Transaction::new(
|
Transaction::new_unsigned(
|
||||||
vote_account,
|
vote_account,
|
||||||
&[],
|
&[],
|
||||||
vote_program::id(),
|
vote_program::id(),
|
||||||
|
|
|
@ -160,12 +160,11 @@ pub mod tests {
|
||||||
use crate::create_vote_account::*;
|
use crate::create_vote_account::*;
|
||||||
|
|
||||||
use crate::mint::Mint;
|
use crate::mint::Mint;
|
||||||
|
use crate::rpc_request::RpcClient;
|
||||||
|
use crate::vote_stage::create_new_signed_vote_transaction;
|
||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
use solana_sdk::hash::hash;
|
use solana_sdk::hash::hash;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::transaction::Transaction;
|
|
||||||
use solana_sdk::vote_program::Vote;
|
|
||||||
use solana_sdk::vote_transaction::VoteTransaction;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -188,6 +187,8 @@ pub mod tests {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
|
let rpc_client = RpcClient::new_from_socket(signer);
|
||||||
// Create a total of 10 vote accounts, each will have a balance of 1 (after giving 1 to
|
// Create a total of 10 vote accounts, each will have a balance of 1 (after giving 1 to
|
||||||
// their vote account), for a total staking pool of 10 tokens.
|
// their vote account), for a total staking pool of 10 tokens.
|
||||||
let vote_accounts: Vec<_> = (0..10)
|
let vote_accounts: Vec<_> = (0..10)
|
||||||
|
@ -199,17 +200,22 @@ pub mod tests {
|
||||||
// Give the validator some tokens
|
// Give the validator some tokens
|
||||||
bank.transfer(2, &mint.keypair(), validator_keypair.pubkey(), last_id)
|
bank.transfer(2, &mint.keypair(), validator_keypair.pubkey(), last_id)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let vote_account = create_vote_account(&validator_keypair, &bank, 1, last_id)
|
let vote_account =
|
||||||
.expect("Expected successful creation of account");
|
create_vote_account(&validator_keypair, &bank, 1, last_id, &rpc_client)
|
||||||
|
.expect("Expected successful creation of account");
|
||||||
|
|
||||||
|
let validator_keypair = Arc::new(validator_keypair);
|
||||||
if i < 6 {
|
if i < 6 {
|
||||||
let vote = Vote {
|
let vote_tx = create_new_signed_vote_transaction(
|
||||||
tick_height: (i + 1) as u64,
|
&last_id,
|
||||||
};
|
&validator_keypair,
|
||||||
let vote_tx = Transaction::vote_new(&vote_account, vote, last_id, 0);
|
(i + 1) as u64,
|
||||||
|
&vote_account,
|
||||||
|
&rpc_client,
|
||||||
|
);
|
||||||
bank.process_transaction(&vote_tx).unwrap();
|
bank.process_transaction(&vote_tx).unwrap();
|
||||||
}
|
}
|
||||||
vote_account
|
(vote_account, validator_keypair)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -223,9 +229,14 @@ pub mod tests {
|
||||||
assert_eq!(bank.confirmation_time(), std::usize::MAX);
|
assert_eq!(bank.confirmation_time(), std::usize::MAX);
|
||||||
|
|
||||||
// Get another validator to vote, so we now have 2/3 consensus
|
// Get another validator to vote, so we now have 2/3 consensus
|
||||||
let vote_account = &vote_accounts[7];
|
let vote_account = &vote_accounts[7].0;
|
||||||
let vote = Vote { tick_height: 7 };
|
let vote_tx = create_new_signed_vote_transaction(
|
||||||
let vote_tx = Transaction::vote_new(&vote_account, vote, ids[6], 0);
|
&ids[6],
|
||||||
|
&vote_accounts[7].1,
|
||||||
|
7,
|
||||||
|
&vote_account,
|
||||||
|
&rpc_client,
|
||||||
|
);
|
||||||
bank.process_transaction(&vote_tx).unwrap();
|
bank.process_transaction(&vote_tx).unwrap();
|
||||||
|
|
||||||
ComputeLeaderConfirmationService::compute_confirmation(
|
ComputeLeaderConfirmationService::compute_confirmation(
|
||||||
|
@ -235,5 +246,6 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
assert!(bank.confirmation_time() != std::usize::MAX);
|
assert!(bank.confirmation_time() != std::usize::MAX);
|
||||||
assert!(last_confirmation_time > 0);
|
assert!(last_confirmation_time > 0);
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,60 @@
|
||||||
use crate::bank::Bank;
|
use crate::bank::Bank;
|
||||||
|
use crate::cluster_info::FULLNODE_PORT_RANGE;
|
||||||
use crate::result::Result;
|
use crate::result::Result;
|
||||||
|
use crate::rpc_request::{RpcClient, RpcRequest};
|
||||||
|
use solana_netutil::find_available_port_in_range;
|
||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::hash::Hash;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
use solana_sdk::vote_transaction::*;
|
use solana_sdk::vote_transaction::*;
|
||||||
|
use solana_vote_signer::rpc::VoteSignerRpcService;
|
||||||
|
use std::io;
|
||||||
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::thread::{Builder, JoinHandle};
|
||||||
|
|
||||||
|
pub fn local_vote_signer_service() -> io::Result<(SocketAddr, JoinHandle<()>, Arc<AtomicBool>)> {
|
||||||
|
let addr = match find_available_port_in_range(FULLNODE_PORT_RANGE) {
|
||||||
|
Ok(port) => SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), port),
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
};
|
||||||
|
let service_addr = addr;
|
||||||
|
let exit = Arc::new(AtomicBool::new(false));
|
||||||
|
let thread_exit = exit.clone();
|
||||||
|
let thread = Builder::new()
|
||||||
|
.name("solana-vote-signer".to_string())
|
||||||
|
.spawn(move || {
|
||||||
|
let service = VoteSignerRpcService::new(service_addr, thread_exit);
|
||||||
|
service.join().unwrap();
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
Ok((addr, thread, exit))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stop_local_vote_signer_service(t: JoinHandle<()>, exit: &Arc<AtomicBool>) {
|
||||||
|
exit.store(true, Ordering::Relaxed);
|
||||||
|
t.join().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_vote_account(
|
pub fn create_vote_account(
|
||||||
node_keypair: &Keypair,
|
node_keypair: &Keypair,
|
||||||
bank: &Bank,
|
bank: &Bank,
|
||||||
num_tokens: u64,
|
num_tokens: u64,
|
||||||
last_id: Hash,
|
last_id: Hash,
|
||||||
) -> Result<Keypair> {
|
rpc_client: &RpcClient,
|
||||||
let new_vote_account = Keypair::new();
|
) -> Result<Pubkey> {
|
||||||
|
let msg = "Registering a new node";
|
||||||
|
let sig = Signature::new(&node_keypair.sign(msg.as_bytes()).as_ref());
|
||||||
|
let params = json!([node_keypair.pubkey(), sig, msg.as_bytes()]);
|
||||||
|
let resp = RpcRequest::RegisterNode
|
||||||
|
.make_rpc_request(&rpc_client, 1, Some(params))
|
||||||
|
.unwrap();
|
||||||
|
let new_vote_account: Pubkey = serde_json::from_value(resp).unwrap();
|
||||||
|
|
||||||
// Create and register the new vote account
|
// Create and register the new vote account
|
||||||
let tx = Transaction::vote_account_new(
|
let tx = Transaction::vote_account_new(node_keypair, new_vote_account, last_id, num_tokens, 0);
|
||||||
node_keypair,
|
|
||||||
new_vote_account.pubkey(),
|
|
||||||
last_id,
|
|
||||||
num_tokens,
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
bank.process_transaction(&tx)?;
|
bank.process_transaction(&tx)?;
|
||||||
|
|
||||||
Ok(new_vote_account)
|
Ok(new_vote_account)
|
||||||
|
|
|
@ -16,6 +16,7 @@ use crate::tvu::{Sockets, Tvu, TvuReturnType};
|
||||||
use crate::window::{new_window, SharedWindow};
|
use crate::window::{new_window, SharedWindow};
|
||||||
use log::Level;
|
use log::Level;
|
||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::hash::Hash;
|
||||||
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::timing::timestamp;
|
use solana_sdk::timing::timestamp;
|
||||||
use std::net::UdpSocket;
|
use std::net::UdpSocket;
|
||||||
|
@ -90,7 +91,7 @@ pub enum FullnodeReturnType {
|
||||||
pub struct Fullnode {
|
pub struct Fullnode {
|
||||||
pub node_role: Option<NodeRole>,
|
pub node_role: Option<NodeRole>,
|
||||||
keypair: Arc<Keypair>,
|
keypair: Arc<Keypair>,
|
||||||
vote_account_keypair: Arc<Keypair>,
|
vote_account_id: Pubkey,
|
||||||
exit: Arc<AtomicBool>,
|
exit: Arc<AtomicBool>,
|
||||||
rpc_service: Option<JsonRpcService>,
|
rpc_service: Option<JsonRpcService>,
|
||||||
rpc_pubsub_service: Option<PubSubService>,
|
rpc_pubsub_service: Option<PubSubService>,
|
||||||
|
@ -107,6 +108,7 @@ pub struct Fullnode {
|
||||||
rpc_addr: SocketAddr,
|
rpc_addr: SocketAddr,
|
||||||
rpc_pubsub_addr: SocketAddr,
|
rpc_pubsub_addr: SocketAddr,
|
||||||
drone_addr: SocketAddr,
|
drone_addr: SocketAddr,
|
||||||
|
vote_signer_addr: SocketAddr,
|
||||||
db_ledger: Arc<DbLedger>,
|
db_ledger: Arc<DbLedger>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +117,8 @@ impl Fullnode {
|
||||||
node: Node,
|
node: Node,
|
||||||
ledger_path: &str,
|
ledger_path: &str,
|
||||||
keypair: Arc<Keypair>,
|
keypair: Arc<Keypair>,
|
||||||
vote_account_keypair: Arc<Keypair>,
|
vote_account_id: &Pubkey,
|
||||||
|
vote_signer_addr: &SocketAddr,
|
||||||
leader_addr: Option<SocketAddr>,
|
leader_addr: Option<SocketAddr>,
|
||||||
sigverify_disabled: bool,
|
sigverify_disabled: bool,
|
||||||
leader_scheduler: LeaderScheduler,
|
leader_scheduler: LeaderScheduler,
|
||||||
|
@ -144,7 +147,8 @@ impl Fullnode {
|
||||||
let leader_info = leader_addr.map(|i| NodeInfo::new_entry_point(&i));
|
let leader_info = leader_addr.map(|i| NodeInfo::new_entry_point(&i));
|
||||||
let server = Self::new_with_bank(
|
let server = Self::new_with_bank(
|
||||||
keypair,
|
keypair,
|
||||||
vote_account_keypair,
|
vote_account_id,
|
||||||
|
vote_signer_addr,
|
||||||
bank,
|
bank,
|
||||||
Some(db_ledger),
|
Some(db_ledger),
|
||||||
entry_height,
|
entry_height,
|
||||||
|
@ -175,7 +179,8 @@ impl Fullnode {
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new_with_bank(
|
pub fn new_with_bank(
|
||||||
keypair: Arc<Keypair>,
|
keypair: Arc<Keypair>,
|
||||||
vote_account_keypair: Arc<Keypair>,
|
vote_account_id: &Pubkey,
|
||||||
|
vote_signer_addr: &SocketAddr,
|
||||||
bank: Bank,
|
bank: Bank,
|
||||||
db_ledger: Option<Arc<DbLedger>>,
|
db_ledger: Option<Arc<DbLedger>>,
|
||||||
entry_height: u64,
|
entry_height: u64,
|
||||||
|
@ -266,7 +271,8 @@ impl Fullnode {
|
||||||
};
|
};
|
||||||
|
|
||||||
let tvu = Tvu::new(
|
let tvu = Tvu::new(
|
||||||
vote_account_keypair.clone(),
|
vote_account_id,
|
||||||
|
vote_signer_addr,
|
||||||
&bank,
|
&bank,
|
||||||
entry_height,
|
entry_height,
|
||||||
*last_entry_id,
|
*last_entry_id,
|
||||||
|
@ -329,7 +335,7 @@ impl Fullnode {
|
||||||
|
|
||||||
Fullnode {
|
Fullnode {
|
||||||
keypair,
|
keypair,
|
||||||
vote_account_keypair,
|
vote_account_id: *vote_account_id,
|
||||||
cluster_info,
|
cluster_info,
|
||||||
shared_window,
|
shared_window,
|
||||||
bank,
|
bank,
|
||||||
|
@ -347,6 +353,7 @@ impl Fullnode {
|
||||||
rpc_addr,
|
rpc_addr,
|
||||||
rpc_pubsub_addr,
|
rpc_pubsub_addr,
|
||||||
drone_addr,
|
drone_addr,
|
||||||
|
vote_signer_addr: *vote_signer_addr,
|
||||||
db_ledger,
|
db_ledger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -430,7 +437,8 @@ impl Fullnode {
|
||||||
};
|
};
|
||||||
|
|
||||||
let tvu = Tvu::new(
|
let tvu = Tvu::new(
|
||||||
self.vote_account_keypair.clone(),
|
&self.vote_account_id,
|
||||||
|
&self.vote_signer_addr,
|
||||||
&self.bank,
|
&self.bank,
|
||||||
entry_height,
|
entry_height,
|
||||||
last_entry_id,
|
last_entry_id,
|
||||||
|
@ -644,6 +652,7 @@ impl Service for Fullnode {
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::bank::Bank;
|
use crate::bank::Bank;
|
||||||
use crate::cluster_info::Node;
|
use crate::cluster_info::Node;
|
||||||
|
use crate::create_vote_account::*;
|
||||||
use crate::db_ledger::*;
|
use crate::db_ledger::*;
|
||||||
use crate::fullnode::{Fullnode, FullnodeReturnType, NodeRole, TvuReturnType};
|
use crate::fullnode::{Fullnode, FullnodeReturnType, NodeRole, TvuReturnType};
|
||||||
use crate::leader_scheduler::{
|
use crate::leader_scheduler::{
|
||||||
|
@ -652,12 +661,15 @@ mod tests {
|
||||||
use crate::ledger::{
|
use crate::ledger::{
|
||||||
create_tmp_genesis, create_tmp_sample_ledger, make_consecutive_blobs, tmp_copy_ledger,
|
create_tmp_genesis, create_tmp_sample_ledger, make_consecutive_blobs, tmp_copy_ledger,
|
||||||
};
|
};
|
||||||
|
use crate::rpc_request::{RpcClient, RpcRequest};
|
||||||
use crate::service::Service;
|
use crate::service::Service;
|
||||||
use crate::streamer::responder;
|
use crate::streamer::responder;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::fs::remove_dir_all;
|
use std::fs::remove_dir_all;
|
||||||
use std::net::UdpSocket;
|
use std::net::UdpSocket;
|
||||||
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
@ -680,7 +692,8 @@ mod tests {
|
||||||
let last_id = bank.last_id();
|
let last_id = bank.last_id();
|
||||||
let v = Fullnode::new_with_bank(
|
let v = Fullnode::new_with_bank(
|
||||||
Arc::new(keypair),
|
Arc::new(keypair),
|
||||||
Arc::new(Keypair::new()),
|
&Keypair::new().pubkey(),
|
||||||
|
&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
|
||||||
bank,
|
bank,
|
||||||
None,
|
None,
|
||||||
entry_height,
|
entry_height,
|
||||||
|
@ -721,7 +734,8 @@ mod tests {
|
||||||
let last_id = bank.last_id();
|
let last_id = bank.last_id();
|
||||||
Fullnode::new_with_bank(
|
Fullnode::new_with_bank(
|
||||||
Arc::new(keypair),
|
Arc::new(keypair),
|
||||||
Arc::new(Keypair::new()),
|
&Keypair::new().pubkey(),
|
||||||
|
&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
|
||||||
bank,
|
bank,
|
||||||
None,
|
None,
|
||||||
entry_height,
|
entry_height,
|
||||||
|
@ -795,7 +809,8 @@ mod tests {
|
||||||
bootstrap_leader_node,
|
bootstrap_leader_node,
|
||||||
&bootstrap_leader_ledger_path,
|
&bootstrap_leader_ledger_path,
|
||||||
Arc::new(bootstrap_leader_keypair),
|
Arc::new(bootstrap_leader_keypair),
|
||||||
Arc::new(Keypair::new()),
|
&Keypair::new().pubkey(),
|
||||||
|
&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
|
||||||
Some(bootstrap_leader_info.gossip),
|
Some(bootstrap_leader_info.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::new(&leader_scheduler_config),
|
LeaderScheduler::new(&leader_scheduler_config),
|
||||||
|
@ -848,8 +863,10 @@ mod tests {
|
||||||
|
|
||||||
// Write the entries to the ledger that will cause leader rotation
|
// Write the entries to the ledger that will cause leader rotation
|
||||||
// after the bootstrap height
|
// after the bootstrap height
|
||||||
let (active_set_entries, validator_vote_account_keypair) = make_active_set_entries(
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
|
let (active_set_entries, validator_vote_account_id) = make_active_set_entries(
|
||||||
&validator_keypair,
|
&validator_keypair,
|
||||||
|
signer,
|
||||||
&mint.keypair(),
|
&mint.keypair(),
|
||||||
&last_id,
|
&last_id,
|
||||||
&last_id,
|
&last_id,
|
||||||
|
@ -898,12 +915,13 @@ mod tests {
|
||||||
|
|
||||||
{
|
{
|
||||||
// Test that a node knows to transition to a validator based on parsing the ledger
|
// Test that a node knows to transition to a validator based on parsing the ledger
|
||||||
let leader_vote_account_keypair = Arc::new(Keypair::new());
|
let leader_vote_id = register_node(signer, bootstrap_leader_keypair.clone());
|
||||||
let bootstrap_leader = Fullnode::new(
|
let bootstrap_leader = Fullnode::new(
|
||||||
bootstrap_leader_node,
|
bootstrap_leader_node,
|
||||||
&bootstrap_leader_ledger_path,
|
&bootstrap_leader_ledger_path,
|
||||||
bootstrap_leader_keypair,
|
bootstrap_leader_keypair,
|
||||||
leader_vote_account_keypair,
|
&leader_vote_id,
|
||||||
|
&signer,
|
||||||
Some(bootstrap_leader_info.gossip),
|
Some(bootstrap_leader_info.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::new(&leader_scheduler_config),
|
LeaderScheduler::new(&leader_scheduler_config),
|
||||||
|
@ -922,7 +940,8 @@ mod tests {
|
||||||
validator_node,
|
validator_node,
|
||||||
&validator_ledger_path,
|
&validator_ledger_path,
|
||||||
Arc::new(validator_keypair),
|
Arc::new(validator_keypair),
|
||||||
Arc::new(validator_vote_account_keypair),
|
&validator_vote_account_id,
|
||||||
|
&signer,
|
||||||
Some(bootstrap_leader_info.gossip),
|
Some(bootstrap_leader_info.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::new(&leader_scheduler_config),
|
LeaderScheduler::new(&leader_scheduler_config),
|
||||||
|
@ -945,6 +964,21 @@ mod tests {
|
||||||
DbLedger::destroy(&path).expect("Expected successful database destruction");
|
DbLedger::destroy(&path).expect("Expected successful database destruction");
|
||||||
let _ignored = remove_dir_all(&path);
|
let _ignored = remove_dir_all(&path);
|
||||||
}
|
}
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register_node(signer: SocketAddr, keypair: Arc<Keypair>) -> Pubkey {
|
||||||
|
let rpc_client = RpcClient::new_from_socket(signer);
|
||||||
|
|
||||||
|
let msg = "Registering a new node";
|
||||||
|
let sig = Signature::new(&keypair.sign(msg.as_bytes()).as_ref());
|
||||||
|
|
||||||
|
let params = json!([keypair.pubkey(), sig, msg.as_bytes()]);
|
||||||
|
let resp = RpcRequest::RegisterNode
|
||||||
|
.make_rpc_request(&rpc_client, 1, Some(params))
|
||||||
|
.unwrap();
|
||||||
|
let vote_account_id: Pubkey = serde_json::from_value(resp).unwrap();
|
||||||
|
vote_account_id
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -981,8 +1015,15 @@ mod tests {
|
||||||
// after the bootstrap height
|
// after the bootstrap height
|
||||||
//
|
//
|
||||||
// 2) A vote from the validator
|
// 2) A vote from the validator
|
||||||
let (active_set_entries, validator_vote_account_keypair) =
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
make_active_set_entries(&validator_keypair, &mint.keypair(), &last_id, &last_id, 0);
|
let (active_set_entries, _validator_vote_account_id) = make_active_set_entries(
|
||||||
|
&validator_keypair,
|
||||||
|
signer,
|
||||||
|
&mint.keypair(),
|
||||||
|
&last_id,
|
||||||
|
&last_id,
|
||||||
|
0,
|
||||||
|
);
|
||||||
let initial_tick_height = genesis_entries
|
let initial_tick_height = genesis_entries
|
||||||
.iter()
|
.iter()
|
||||||
.skip(2)
|
.skip(2)
|
||||||
|
@ -1016,12 +1057,15 @@ mod tests {
|
||||||
Some(bootstrap_height),
|
Some(bootstrap_height),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let validator_keypair = Arc::new(validator_keypair);
|
||||||
|
let vote_id = register_node(signer, validator_keypair.clone());
|
||||||
// Start the validator
|
// Start the validator
|
||||||
let mut validator = Fullnode::new(
|
let mut validator = Fullnode::new(
|
||||||
validator_node,
|
validator_node,
|
||||||
&validator_ledger_path,
|
&validator_ledger_path,
|
||||||
Arc::new(validator_keypair),
|
validator_keypair,
|
||||||
Arc::new(validator_vote_account_keypair),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
Some(leader_gossip),
|
Some(leader_gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::new(&leader_scheduler_config),
|
LeaderScheduler::new(&leader_scheduler_config),
|
||||||
|
@ -1090,6 +1134,7 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Shut down
|
// Shut down
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
t_responder.join().expect("responder thread join");
|
t_responder.join().expect("responder thread join");
|
||||||
validator.close().unwrap();
|
validator.close().unwrap();
|
||||||
DbLedger::destroy(&validator_ledger_path)
|
DbLedger::destroy(&validator_ledger_path)
|
||||||
|
|
|
@ -5,17 +5,19 @@ use crate::bank::Bank;
|
||||||
|
|
||||||
use crate::entry::Entry;
|
use crate::entry::Entry;
|
||||||
use crate::ledger::create_ticks;
|
use crate::ledger::create_ticks;
|
||||||
|
use crate::rpc_request::{RpcClient, RpcRequest};
|
||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
use byteorder::{LittleEndian, ReadBytesExt};
|
use byteorder::{LittleEndian, ReadBytesExt};
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
use solana_sdk::hash::{hash, Hash};
|
use solana_sdk::hash::{hash, Hash};
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||||
use solana_sdk::system_transaction::SystemTransaction;
|
use solana_sdk::system_transaction::SystemTransaction;
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
use solana_sdk::vote_program::{self, Vote, VoteProgram};
|
use solana_sdk::vote_program::{self, Vote, VoteProgram};
|
||||||
use solana_sdk::vote_transaction::VoteTransaction;
|
use solana_sdk::vote_transaction::VoteTransaction;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
pub const DEFAULT_BOOTSTRAP_HEIGHT: u64 = 1000;
|
pub const DEFAULT_BOOTSTRAP_HEIGHT: u64 = 1000;
|
||||||
pub const DEFAULT_LEADER_ROTATION_INTERVAL: u64 = 100;
|
pub const DEFAULT_LEADER_ROTATION_INTERVAL: u64 = 100;
|
||||||
|
@ -480,11 +482,12 @@ impl Default for LeaderScheduler {
|
||||||
// 2) A vote from the validator
|
// 2) A vote from the validator
|
||||||
pub fn make_active_set_entries(
|
pub fn make_active_set_entries(
|
||||||
active_keypair: &Keypair,
|
active_keypair: &Keypair,
|
||||||
|
signer: SocketAddr,
|
||||||
token_source: &Keypair,
|
token_source: &Keypair,
|
||||||
last_entry_id: &Hash,
|
last_entry_id: &Hash,
|
||||||
last_tick_id: &Hash,
|
last_tick_id: &Hash,
|
||||||
num_ending_ticks: usize,
|
num_ending_ticks: usize,
|
||||||
) -> (Vec<Entry>, Keypair) {
|
) -> (Vec<Entry>, Pubkey) {
|
||||||
// 1) Create transfer token entry
|
// 1) Create transfer token entry
|
||||||
let transfer_tx =
|
let transfer_tx =
|
||||||
Transaction::system_new(&token_source, active_keypair.pubkey(), 3, *last_tick_id);
|
Transaction::system_new(&token_source, active_keypair.pubkey(), 3, *last_tick_id);
|
||||||
|
@ -492,15 +495,35 @@ pub fn make_active_set_entries(
|
||||||
let mut last_entry_id = transfer_entry.id;
|
let mut last_entry_id = transfer_entry.id;
|
||||||
|
|
||||||
// 2) Create and register the vote account
|
// 2) Create and register the vote account
|
||||||
let vote_account = Keypair::new();
|
let rpc_client = RpcClient::new_from_socket(signer);
|
||||||
|
|
||||||
|
let msg = "Registering a new node";
|
||||||
|
let sig = Signature::new(&active_keypair.sign(msg.as_bytes()).as_ref());
|
||||||
|
|
||||||
|
let params = json!([active_keypair.pubkey(), sig, msg.as_bytes()]);
|
||||||
|
let resp = RpcRequest::RegisterNode
|
||||||
|
.make_rpc_request(&rpc_client, 1, Some(params))
|
||||||
|
.unwrap();
|
||||||
|
let vote_account_id: Pubkey = serde_json::from_value(resp).unwrap();
|
||||||
|
|
||||||
let new_vote_account_tx =
|
let new_vote_account_tx =
|
||||||
Transaction::vote_account_new(active_keypair, vote_account.pubkey(), *last_tick_id, 1, 1);
|
Transaction::vote_account_new(active_keypair, vote_account_id, *last_tick_id, 1, 1);
|
||||||
let new_vote_account_entry = Entry::new(&last_entry_id, 0, 1, vec![new_vote_account_tx]);
|
let new_vote_account_entry = Entry::new(&last_entry_id, 0, 1, vec![new_vote_account_tx]);
|
||||||
last_entry_id = new_vote_account_entry.id;
|
last_entry_id = new_vote_account_entry.id;
|
||||||
|
|
||||||
// 3) Create vote entry
|
// 3) Create vote entry
|
||||||
let vote = Vote { tick_height: 1 };
|
let vote = Vote { tick_height: 1 };
|
||||||
let vote_tx = Transaction::vote_new(&vote_account, vote, *last_tick_id, 0);
|
let tx = Transaction::vote_new(&vote_account_id, vote, *last_tick_id, 0);
|
||||||
|
let msg = tx.get_sign_data();
|
||||||
|
let sig = Signature::new(&active_keypair.sign(&msg).as_ref());
|
||||||
|
let vote_tx = Transaction {
|
||||||
|
signatures: vec![sig],
|
||||||
|
account_keys: tx.account_keys,
|
||||||
|
last_id: tx.last_id,
|
||||||
|
fee: tx.fee,
|
||||||
|
program_ids: tx.program_ids,
|
||||||
|
instructions: tx.instructions,
|
||||||
|
};
|
||||||
let vote_entry = Entry::new(&last_entry_id, 0, 1, vec![vote_tx]);
|
let vote_entry = Entry::new(&last_entry_id, 0, 1, vec![vote_tx]);
|
||||||
last_entry_id = vote_entry.id;
|
last_entry_id = vote_entry.id;
|
||||||
|
|
||||||
|
@ -508,7 +531,7 @@ pub fn make_active_set_entries(
|
||||||
let mut txs = vec![transfer_entry, new_vote_account_entry, vote_entry];
|
let mut txs = vec![transfer_entry, new_vote_account_entry, vote_entry];
|
||||||
let empty_ticks = create_ticks(num_ending_ticks, last_entry_id);
|
let empty_ticks = create_ticks(num_ending_ticks, last_entry_id);
|
||||||
txs.extend(empty_ticks);
|
txs.extend(empty_ticks);
|
||||||
(txs, vote_account)
|
(txs, vote_account_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -520,15 +543,15 @@ mod tests {
|
||||||
DEFAULT_LEADER_ROTATION_INTERVAL, DEFAULT_SEED_ROTATION_INTERVAL,
|
DEFAULT_LEADER_ROTATION_INTERVAL, DEFAULT_SEED_ROTATION_INTERVAL,
|
||||||
};
|
};
|
||||||
use crate::mint::Mint;
|
use crate::mint::Mint;
|
||||||
|
use crate::rpc_request::RpcClient;
|
||||||
|
use crate::vote_stage::create_new_signed_vote_transaction;
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::hash::Hash;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::transaction::Transaction;
|
|
||||||
use solana_sdk::vote_program::Vote;
|
|
||||||
use solana_sdk::vote_transaction::VoteTransaction;
|
|
||||||
use std::hash::Hash as StdHash;
|
use std::hash::Hash as StdHash;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
fn to_hashset_owned<T>(slice: &[T]) -> HashSet<T>
|
fn to_hashset_owned<T>(slice: &[T]) -> HashSet<T>
|
||||||
where
|
where
|
||||||
|
@ -537,12 +560,16 @@ mod tests {
|
||||||
HashSet::from_iter(slice.iter().cloned())
|
HashSet::from_iter(slice.iter().cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_vote(vote_account: &Keypair, bank: &Bank, height: u64, last_id: Hash) {
|
fn push_vote(
|
||||||
let vote = Vote {
|
keypair: &Arc<Keypair>,
|
||||||
tick_height: height,
|
vote_account: &Pubkey,
|
||||||
};
|
bank: &Bank,
|
||||||
|
height: u64,
|
||||||
let new_vote_tx = Transaction::vote_new(vote_account, vote, last_id, 0);
|
last_id: Hash,
|
||||||
|
rpc_client: &RpcClient,
|
||||||
|
) {
|
||||||
|
let new_vote_tx =
|
||||||
|
create_new_signed_vote_transaction(&last_id, keypair, height, vote_account, rpc_client);
|
||||||
|
|
||||||
bank.process_transaction(&new_vote_tx).unwrap();
|
bank.process_transaction(&new_vote_tx).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -581,6 +608,8 @@ mod tests {
|
||||||
.last()
|
.last()
|
||||||
.expect("Mint should not create empty genesis entries")
|
.expect("Mint should not create empty genesis entries")
|
||||||
.id;
|
.id;
|
||||||
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
|
let rpc_client = RpcClient::new_from_socket(signer);
|
||||||
for i in 0..num_validators {
|
for i in 0..num_validators {
|
||||||
let new_validator = Keypair::new();
|
let new_validator = Keypair::new();
|
||||||
let new_pubkey = new_validator.pubkey();
|
let new_pubkey = new_validator.pubkey();
|
||||||
|
@ -600,11 +629,19 @@ mod tests {
|
||||||
&bank,
|
&bank,
|
||||||
num_vote_account_tokens as u64,
|
num_vote_account_tokens as u64,
|
||||||
mint.last_id(),
|
mint.last_id(),
|
||||||
|
&rpc_client,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// Vote to make the validator part of the active set for the entire test
|
// Vote to make the validator part of the active set for the entire test
|
||||||
// (we made the active_window_length large enough at the beginning of the test)
|
// (we made the active_window_length large enough at the beginning of the test)
|
||||||
push_vote(&new_vote_account, &bank, 1, mint.last_id());
|
push_vote(
|
||||||
|
&Arc::new(new_validator),
|
||||||
|
&new_vote_account,
|
||||||
|
&bank,
|
||||||
|
1,
|
||||||
|
mint.last_id(),
|
||||||
|
&rpc_client,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The scheduled leader during the bootstrapping period (assuming a seed + schedule
|
// The scheduled leader during the bootstrapping period (assuming a seed + schedule
|
||||||
|
@ -681,6 +718,7 @@ mod tests {
|
||||||
Some((current_leader, slot))
|
Some((current_leader, slot))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -700,6 +738,8 @@ mod tests {
|
||||||
let start_height = 3;
|
let start_height = 3;
|
||||||
let num_old_ids = 20;
|
let num_old_ids = 20;
|
||||||
let mut old_ids = HashSet::new();
|
let mut old_ids = HashSet::new();
|
||||||
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
|
let rpc_client = RpcClient::new_from_socket(signer);
|
||||||
for _ in 0..num_old_ids {
|
for _ in 0..num_old_ids {
|
||||||
let new_keypair = Keypair::new();
|
let new_keypair = Keypair::new();
|
||||||
let pk = new_keypair.pubkey();
|
let pk = new_keypair.pubkey();
|
||||||
|
@ -711,10 +751,17 @@ mod tests {
|
||||||
|
|
||||||
// Create a vote account
|
// Create a vote account
|
||||||
let new_vote_account =
|
let new_vote_account =
|
||||||
create_vote_account(&new_keypair, &bank, 1, mint.last_id()).unwrap();
|
create_vote_account(&new_keypair, &bank, 1, mint.last_id(), &rpc_client).unwrap();
|
||||||
|
|
||||||
// Push a vote for the account
|
// Push a vote for the account
|
||||||
push_vote(&new_vote_account, &bank, start_height, mint.last_id());
|
push_vote(
|
||||||
|
&Arc::new(new_keypair),
|
||||||
|
&new_vote_account,
|
||||||
|
&bank,
|
||||||
|
start_height,
|
||||||
|
mint.last_id(),
|
||||||
|
&rpc_client,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert a bunch of votes at height "start_height + active_window_length"
|
// Insert a bunch of votes at height "start_height + active_window_length"
|
||||||
|
@ -730,13 +777,15 @@ mod tests {
|
||||||
|
|
||||||
// Create a vote account
|
// Create a vote account
|
||||||
let new_vote_account =
|
let new_vote_account =
|
||||||
create_vote_account(&new_keypair, &bank, 1, mint.last_id()).unwrap();
|
create_vote_account(&new_keypair, &bank, 1, mint.last_id(), &rpc_client).unwrap();
|
||||||
|
|
||||||
push_vote(
|
push_vote(
|
||||||
|
&Arc::new(new_keypair),
|
||||||
&new_vote_account,
|
&new_vote_account,
|
||||||
&bank,
|
&bank,
|
||||||
start_height + active_window_length,
|
start_height + active_window_length,
|
||||||
mint.last_id(),
|
mint.last_id(),
|
||||||
|
&rpc_client,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -755,6 +804,7 @@ mod tests {
|
||||||
let result =
|
let result =
|
||||||
leader_scheduler.get_active_set(2 * active_window_length + start_height, &bank);
|
leader_scheduler.get_active_set(2 * active_window_length + start_height, &bank);
|
||||||
assert!(result.is_empty());
|
assert!(result.is_empty());
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -997,6 +1047,8 @@ mod tests {
|
||||||
.last()
|
.last()
|
||||||
.expect("Mint should not create empty genesis entries")
|
.expect("Mint should not create empty genesis entries")
|
||||||
.id;
|
.id;
|
||||||
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
|
let rpc_client = RpcClient::new_from_socket(signer);
|
||||||
for i in 0..num_validators {
|
for i in 0..num_validators {
|
||||||
let new_validator = Keypair::new();
|
let new_validator = Keypair::new();
|
||||||
let new_pubkey = new_validator.pubkey();
|
let new_pubkey = new_validator.pubkey();
|
||||||
|
@ -1016,15 +1068,18 @@ mod tests {
|
||||||
&bank,
|
&bank,
|
||||||
num_vote_account_tokens as u64,
|
num_vote_account_tokens as u64,
|
||||||
mint.last_id(),
|
mint.last_id(),
|
||||||
|
&rpc_client,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Vote at height i * active_window_length for validator i
|
// Vote at height i * active_window_length for validator i
|
||||||
push_vote(
|
push_vote(
|
||||||
|
&Arc::new(new_validator),
|
||||||
&new_vote_account,
|
&new_vote_account,
|
||||||
&bank,
|
&bank,
|
||||||
i * active_window_length + bootstrap_height,
|
i * active_window_length + bootstrap_height,
|
||||||
mint.last_id(),
|
mint.last_id(),
|
||||||
|
&rpc_client,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1042,6 +1097,7 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(vec![expected], *result);
|
assert_eq!(vec![expected], *result);
|
||||||
}
|
}
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1062,22 +1118,28 @@ mod tests {
|
||||||
// window
|
// window
|
||||||
let initial_vote_height = 1;
|
let initial_vote_height = 1;
|
||||||
|
|
||||||
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
|
let rpc_client = RpcClient::new_from_socket(signer);
|
||||||
// Create a vote account
|
// Create a vote account
|
||||||
let new_vote_account =
|
let new_vote_account =
|
||||||
create_vote_account(&leader_keypair, &bank, 1, mint.last_id()).unwrap();
|
create_vote_account(&leader_keypair, &bank, 1, mint.last_id(), &rpc_client).unwrap();
|
||||||
|
let leader_keypair = Arc::new(leader_keypair);
|
||||||
// Vote twice
|
// Vote twice
|
||||||
push_vote(
|
push_vote(
|
||||||
|
&leader_keypair,
|
||||||
&new_vote_account,
|
&new_vote_account,
|
||||||
&bank,
|
&bank,
|
||||||
initial_vote_height,
|
initial_vote_height,
|
||||||
mint.last_id(),
|
mint.last_id(),
|
||||||
|
&rpc_client,
|
||||||
);
|
);
|
||||||
push_vote(
|
push_vote(
|
||||||
|
&leader_keypair,
|
||||||
&new_vote_account,
|
&new_vote_account,
|
||||||
&bank,
|
&bank,
|
||||||
initial_vote_height + 1,
|
initial_vote_height + 1,
|
||||||
mint.last_id(),
|
mint.last_id(),
|
||||||
|
&rpc_client,
|
||||||
);
|
);
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
|
@ -1086,6 +1148,7 @@ mod tests {
|
||||||
let result =
|
let result =
|
||||||
leader_scheduler.get_active_set(initial_vote_height + active_window_length + 1, &bank);
|
leader_scheduler.get_active_set(initial_vote_height + active_window_length + 1, &bank);
|
||||||
assert!(result.is_empty());
|
assert!(result.is_empty());
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1206,17 +1269,22 @@ mod tests {
|
||||||
// Create and add validator to the active set
|
// Create and add validator to the active set
|
||||||
let validator_keypair = Keypair::new();
|
let validator_keypair = Keypair::new();
|
||||||
let validator_id = validator_keypair.pubkey();
|
let validator_id = validator_keypair.pubkey();
|
||||||
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
|
let rpc_client = RpcClient::new_from_socket(signer);
|
||||||
if add_validator {
|
if add_validator {
|
||||||
bank.transfer(5, &mint.keypair(), validator_id, last_id)
|
bank.transfer(5, &mint.keypair(), validator_id, last_id)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// Create a vote account
|
// Create a vote account
|
||||||
let new_vote_account =
|
let new_vote_account =
|
||||||
create_vote_account(&validator_keypair, &bank, 1, mint.last_id()).unwrap();
|
create_vote_account(&validator_keypair, &bank, 1, mint.last_id(), &rpc_client)
|
||||||
|
.unwrap();
|
||||||
push_vote(
|
push_vote(
|
||||||
|
&Arc::new(validator_keypair),
|
||||||
&new_vote_account,
|
&new_vote_account,
|
||||||
&bank,
|
&bank,
|
||||||
initial_vote_height,
|
initial_vote_height,
|
||||||
mint.last_id(),
|
mint.last_id(),
|
||||||
|
&rpc_client,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1249,15 +1317,18 @@ mod tests {
|
||||||
&bank,
|
&bank,
|
||||||
vote_account_tokens,
|
vote_account_tokens,
|
||||||
mint.last_id(),
|
mint.last_id(),
|
||||||
|
&rpc_client,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Add leader to the active set
|
// Add leader to the active set
|
||||||
push_vote(
|
push_vote(
|
||||||
|
&Arc::new(bootstrap_leader_keypair),
|
||||||
&new_vote_account,
|
&new_vote_account,
|
||||||
&bank,
|
&bank,
|
||||||
initial_vote_height,
|
initial_vote_height,
|
||||||
mint.last_id(),
|
mint.last_id(),
|
||||||
|
&rpc_client,
|
||||||
);
|
);
|
||||||
|
|
||||||
leader_scheduler.generate_schedule(bootstrap_height, &bank);
|
leader_scheduler.generate_schedule(bootstrap_height, &bank);
|
||||||
|
@ -1269,6 +1340,7 @@ mod tests {
|
||||||
} else {
|
} else {
|
||||||
assert!(leader_scheduler.leader_schedule[0] == bootstrap_leader_id);
|
assert!(leader_scheduler.leader_schedule[0] == bootstrap_leader_id);
|
||||||
}
|
}
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1373,27 +1445,39 @@ mod tests {
|
||||||
// Create a vote account for the validator
|
// Create a vote account for the validator
|
||||||
bank.transfer(5, &mint.keypair(), validator_id, last_id)
|
bank.transfer(5, &mint.keypair(), validator_id, last_id)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
|
let rpc_client = RpcClient::new_from_socket(signer);
|
||||||
let new_validator_vote_account =
|
let new_validator_vote_account =
|
||||||
create_vote_account(&validator_keypair, &bank, 1, mint.last_id()).unwrap();
|
create_vote_account(&validator_keypair, &bank, 1, mint.last_id(), &rpc_client).unwrap();
|
||||||
push_vote(
|
push_vote(
|
||||||
|
&Arc::new(validator_keypair),
|
||||||
&new_validator_vote_account,
|
&new_validator_vote_account,
|
||||||
&bank,
|
&bank,
|
||||||
initial_vote_height,
|
initial_vote_height,
|
||||||
mint.last_id(),
|
mint.last_id(),
|
||||||
|
&rpc_client,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Create a vote account for the leader
|
// Create a vote account for the leader
|
||||||
bank.transfer(5, &mint.keypair(), bootstrap_leader_id, last_id)
|
bank.transfer(5, &mint.keypair(), bootstrap_leader_id, last_id)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let new_leader_vote_account =
|
let new_leader_vote_account = create_vote_account(
|
||||||
create_vote_account(&bootstrap_leader_keypair, &bank, 1, mint.last_id()).unwrap();
|
&bootstrap_leader_keypair,
|
||||||
|
&bank,
|
||||||
|
1,
|
||||||
|
mint.last_id(),
|
||||||
|
&rpc_client,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Add leader to the active set
|
// Add leader to the active set
|
||||||
push_vote(
|
push_vote(
|
||||||
|
&Arc::new(bootstrap_leader_keypair),
|
||||||
&new_leader_vote_account,
|
&new_leader_vote_account,
|
||||||
&bank,
|
&bank,
|
||||||
initial_vote_height,
|
initial_vote_height,
|
||||||
mint.last_id(),
|
mint.last_id(),
|
||||||
|
&rpc_client,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Generate the schedule
|
// Generate the schedule
|
||||||
|
@ -1452,5 +1536,6 @@ mod tests {
|
||||||
.max_height_for_leader(bootstrap_height + 2 * seed_rotation_interval + 1),
|
.max_height_for_leader(bootstrap_height + 2 * seed_rotation_interval + 1),
|
||||||
None
|
None
|
||||||
);
|
);
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -734,7 +734,7 @@ mod tests {
|
||||||
use crate::packet::{to_blobs, BLOB_DATA_SIZE, PACKET_DATA_SIZE};
|
use crate::packet::{to_blobs, BLOB_DATA_SIZE, PACKET_DATA_SIZE};
|
||||||
use bincode::{deserialize, serialized_size};
|
use bincode::{deserialize, serialized_size};
|
||||||
use solana_sdk::hash::hash;
|
use solana_sdk::hash::hash;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
use solana_sdk::vote_program::Vote;
|
use solana_sdk::vote_program::Vote;
|
||||||
use std;
|
use std;
|
||||||
|
@ -760,7 +760,17 @@ mod tests {
|
||||||
let one = hash(&zero.as_ref());
|
let one = hash(&zero.as_ref());
|
||||||
let keypair = Keypair::new();
|
let keypair = Keypair::new();
|
||||||
let vote_account = Keypair::new();
|
let vote_account = Keypair::new();
|
||||||
let tx0 = Transaction::vote_new(&vote_account, Vote { tick_height: 1 }, one, 1);
|
let tx = Transaction::vote_new(&vote_account.pubkey(), Vote { tick_height: 1 }, one, 1);
|
||||||
|
let msg = tx.get_sign_data();
|
||||||
|
let sig = Signature::new(&vote_account.sign(&msg).as_ref());
|
||||||
|
let tx0 = Transaction {
|
||||||
|
signatures: vec![sig],
|
||||||
|
account_keys: tx.account_keys,
|
||||||
|
last_id: tx.last_id,
|
||||||
|
fee: tx.fee,
|
||||||
|
program_ids: tx.program_ids,
|
||||||
|
instructions: tx.instructions,
|
||||||
|
};
|
||||||
let tx1 = Transaction::budget_new_timestamp(
|
let tx1 = Transaction::budget_new_timestamp(
|
||||||
&keypair,
|
&keypair,
|
||||||
keypair.pubkey(),
|
keypair.pubkey(),
|
||||||
|
@ -808,7 +818,17 @@ mod tests {
|
||||||
let next_id = hash(&id.as_ref());
|
let next_id = hash(&id.as_ref());
|
||||||
let keypair = Keypair::new();
|
let keypair = Keypair::new();
|
||||||
let vote_account = Keypair::new();
|
let vote_account = Keypair::new();
|
||||||
let tx_small = Transaction::vote_new(&vote_account, Vote { tick_height: 1 }, next_id, 2);
|
let tx = Transaction::vote_new(&vote_account.pubkey(), Vote { tick_height: 1 }, next_id, 2);
|
||||||
|
let msg = tx.get_sign_data();
|
||||||
|
let sig = Signature::new(&vote_account.sign(&msg).as_ref());
|
||||||
|
let tx_small = Transaction {
|
||||||
|
signatures: vec![sig],
|
||||||
|
account_keys: tx.account_keys,
|
||||||
|
last_id: tx.last_id,
|
||||||
|
fee: tx.fee,
|
||||||
|
program_ids: tx.program_ids,
|
||||||
|
instructions: tx.instructions,
|
||||||
|
};
|
||||||
let tx_large = Transaction::budget_new(&keypair, keypair.pubkey(), 1, next_id);
|
let tx_large = Transaction::budget_new(&keypair, keypair.pubkey(), 1, next_id);
|
||||||
|
|
||||||
let tx_small_size = serialized_size(&tx_small).unwrap() as usize;
|
let tx_small_size = serialized_size(&tx_small).unwrap() as usize;
|
||||||
|
|
|
@ -93,6 +93,7 @@ use solana_jsonrpc_http_server as jsonrpc_http_server;
|
||||||
extern crate solana_jsonrpc_macros as jsonrpc_macros;
|
extern crate solana_jsonrpc_macros as jsonrpc_macros;
|
||||||
use solana_jsonrpc_pubsub as jsonrpc_pubsub;
|
use solana_jsonrpc_pubsub as jsonrpc_pubsub;
|
||||||
use solana_jsonrpc_ws_server as jsonrpc_ws_server;
|
use solana_jsonrpc_ws_server as jsonrpc_ws_server;
|
||||||
|
use solana_vote_signer;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -9,14 +9,16 @@ use solana_sdk::hash::Hash;
|
||||||
use crate::ledger::Block;
|
use crate::ledger::Block;
|
||||||
use crate::packet::BlobError;
|
use crate::packet::BlobError;
|
||||||
use crate::result::{Error, Result};
|
use crate::result::{Error, Result};
|
||||||
|
use crate::rpc_request::RpcClient;
|
||||||
use crate::service::Service;
|
use crate::service::Service;
|
||||||
use crate::streamer::{responder, BlobSender};
|
use crate::streamer::{responder, BlobSender};
|
||||||
use crate::vote_stage::send_validator_vote;
|
use crate::vote_stage::send_validator_vote;
|
||||||
use log::Level;
|
use log::Level;
|
||||||
use solana_metrics::{influxdb, submit};
|
use solana_metrics::{influxdb, submit};
|
||||||
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::timing::duration_as_ms;
|
use solana_sdk::timing::duration_as_ms;
|
||||||
use std::net::UdpSocket;
|
use std::net::{SocketAddr, UdpSocket};
|
||||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
use std::sync::mpsc::RecvTimeoutError;
|
use std::sync::mpsc::RecvTimeoutError;
|
||||||
|
@ -58,12 +60,14 @@ pub struct ReplayStage {
|
||||||
|
|
||||||
impl ReplayStage {
|
impl ReplayStage {
|
||||||
/// Process entry blobs, already in order
|
/// Process entry blobs, already in order
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn process_entries(
|
fn process_entries(
|
||||||
bank: &Arc<Bank>,
|
bank: &Arc<Bank>,
|
||||||
cluster_info: &Arc<RwLock<ClusterInfo>>,
|
cluster_info: &Arc<RwLock<ClusterInfo>>,
|
||||||
window_receiver: &EntryReceiver,
|
window_receiver: &EntryReceiver,
|
||||||
keypair: &Arc<Keypair>,
|
keypair: &Arc<Keypair>,
|
||||||
vote_account_keypair: &Arc<Keypair>,
|
vote_account_id: &Pubkey,
|
||||||
|
vote_signer_rpc: &RpcClient,
|
||||||
vote_blob_sender: Option<&BlobSender>,
|
vote_blob_sender: Option<&BlobSender>,
|
||||||
ledger_entry_sender: &EntrySender,
|
ledger_entry_sender: &EntrySender,
|
||||||
entry_height: &mut u64,
|
entry_height: &mut u64,
|
||||||
|
@ -137,8 +141,15 @@ impl ReplayStage {
|
||||||
|
|
||||||
if 0 == num_ticks_to_next_vote {
|
if 0 == num_ticks_to_next_vote {
|
||||||
if let Some(sender) = vote_blob_sender {
|
if let Some(sender) = vote_blob_sender {
|
||||||
send_validator_vote(bank, vote_account_keypair, &cluster_info, sender)
|
send_validator_vote(
|
||||||
.unwrap();
|
bank,
|
||||||
|
&keypair,
|
||||||
|
&vote_account_id,
|
||||||
|
vote_signer_rpc,
|
||||||
|
&cluster_info,
|
||||||
|
sender,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let (scheduled_leader, _) = bank
|
let (scheduled_leader, _) = bank
|
||||||
|
@ -192,7 +203,8 @@ impl ReplayStage {
|
||||||
#[allow(clippy::new_ret_no_self)]
|
#[allow(clippy::new_ret_no_self)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
keypair: Arc<Keypair>,
|
keypair: Arc<Keypair>,
|
||||||
vote_account_keypair: Arc<Keypair>,
|
vote_account_id: &Pubkey,
|
||||||
|
vote_signer_addr: &SocketAddr,
|
||||||
bank: Arc<Bank>,
|
bank: Arc<Bank>,
|
||||||
cluster_info: Arc<RwLock<ClusterInfo>>,
|
cluster_info: Arc<RwLock<ClusterInfo>>,
|
||||||
window_receiver: EntryReceiver,
|
window_receiver: EntryReceiver,
|
||||||
|
@ -206,7 +218,9 @@ impl ReplayStage {
|
||||||
let t_responder = responder("replay_stage", Arc::new(send), vote_blob_receiver);
|
let t_responder = responder("replay_stage", Arc::new(send), vote_blob_receiver);
|
||||||
|
|
||||||
let keypair = Arc::new(keypair);
|
let keypair = Arc::new(keypair);
|
||||||
|
let vote_account_id = *vote_account_id;
|
||||||
|
|
||||||
|
let rpc_client = RpcClient::new_from_socket(*vote_signer_addr);
|
||||||
let t_replay = Builder::new()
|
let t_replay = Builder::new()
|
||||||
.name("solana-replay-stage".to_string())
|
.name("solana-replay-stage".to_string())
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
|
@ -235,7 +249,8 @@ impl ReplayStage {
|
||||||
&cluster_info,
|
&cluster_info,
|
||||||
&window_receiver,
|
&window_receiver,
|
||||||
&keypair,
|
&keypair,
|
||||||
&vote_account_keypair,
|
&vote_account_id,
|
||||||
|
&rpc_client,
|
||||||
Some(&vote_blob_sender),
|
Some(&vote_blob_sender),
|
||||||
&ledger_entry_sender,
|
&ledger_entry_sender,
|
||||||
&mut entry_height_,
|
&mut entry_height_,
|
||||||
|
@ -282,14 +297,18 @@ mod test {
|
||||||
make_active_set_entries, LeaderScheduler, LeaderSchedulerConfig,
|
make_active_set_entries, LeaderScheduler, LeaderSchedulerConfig,
|
||||||
};
|
};
|
||||||
use crate::ledger::{create_ticks, create_tmp_sample_ledger};
|
use crate::ledger::{create_ticks, create_tmp_sample_ledger};
|
||||||
|
|
||||||
|
use crate::create_vote_account::*;
|
||||||
use crate::packet::BlobError;
|
use crate::packet::BlobError;
|
||||||
use crate::replay_stage::{ReplayStage, ReplayStageReturnType};
|
use crate::replay_stage::{ReplayStage, ReplayStageReturnType};
|
||||||
use crate::result::Error;
|
use crate::result::Error;
|
||||||
|
use crate::rpc_request::RpcClient;
|
||||||
use crate::service::Service;
|
use crate::service::Service;
|
||||||
use crate::vote_stage::send_validator_vote;
|
use crate::vote_stage::send_validator_vote;
|
||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::hash::Hash;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use std::fs::remove_dir_all;
|
use std::fs::remove_dir_all;
|
||||||
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
@ -324,8 +343,9 @@ mod test {
|
||||||
// Write two entries to the ledger so that the validator is in the active set:
|
// Write two entries to the ledger so that the validator is in the active set:
|
||||||
// 1) Give the validator a nonzero number of tokens 2) A vote from the validator .
|
// 1) Give the validator a nonzero number of tokens 2) A vote from the validator .
|
||||||
// This will cause leader rotation after the bootstrap height
|
// This will cause leader rotation after the bootstrap height
|
||||||
let (active_set_entries, vote_account_keypair) =
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
make_active_set_entries(&my_keypair, &mint.keypair(), &last_id, &last_id, 0);
|
let (active_set_entries, vote_account_id) =
|
||||||
|
make_active_set_entries(&my_keypair, signer, &mint.keypair(), &last_id, &last_id, 0);
|
||||||
last_id = active_set_entries.last().unwrap().id;
|
last_id = active_set_entries.last().unwrap().id;
|
||||||
let initial_tick_height = genesis_entries
|
let initial_tick_height = genesis_entries
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -370,7 +390,8 @@ mod test {
|
||||||
let exit = Arc::new(AtomicBool::new(false));
|
let exit = Arc::new(AtomicBool::new(false));
|
||||||
let (replay_stage, ledger_writer_recv) = ReplayStage::new(
|
let (replay_stage, ledger_writer_recv) = ReplayStage::new(
|
||||||
Arc::new(my_keypair),
|
Arc::new(my_keypair),
|
||||||
Arc::new(vote_account_keypair),
|
&vote_account_id,
|
||||||
|
&signer,
|
||||||
Arc::new(bank),
|
Arc::new(bank),
|
||||||
Arc::new(RwLock::new(cluster_info_me)),
|
Arc::new(RwLock::new(cluster_info_me)),
|
||||||
entry_receiver,
|
entry_receiver,
|
||||||
|
@ -421,6 +442,8 @@ mod test {
|
||||||
&entries_to_send[..leader_rotation_index + 1]
|
&entries_to_send[..leader_rotation_index + 1]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
|
|
||||||
assert_eq!(exit.load(Ordering::Relaxed), true);
|
assert_eq!(exit.load(Ordering::Relaxed), true);
|
||||||
|
|
||||||
let _ignored = remove_dir_all(&my_ledger_path);
|
let _ignored = remove_dir_all(&my_ledger_path);
|
||||||
|
@ -456,13 +479,16 @@ mod test {
|
||||||
let cluster_info_me = Arc::new(RwLock::new(ClusterInfo::new(my_node.info.clone())));
|
let cluster_info_me = Arc::new(RwLock::new(ClusterInfo::new(my_node.info.clone())));
|
||||||
|
|
||||||
// Set up the replay stage
|
// Set up the replay stage
|
||||||
let vote_account_keypair = Arc::new(Keypair::new());
|
let vote_account_id = Keypair::new().pubkey();
|
||||||
let bank = Arc::new(bank);
|
let bank = Arc::new(bank);
|
||||||
let (entry_sender, entry_receiver) = channel();
|
let (entry_sender, entry_receiver) = channel();
|
||||||
let exit = Arc::new(AtomicBool::new(false));
|
let exit = Arc::new(AtomicBool::new(false));
|
||||||
|
let signer = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0);
|
||||||
|
let my_keypair = Arc::new(my_keypair);
|
||||||
let (replay_stage, ledger_writer_recv) = ReplayStage::new(
|
let (replay_stage, ledger_writer_recv) = ReplayStage::new(
|
||||||
Arc::new(my_keypair),
|
my_keypair.clone(),
|
||||||
vote_account_keypair.clone(),
|
&vote_account_id,
|
||||||
|
&signer,
|
||||||
bank.clone(),
|
bank.clone(),
|
||||||
cluster_info_me.clone(),
|
cluster_info_me.clone(),
|
||||||
entry_receiver,
|
entry_receiver,
|
||||||
|
@ -474,8 +500,14 @@ mod test {
|
||||||
// Vote sender should error because no leader contact info is found in the
|
// Vote sender should error because no leader contact info is found in the
|
||||||
// ClusterInfo
|
// ClusterInfo
|
||||||
let (mock_sender, _mock_receiver) = channel();
|
let (mock_sender, _mock_receiver) = channel();
|
||||||
let _vote_err =
|
let _vote_err = send_validator_vote(
|
||||||
send_validator_vote(&bank, &vote_account_keypair, &cluster_info_me, &mock_sender);
|
&bank,
|
||||||
|
&my_keypair,
|
||||||
|
&vote_account_id,
|
||||||
|
&RpcClient::new_from_socket(signer),
|
||||||
|
&cluster_info_me,
|
||||||
|
&mock_sender,
|
||||||
|
);
|
||||||
|
|
||||||
// Send ReplayStage an entry, should see it on the ledger writer receiver
|
// Send ReplayStage an entry, should see it on the ledger writer receiver
|
||||||
let next_tick = create_ticks(
|
let next_tick = create_ticks(
|
||||||
|
@ -527,8 +559,9 @@ mod test {
|
||||||
// Write two entries to the ledger so that the validator is in the active set:
|
// Write two entries to the ledger so that the validator is in the active set:
|
||||||
// 1) Give the validator a nonzero number of tokens 2) A vote from the validator.
|
// 1) Give the validator a nonzero number of tokens 2) A vote from the validator.
|
||||||
// This will cause leader rotation after the bootstrap height
|
// This will cause leader rotation after the bootstrap height
|
||||||
let (active_set_entries, vote_account_keypair) =
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
make_active_set_entries(&my_keypair, &mint.keypair(), &last_id, &last_id, 0);
|
let (active_set_entries, vote_account_id) =
|
||||||
|
make_active_set_entries(&my_keypair, signer, &mint.keypair(), &last_id, &last_id, 0);
|
||||||
last_id = active_set_entries.last().unwrap().id;
|
last_id = active_set_entries.last().unwrap().id;
|
||||||
let initial_tick_height = genesis_entries
|
let initial_tick_height = genesis_entries
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -572,13 +605,15 @@ mod test {
|
||||||
let cluster_info_me = Arc::new(RwLock::new(ClusterInfo::new(my_node.info.clone())));
|
let cluster_info_me = Arc::new(RwLock::new(ClusterInfo::new(my_node.info.clone())));
|
||||||
|
|
||||||
// Set up the replay stage
|
// Set up the replay stage
|
||||||
let vote_account_keypair = Arc::new(vote_account_keypair);
|
let vote_account_id = Arc::new(vote_account_id);
|
||||||
let bank = Arc::new(bank);
|
let bank = Arc::new(bank);
|
||||||
let (entry_sender, entry_receiver) = channel();
|
let (entry_sender, entry_receiver) = channel();
|
||||||
let exit = Arc::new(AtomicBool::new(false));
|
let exit = Arc::new(AtomicBool::new(false));
|
||||||
|
let my_keypair = Arc::new(my_keypair);
|
||||||
let (replay_stage, ledger_writer_recv) = ReplayStage::new(
|
let (replay_stage, ledger_writer_recv) = ReplayStage::new(
|
||||||
Arc::new(my_keypair),
|
my_keypair.clone(),
|
||||||
vote_account_keypair.clone(),
|
&vote_account_id,
|
||||||
|
&signer,
|
||||||
bank.clone(),
|
bank.clone(),
|
||||||
cluster_info_me.clone(),
|
cluster_info_me.clone(),
|
||||||
entry_receiver,
|
entry_receiver,
|
||||||
|
@ -590,8 +625,14 @@ mod test {
|
||||||
// Vote sender should error because no leader contact info is found in the
|
// Vote sender should error because no leader contact info is found in the
|
||||||
// ClusterInfo
|
// ClusterInfo
|
||||||
let (mock_sender, _mock_receiver) = channel();
|
let (mock_sender, _mock_receiver) = channel();
|
||||||
let _vote_err =
|
let _vote_err = send_validator_vote(
|
||||||
send_validator_vote(&bank, &vote_account_keypair, &cluster_info_me, &mock_sender);
|
&bank,
|
||||||
|
&my_keypair,
|
||||||
|
&vote_account_id,
|
||||||
|
&RpcClient::new_from_socket(signer),
|
||||||
|
&cluster_info_me,
|
||||||
|
&mock_sender,
|
||||||
|
);
|
||||||
|
|
||||||
// Send enough ticks to trigger leader rotation
|
// Send enough ticks to trigger leader rotation
|
||||||
let total_entries_to_send = (bootstrap_height - initial_tick_height) as usize;
|
let total_entries_to_send = (bootstrap_height - initial_tick_height) as usize;
|
||||||
|
@ -631,7 +672,7 @@ mod test {
|
||||||
)),
|
)),
|
||||||
replay_stage.join().expect("replay stage join")
|
replay_stage.join().expect("replay stage join")
|
||||||
);
|
);
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
assert_eq!(exit.load(Ordering::Relaxed), true);
|
assert_eq!(exit.load(Ordering::Relaxed), true);
|
||||||
let _ignored = remove_dir_all(&my_ledger_path);
|
let _ignored = remove_dir_all(&my_ledger_path);
|
||||||
}
|
}
|
||||||
|
@ -671,12 +712,16 @@ mod test {
|
||||||
.send(entries.clone())
|
.send(entries.clone())
|
||||||
.expect("Expected to err out");
|
.expect("Expected to err out");
|
||||||
|
|
||||||
|
let signer = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0);
|
||||||
|
let rpc_client = RpcClient::new_from_socket(signer);
|
||||||
|
let my_keypair = Arc::new(my_keypair);
|
||||||
let res = ReplayStage::process_entries(
|
let res = ReplayStage::process_entries(
|
||||||
&Arc::new(Bank::default()),
|
&Arc::new(Bank::default()),
|
||||||
&cluster_info_me,
|
&cluster_info_me,
|
||||||
&entry_receiver,
|
&entry_receiver,
|
||||||
&Arc::new(my_keypair),
|
&my_keypair,
|
||||||
&Arc::new(vote_keypair),
|
&vote_keypair.pubkey(),
|
||||||
|
&rpc_client,
|
||||||
None,
|
None,
|
||||||
&ledger_entry_sender,
|
&ledger_entry_sender,
|
||||||
&mut entry_height,
|
&mut entry_height,
|
||||||
|
@ -702,7 +747,8 @@ mod test {
|
||||||
&cluster_info_me,
|
&cluster_info_me,
|
||||||
&entry_receiver,
|
&entry_receiver,
|
||||||
&Arc::new(Keypair::new()),
|
&Arc::new(Keypair::new()),
|
||||||
&Arc::new(Keypair::new()),
|
&Keypair::new().pubkey(),
|
||||||
|
&rpc_client,
|
||||||
None,
|
None,
|
||||||
&ledger_entry_sender,
|
&ledger_entry_sender,
|
||||||
&mut entry_height,
|
&mut entry_height,
|
||||||
|
|
|
@ -689,7 +689,8 @@ mod tests {
|
||||||
let entry_height = alice.create_entries().len() as u64;
|
let entry_height = alice.create_entries().len() as u64;
|
||||||
let server = Fullnode::new_with_bank(
|
let server = Fullnode::new_with_bank(
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
vote_account_keypair,
|
&vote_account_keypair.pubkey(),
|
||||||
|
&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
|
||||||
bank,
|
bank,
|
||||||
None,
|
None,
|
||||||
entry_height,
|
entry_height,
|
||||||
|
|
|
@ -485,7 +485,17 @@ mod tests {
|
||||||
tick_height: 123456,
|
tick_height: 123456,
|
||||||
};
|
};
|
||||||
let keypair = Keypair::new();
|
let keypair = Keypair::new();
|
||||||
let vote_tx = VoteTransaction::vote_new(&keypair, vote, Hash::default(), 1);
|
let tx = Transaction::vote_new(&keypair.pubkey(), vote, Hash::default(), 1);
|
||||||
|
let msg = tx.get_sign_data();
|
||||||
|
let sig = Signature::new(&keypair.sign(&msg).as_ref());
|
||||||
|
let vote_tx = Transaction {
|
||||||
|
signatures: vec![sig],
|
||||||
|
account_keys: tx.account_keys,
|
||||||
|
last_id: tx.last_id,
|
||||||
|
fee: tx.fee,
|
||||||
|
program_ids: tx.program_ids,
|
||||||
|
instructions: tx.instructions,
|
||||||
|
};
|
||||||
vote_txs.push(vote_tx);
|
vote_txs.push(vote_tx);
|
||||||
let vote_entries = vec![Entry::new(&Hash::default(), 0, 1, vote_txs)];
|
let vote_entries = vec![Entry::new(&Hash::default(), 0, 1, vote_txs)];
|
||||||
storage_entry_sender.send(vote_entries).unwrap();
|
storage_entry_sender.send(vote_entries).unwrap();
|
||||||
|
|
|
@ -438,6 +438,7 @@ mod tests {
|
||||||
use solana_sdk::vote_program::VoteProgram;
|
use solana_sdk::vote_program::VoteProgram;
|
||||||
use solana_sdk::vote_transaction::VoteTransaction;
|
use solana_sdk::vote_transaction::VoteTransaction;
|
||||||
use std::fs::remove_dir_all;
|
use std::fs::remove_dir_all;
|
||||||
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_thin_client() {
|
fn test_thin_client() {
|
||||||
|
@ -460,7 +461,8 @@ mod tests {
|
||||||
let last_id = bank.last_id();
|
let last_id = bank.last_id();
|
||||||
let server = Fullnode::new_with_bank(
|
let server = Fullnode::new_with_bank(
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
vote_account_keypair,
|
&vote_account_keypair.pubkey(),
|
||||||
|
&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
|
||||||
bank,
|
bank,
|
||||||
None,
|
None,
|
||||||
entry_height,
|
entry_height,
|
||||||
|
@ -514,7 +516,8 @@ mod tests {
|
||||||
let last_id = bank.last_id();
|
let last_id = bank.last_id();
|
||||||
let server = Fullnode::new_with_bank(
|
let server = Fullnode::new_with_bank(
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
vote_account_keypair,
|
&vote_account_keypair.pubkey(),
|
||||||
|
&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
|
||||||
bank,
|
bank,
|
||||||
None,
|
None,
|
||||||
0,
|
0,
|
||||||
|
@ -573,7 +576,8 @@ mod tests {
|
||||||
let last_id = bank.last_id();
|
let last_id = bank.last_id();
|
||||||
let server = Fullnode::new_with_bank(
|
let server = Fullnode::new_with_bank(
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
vote_account_keypair,
|
&vote_account_keypair.pubkey(),
|
||||||
|
&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
|
||||||
bank,
|
bank,
|
||||||
None,
|
None,
|
||||||
entry_height,
|
entry_height,
|
||||||
|
@ -619,7 +623,8 @@ mod tests {
|
||||||
let leader_vote_account_keypair = Arc::new(Keypair::new());
|
let leader_vote_account_keypair = Arc::new(Keypair::new());
|
||||||
let server = Fullnode::new_with_bank(
|
let server = Fullnode::new_with_bank(
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
leader_vote_account_keypair.clone(),
|
&leader_vote_account_keypair.pubkey(),
|
||||||
|
&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
|
||||||
bank,
|
bank,
|
||||||
None,
|
None,
|
||||||
entry_height,
|
entry_height,
|
||||||
|
@ -713,7 +718,8 @@ mod tests {
|
||||||
let entry_height = alice.create_entries().len() as u64;
|
let entry_height = alice.create_entries().len() as u64;
|
||||||
let server = Fullnode::new_with_bank(
|
let server = Fullnode::new_with_bank(
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
vote_account_keypair,
|
&vote_account_keypair.pubkey(),
|
||||||
|
&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
|
||||||
bank,
|
bank,
|
||||||
None,
|
None,
|
||||||
entry_height,
|
entry_height,
|
||||||
|
|
17
src/tvu.rs
17
src/tvu.rs
|
@ -21,8 +21,9 @@ use crate::retransmit_stage::RetransmitStage;
|
||||||
use crate::service::Service;
|
use crate::service::Service;
|
||||||
use crate::storage_stage::StorageStage;
|
use crate::storage_stage::StorageStage;
|
||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::hash::Hash;
|
||||||
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::signature::Keypair;
|
use solana_sdk::signature::Keypair;
|
||||||
use std::net::UdpSocket;
|
use std::net::{SocketAddr, UdpSocket};
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
@ -50,7 +51,7 @@ impl Tvu {
|
||||||
/// This service receives messages from a leader in the network and processes the transactions
|
/// This service receives messages from a leader in the network and processes the transactions
|
||||||
/// on the bank state.
|
/// on the bank state.
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `vote_account_keypair` - Vote key pair
|
/// * `vote_account_id` - Vote public key
|
||||||
/// * `bank` - The bank state.
|
/// * `bank` - The bank state.
|
||||||
/// * `entry_height` - Initial ledger height
|
/// * `entry_height` - Initial ledger height
|
||||||
/// * `last_entry_id` - Hash of the last entry
|
/// * `last_entry_id` - Hash of the last entry
|
||||||
|
@ -58,7 +59,8 @@ impl Tvu {
|
||||||
/// * `sockets` - My fetch, repair, and restransmit sockets
|
/// * `sockets` - My fetch, repair, and restransmit sockets
|
||||||
/// * `db_ledger` - the ledger itself
|
/// * `db_ledger` - the ledger itself
|
||||||
pub fn new(
|
pub fn new(
|
||||||
vote_account_keypair: Arc<Keypair>,
|
vote_account_id: &Pubkey,
|
||||||
|
vote_signer_addr: &SocketAddr,
|
||||||
bank: &Arc<Bank>,
|
bank: &Arc<Bank>,
|
||||||
entry_height: u64,
|
entry_height: u64,
|
||||||
last_entry_id: Hash,
|
last_entry_id: Hash,
|
||||||
|
@ -103,7 +105,8 @@ impl Tvu {
|
||||||
|
|
||||||
let (replay_stage, ledger_entry_receiver) = ReplayStage::new(
|
let (replay_stage, ledger_entry_receiver) = ReplayStage::new(
|
||||||
keypair.clone(),
|
keypair.clone(),
|
||||||
vote_account_keypair,
|
vote_account_id,
|
||||||
|
vote_signer_addr,
|
||||||
bank.clone(),
|
bank.clone(),
|
||||||
cluster_info.clone(),
|
cluster_info.clone(),
|
||||||
blob_window_receiver,
|
blob_window_receiver,
|
||||||
|
@ -189,6 +192,7 @@ pub mod tests {
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
use std::fs::remove_dir_all;
|
use std::fs::remove_dir_all;
|
||||||
use std::net::UdpSocket;
|
use std::net::UdpSocket;
|
||||||
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
@ -264,13 +268,14 @@ pub mod tests {
|
||||||
let cref1 = Arc::new(RwLock::new(cluster_info1));
|
let cref1 = Arc::new(RwLock::new(cluster_info1));
|
||||||
let dr_1 = new_ncp(cref1.clone(), target1.sockets.gossip, exit.clone());
|
let dr_1 = new_ncp(cref1.clone(), target1.sockets.gossip, exit.clone());
|
||||||
|
|
||||||
let vote_account_keypair = Arc::new(Keypair::new());
|
let vote_account_id = Keypair::new().pubkey();
|
||||||
let mut cur_hash = Hash::default();
|
let mut cur_hash = Hash::default();
|
||||||
let db_ledger_path = get_tmp_ledger_path("test_replay");
|
let db_ledger_path = get_tmp_ledger_path("test_replay");
|
||||||
let db_ledger =
|
let db_ledger =
|
||||||
DbLedger::open(&db_ledger_path).expect("Expected to successfully open ledger");
|
DbLedger::open(&db_ledger_path).expect("Expected to successfully open ledger");
|
||||||
let tvu = Tvu::new(
|
let tvu = Tvu::new(
|
||||||
vote_account_keypair,
|
&vote_account_id,
|
||||||
|
&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
|
||||||
&bank,
|
&bank,
|
||||||
0,
|
0,
|
||||||
cur_hash,
|
cur_hash,
|
||||||
|
|
|
@ -5,11 +5,13 @@ use crate::cluster_info::ClusterInfo;
|
||||||
use crate::counter::Counter;
|
use crate::counter::Counter;
|
||||||
use crate::packet::SharedBlob;
|
use crate::packet::SharedBlob;
|
||||||
use crate::result::{Error, Result};
|
use crate::result::{Error, Result};
|
||||||
|
use crate::rpc_request::{RpcClient, RpcRequest};
|
||||||
use crate::streamer::BlobSender;
|
use crate::streamer::BlobSender;
|
||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
use log::Level;
|
use log::Level;
|
||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::hash::Hash;
|
||||||
use solana_sdk::signature::Keypair;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
use solana_sdk::vote_program::Vote;
|
use solana_sdk::vote_program::Vote;
|
||||||
use solana_sdk::vote_transaction::VoteTransaction;
|
use solana_sdk::vote_transaction::VoteTransaction;
|
||||||
|
@ -24,10 +26,41 @@ pub enum VoteError {
|
||||||
LeaderInfoNotFound,
|
LeaderInfoNotFound,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_new_signed_vote_transaction(
|
||||||
|
last_id: &Hash,
|
||||||
|
keypair: &Arc<Keypair>,
|
||||||
|
tick_height: u64,
|
||||||
|
vote_account: &Pubkey,
|
||||||
|
rpc_client: &RpcClient,
|
||||||
|
) -> Transaction {
|
||||||
|
let vote = Vote { tick_height };
|
||||||
|
let tx = Transaction::vote_new(&vote_account, vote, *last_id, 0);
|
||||||
|
|
||||||
|
let msg = tx.get_sign_data();
|
||||||
|
let sig = Signature::new(&keypair.sign(&msg).as_ref());
|
||||||
|
|
||||||
|
let params = json!([keypair.pubkey(), sig, &msg]);
|
||||||
|
let resp = RpcRequest::SignVote
|
||||||
|
.make_rpc_request(&rpc_client, 1, Some(params))
|
||||||
|
.unwrap();
|
||||||
|
let vote_signature: Signature = serde_json::from_value(resp).unwrap();
|
||||||
|
|
||||||
|
Transaction {
|
||||||
|
signatures: vec![vote_signature],
|
||||||
|
account_keys: tx.account_keys,
|
||||||
|
last_id: tx.last_id,
|
||||||
|
fee: tx.fee,
|
||||||
|
program_ids: tx.program_ids,
|
||||||
|
instructions: tx.instructions,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Change voting to be on fixed tick intervals based on bank state
|
// TODO: Change voting to be on fixed tick intervals based on bank state
|
||||||
pub fn create_new_signed_vote_blob(
|
pub fn create_new_signed_vote_blob(
|
||||||
last_id: &Hash,
|
last_id: &Hash,
|
||||||
vote_account: &Keypair,
|
keypair: &Arc<Keypair>,
|
||||||
|
vote_account: &Pubkey,
|
||||||
|
rpc_client: &RpcClient,
|
||||||
bank: &Arc<Bank>,
|
bank: &Arc<Bank>,
|
||||||
cluster_info: &Arc<RwLock<ClusterInfo>>,
|
cluster_info: &Arc<RwLock<ClusterInfo>>,
|
||||||
) -> Result<SharedBlob> {
|
) -> Result<SharedBlob> {
|
||||||
|
@ -37,8 +70,9 @@ pub fn create_new_signed_vote_blob(
|
||||||
let leader_tpu = get_leader_tpu(&bank, cluster_info)?;
|
let leader_tpu = get_leader_tpu(&bank, cluster_info)?;
|
||||||
//TODO: doesn't seem like there is a synchronous call to get height and id
|
//TODO: doesn't seem like there is a synchronous call to get height and id
|
||||||
debug!("voting on {:?}", &last_id.as_ref()[..8]);
|
debug!("voting on {:?}", &last_id.as_ref()[..8]);
|
||||||
let vote = Vote { tick_height };
|
let tx =
|
||||||
let tx = Transaction::vote_new(&vote_account, vote, *last_id, 0);
|
create_new_signed_vote_transaction(last_id, keypair, tick_height, vote_account, rpc_client);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut blob = shared_blob.write().unwrap();
|
let mut blob = shared_blob.write().unwrap();
|
||||||
let bytes = serialize(&tx)?;
|
let bytes = serialize(&tx)?;
|
||||||
|
@ -68,16 +102,25 @@ fn get_leader_tpu(bank: &Bank, cluster_info: &Arc<RwLock<ClusterInfo>>) -> Resul
|
||||||
|
|
||||||
pub fn send_validator_vote(
|
pub fn send_validator_vote(
|
||||||
bank: &Arc<Bank>,
|
bank: &Arc<Bank>,
|
||||||
vote_account: &Keypair,
|
keypair: &Arc<Keypair>,
|
||||||
|
vote_account: &Pubkey,
|
||||||
|
vote_signer_rpc: &RpcClient,
|
||||||
cluster_info: &Arc<RwLock<ClusterInfo>>,
|
cluster_info: &Arc<RwLock<ClusterInfo>>,
|
||||||
vote_blob_sender: &BlobSender,
|
vote_blob_sender: &BlobSender,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let last_id = bank.last_id();
|
let last_id = bank.last_id();
|
||||||
|
|
||||||
if let Ok(shared_blob) = create_new_signed_vote_blob(&last_id, vote_account, bank, cluster_info)
|
if let Ok(shared_blob) = create_new_signed_vote_blob(
|
||||||
{
|
&last_id,
|
||||||
|
keypair,
|
||||||
|
vote_account,
|
||||||
|
vote_signer_rpc,
|
||||||
|
bank,
|
||||||
|
cluster_info,
|
||||||
|
) {
|
||||||
inc_new_counter_info!("validator-vote_sent", 1);
|
inc_new_counter_info!("validator-vote_sent", 1);
|
||||||
vote_blob_sender.send(vec![shared_blob])?;
|
vote_blob_sender.send(vec![shared_blob])?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
extern crate bincode;
|
||||||
use solana;
|
extern crate chrono;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_json;
|
||||||
|
extern crate solana;
|
||||||
|
extern crate solana_sdk;
|
||||||
|
extern crate solana_vote_signer;
|
||||||
|
|
||||||
use solana::blob_fetch_stage::BlobFetchStage;
|
use solana::blob_fetch_stage::BlobFetchStage;
|
||||||
use solana::cluster_info::{ClusterInfo, Node, NodeInfo};
|
use solana::cluster_info::{ClusterInfo, Node, NodeInfo};
|
||||||
use solana::contact_info::ContactInfo;
|
use solana::contact_info::ContactInfo;
|
||||||
|
use solana::create_vote_account::*;
|
||||||
use solana::db_ledger::{DbLedger, DEFAULT_SLOT_HEIGHT};
|
use solana::db_ledger::{DbLedger, DEFAULT_SLOT_HEIGHT};
|
||||||
use solana::entry::{reconstruct_entries_from_blobs, Entry};
|
use solana::entry::{reconstruct_entries_from_blobs, Entry};
|
||||||
use solana::fullnode::{Fullnode, FullnodeReturnType};
|
use solana::fullnode::{Fullnode, FullnodeReturnType};
|
||||||
|
@ -17,17 +23,19 @@ use solana::mint::Mint;
|
||||||
use solana::packet::SharedBlob;
|
use solana::packet::SharedBlob;
|
||||||
use solana::poh_service::NUM_TICKS_PER_SECOND;
|
use solana::poh_service::NUM_TICKS_PER_SECOND;
|
||||||
use solana::result;
|
use solana::result;
|
||||||
|
use solana::rpc_request::{RpcClient, RpcRequest};
|
||||||
use solana::service::Service;
|
use solana::service::Service;
|
||||||
use solana::thin_client::{retry_get_balance, ThinClient};
|
use solana::thin_client::{retry_get_balance, ThinClient};
|
||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::hash::Hash;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||||
use solana_sdk::system_transaction::SystemTransaction;
|
use solana_sdk::system_transaction::SystemTransaction;
|
||||||
use solana_sdk::timing::{duration_as_ms, duration_as_s};
|
use solana_sdk::timing::{duration_as_ms, duration_as_s};
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
use std::collections::{HashSet, VecDeque};
|
use std::collections::{HashSet, VecDeque};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::remove_dir_all;
|
use std::fs::remove_dir_all;
|
||||||
|
use std::net::SocketAddr;
|
||||||
use std::net::UdpSocket;
|
use std::net::UdpSocket;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
@ -119,6 +127,20 @@ fn make_tiny_test_entries(start_hash: Hash, num: usize) -> Vec<Entry> {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn register_node(signer: SocketAddr, keypair: Arc<Keypair>) -> Pubkey {
|
||||||
|
let rpc_client = RpcClient::new_from_socket(signer);
|
||||||
|
|
||||||
|
let msg = "Registering a new node";
|
||||||
|
let sig = Signature::new(&keypair.sign(msg.as_bytes()).as_ref());
|
||||||
|
|
||||||
|
let params = json!([keypair.pubkey(), sig, msg.as_bytes()]);
|
||||||
|
let resp = RpcRequest::RegisterNode
|
||||||
|
.make_rpc_request(&rpc_client, 1, Some(params))
|
||||||
|
.unwrap();
|
||||||
|
let vote_account_id: Pubkey = serde_json::from_value(resp).unwrap();
|
||||||
|
vote_account_id
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_multi_node_ledger_window() -> result::Result<()> {
|
fn test_multi_node_ledger_window() -> result::Result<()> {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
|
@ -152,11 +174,14 @@ fn test_multi_node_ledger_window() -> result::Result<()> {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
|
let vote_id = register_node(signer, leader_keypair.clone());
|
||||||
let leader = Fullnode::new(
|
let leader = Fullnode::new(
|
||||||
leader,
|
leader,
|
||||||
&leader_ledger_path,
|
&leader_ledger_path,
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
Arc::new(Keypair::new()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
||||||
|
@ -169,11 +194,13 @@ fn test_multi_node_ledger_window() -> result::Result<()> {
|
||||||
let validator_pubkey = keypair.pubkey().clone();
|
let validator_pubkey = keypair.pubkey().clone();
|
||||||
let validator = Node::new_localhost_with_pubkey(keypair.pubkey());
|
let validator = Node::new_localhost_with_pubkey(keypair.pubkey());
|
||||||
let validator_data = validator.info.clone();
|
let validator_data = validator.info.clone();
|
||||||
|
let validator_vote_id = register_node(signer, keypair.clone());
|
||||||
let validator = Fullnode::new(
|
let validator = Fullnode::new(
|
||||||
validator,
|
validator,
|
||||||
&zero_ledger_path,
|
&zero_ledger_path,
|
||||||
keypair,
|
keypair,
|
||||||
Arc::new(Keypair::new()),
|
&validator_vote_id,
|
||||||
|
&signer,
|
||||||
Some(leader_data.gossip),
|
Some(leader_data.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
||||||
|
@ -212,6 +239,8 @@ fn test_multi_node_ledger_window() -> result::Result<()> {
|
||||||
validator.close()?;
|
validator.close()?;
|
||||||
leader.close()?;
|
leader.close()?;
|
||||||
|
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
|
|
||||||
for path in ledger_paths {
|
for path in ledger_paths {
|
||||||
remove_dir_all(path).unwrap();
|
remove_dir_all(path).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -246,11 +275,14 @@ fn test_multi_node_validator_catchup_from_zero() -> result::Result<()> {
|
||||||
);
|
);
|
||||||
ledger_paths.push(zero_ledger_path.clone());
|
ledger_paths.push(zero_ledger_path.clone());
|
||||||
|
|
||||||
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
|
let vote_id = register_node(signer, leader_keypair.clone());
|
||||||
let server = Fullnode::new(
|
let server = Fullnode::new(
|
||||||
leader,
|
leader,
|
||||||
&leader_ledger_path,
|
&leader_ledger_path,
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
Arc::new(Keypair::new()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
||||||
|
@ -274,11 +306,13 @@ fn test_multi_node_validator_catchup_from_zero() -> result::Result<()> {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
info!("validator balance {}", validator_balance);
|
info!("validator balance {}", validator_balance);
|
||||||
|
|
||||||
|
let vote_id = register_node(signer, keypair.clone());
|
||||||
let val = Fullnode::new(
|
let val = Fullnode::new(
|
||||||
validator,
|
validator,
|
||||||
&ledger_path,
|
&ledger_path,
|
||||||
keypair,
|
keypair,
|
||||||
Arc::new(Keypair::new()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
Some(leader_data.gossip),
|
Some(leader_data.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
||||||
|
@ -312,11 +346,13 @@ fn test_multi_node_validator_catchup_from_zero() -> result::Result<()> {
|
||||||
// balances
|
// balances
|
||||||
let keypair = Arc::new(Keypair::new());
|
let keypair = Arc::new(Keypair::new());
|
||||||
let validator = Node::new_localhost_with_pubkey(keypair.pubkey());
|
let validator = Node::new_localhost_with_pubkey(keypair.pubkey());
|
||||||
|
let vote_id = register_node(signer, keypair.clone());
|
||||||
let val = Fullnode::new(
|
let val = Fullnode::new(
|
||||||
validator,
|
validator,
|
||||||
&zero_ledger_path,
|
&zero_ledger_path,
|
||||||
keypair,
|
keypair,
|
||||||
Arc::new(Keypair::new()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
Some(leader_data.gossip),
|
Some(leader_data.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
||||||
|
@ -358,6 +394,9 @@ fn test_multi_node_validator_catchup_from_zero() -> result::Result<()> {
|
||||||
for node in nodes {
|
for node in nodes {
|
||||||
node.close()?;
|
node.close()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
|
|
||||||
for path in ledger_paths {
|
for path in ledger_paths {
|
||||||
remove_dir_all(path).unwrap();
|
remove_dir_all(path).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -381,11 +420,14 @@ fn test_multi_node_basic() {
|
||||||
let (alice, leader_ledger_path) =
|
let (alice, leader_ledger_path) =
|
||||||
create_tmp_genesis("multi_node_basic", 10_000, leader_data.id, 500);
|
create_tmp_genesis("multi_node_basic", 10_000, leader_data.id, 500);
|
||||||
ledger_paths.push(leader_ledger_path.clone());
|
ledger_paths.push(leader_ledger_path.clone());
|
||||||
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
|
let vote_id = register_node(signer, leader_keypair.clone());
|
||||||
let server = Fullnode::new(
|
let server = Fullnode::new(
|
||||||
leader,
|
leader,
|
||||||
&leader_ledger_path,
|
&leader_ledger_path,
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
Arc::new(Keypair::new()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
||||||
|
@ -405,12 +447,13 @@ fn test_multi_node_basic() {
|
||||||
send_tx_and_retry_get_balance(&leader_data, &alice, &validator_pubkey, 500, None)
|
send_tx_and_retry_get_balance(&leader_data, &alice, &validator_pubkey, 500, None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
info!("validator balance {}", validator_balance);
|
info!("validator balance {}", validator_balance);
|
||||||
|
let vote_id = register_node(signer, keypair.clone());
|
||||||
let val = Fullnode::new(
|
let val = Fullnode::new(
|
||||||
validator,
|
validator,
|
||||||
&ledger_path,
|
&ledger_path,
|
||||||
keypair,
|
keypair,
|
||||||
Arc::new(Keypair::new()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
Some(leader_data.gossip),
|
Some(leader_data.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
||||||
|
@ -441,6 +484,8 @@ fn test_multi_node_basic() {
|
||||||
for node in nodes {
|
for node in nodes {
|
||||||
node.close().unwrap();
|
node.close().unwrap();
|
||||||
}
|
}
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
|
|
||||||
for path in ledger_paths {
|
for path in ledger_paths {
|
||||||
remove_dir_all(path).unwrap();
|
remove_dir_all(path).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -460,11 +505,14 @@ fn test_boot_validator_from_file() -> result::Result<()> {
|
||||||
ledger_paths.push(leader_ledger_path.clone());
|
ledger_paths.push(leader_ledger_path.clone());
|
||||||
|
|
||||||
let leader_data = leader.info.clone();
|
let leader_data = leader.info.clone();
|
||||||
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
|
let vote_id = register_node(signer, leader_keypair.clone());
|
||||||
let leader_fullnode = Fullnode::new(
|
let leader_fullnode = Fullnode::new(
|
||||||
leader,
|
leader,
|
||||||
&leader_ledger_path,
|
&leader_ledger_path,
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
Arc::new(Keypair::new()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
||||||
|
@ -482,11 +530,13 @@ fn test_boot_validator_from_file() -> result::Result<()> {
|
||||||
let validator_data = validator.info.clone();
|
let validator_data = validator.info.clone();
|
||||||
let ledger_path = tmp_copy_ledger(&leader_ledger_path, "boot_validator_from_file");
|
let ledger_path = tmp_copy_ledger(&leader_ledger_path, "boot_validator_from_file");
|
||||||
ledger_paths.push(ledger_path.clone());
|
ledger_paths.push(ledger_path.clone());
|
||||||
|
let vote_id = register_node(signer, keypair.clone());
|
||||||
let val_fullnode = Fullnode::new(
|
let val_fullnode = Fullnode::new(
|
||||||
validator,
|
validator,
|
||||||
&ledger_path,
|
&ledger_path,
|
||||||
keypair,
|
keypair,
|
||||||
Arc::new(Keypair::new()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
Some(leader_data.gossip),
|
Some(leader_data.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
||||||
|
@ -498,6 +548,8 @@ fn test_boot_validator_from_file() -> result::Result<()> {
|
||||||
|
|
||||||
val_fullnode.close()?;
|
val_fullnode.close()?;
|
||||||
leader_fullnode.close()?;
|
leader_fullnode.close()?;
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
|
|
||||||
for path in ledger_paths {
|
for path in ledger_paths {
|
||||||
remove_dir_all(path)?;
|
remove_dir_all(path)?;
|
||||||
}
|
}
|
||||||
|
@ -505,14 +557,20 @@ fn test_boot_validator_from_file() -> result::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_leader(ledger_path: &str, leader_keypair: Arc<Keypair>) -> (NodeInfo, Fullnode) {
|
fn create_leader(
|
||||||
|
ledger_path: &str,
|
||||||
|
leader_keypair: Arc<Keypair>,
|
||||||
|
vote_id: &Pubkey,
|
||||||
|
signer: &SocketAddr,
|
||||||
|
) -> (NodeInfo, Fullnode) {
|
||||||
let leader = Node::new_localhost_with_pubkey(leader_keypair.pubkey());
|
let leader = Node::new_localhost_with_pubkey(leader_keypair.pubkey());
|
||||||
let leader_data = leader.info.clone();
|
let leader_data = leader.info.clone();
|
||||||
let leader_fullnode = Fullnode::new(
|
let leader_fullnode = Fullnode::new(
|
||||||
leader,
|
leader,
|
||||||
&ledger_path,
|
&ledger_path,
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
Arc::new(Keypair::new()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_data.id),
|
LeaderScheduler::from_bootstrap_leader(leader_data.id),
|
||||||
|
@ -539,7 +597,10 @@ fn test_leader_restart_validator_start_from_old_ledger() -> result::Result<()> {
|
||||||
);
|
);
|
||||||
let bob_pubkey = Keypair::new().pubkey();
|
let bob_pubkey = Keypair::new().pubkey();
|
||||||
|
|
||||||
let (leader_data, leader_fullnode) = create_leader(&ledger_path, leader_keypair.clone());
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
|
let vote_id = register_node(signer, leader_keypair.clone());
|
||||||
|
let (leader_data, leader_fullnode) =
|
||||||
|
create_leader(&ledger_path, leader_keypair.clone(), &vote_id, &signer);
|
||||||
|
|
||||||
// lengthen the ledger
|
// lengthen the ledger
|
||||||
let leader_balance =
|
let leader_balance =
|
||||||
|
@ -554,7 +615,8 @@ fn test_leader_restart_validator_start_from_old_ledger() -> result::Result<()> {
|
||||||
|
|
||||||
// restart the leader
|
// restart the leader
|
||||||
leader_fullnode.close()?;
|
leader_fullnode.close()?;
|
||||||
let (leader_data, leader_fullnode) = create_leader(&ledger_path, leader_keypair.clone());
|
let (leader_data, leader_fullnode) =
|
||||||
|
create_leader(&ledger_path, leader_keypair.clone(), &vote_id, &signer);
|
||||||
|
|
||||||
// lengthen the ledger
|
// lengthen the ledger
|
||||||
let leader_balance =
|
let leader_balance =
|
||||||
|
@ -563,18 +625,21 @@ fn test_leader_restart_validator_start_from_old_ledger() -> result::Result<()> {
|
||||||
|
|
||||||
// restart the leader
|
// restart the leader
|
||||||
leader_fullnode.close()?;
|
leader_fullnode.close()?;
|
||||||
let (leader_data, leader_fullnode) = create_leader(&ledger_path, leader_keypair);
|
let (leader_data, leader_fullnode) =
|
||||||
|
create_leader(&ledger_path, leader_keypair, &vote_id, &signer);
|
||||||
|
|
||||||
// start validator from old ledger
|
// start validator from old ledger
|
||||||
let keypair = Arc::new(Keypair::new());
|
let keypair = Arc::new(Keypair::new());
|
||||||
let validator = Node::new_localhost_with_pubkey(keypair.pubkey());
|
let validator = Node::new_localhost_with_pubkey(keypair.pubkey());
|
||||||
let validator_data = validator.info.clone();
|
let validator_data = validator.info.clone();
|
||||||
|
|
||||||
|
let vote_id = register_node(signer, keypair.clone());
|
||||||
let val_fullnode = Fullnode::new(
|
let val_fullnode = Fullnode::new(
|
||||||
validator,
|
validator,
|
||||||
&stale_ledger_path,
|
&stale_ledger_path,
|
||||||
keypair,
|
keypair,
|
||||||
Arc::new(Keypair::new()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
Some(leader_data.gossip),
|
Some(leader_data.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_data.id),
|
LeaderScheduler::from_bootstrap_leader(leader_data.id),
|
||||||
|
@ -604,6 +669,7 @@ fn test_leader_restart_validator_start_from_old_ledger() -> result::Result<()> {
|
||||||
|
|
||||||
val_fullnode.close()?;
|
val_fullnode.close()?;
|
||||||
leader_fullnode.close()?;
|
leader_fullnode.close()?;
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
remove_dir_all(ledger_path)?;
|
remove_dir_all(ledger_path)?;
|
||||||
remove_dir_all(stale_ledger_path)?;
|
remove_dir_all(stale_ledger_path)?;
|
||||||
|
|
||||||
|
@ -637,11 +703,14 @@ fn test_multi_node_dynamic_network() {
|
||||||
let alice_arc = Arc::new(RwLock::new(alice));
|
let alice_arc = Arc::new(RwLock::new(alice));
|
||||||
let leader_data = leader.info.clone();
|
let leader_data = leader.info.clone();
|
||||||
|
|
||||||
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
|
let vote_id = register_node(signer, leader_keypair.clone());
|
||||||
let server = Fullnode::new(
|
let server = Fullnode::new(
|
||||||
leader,
|
leader,
|
||||||
&leader_ledger_path,
|
&leader_ledger_path,
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
Arc::new(Keypair::new()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
None,
|
None,
|
||||||
true,
|
true,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
||||||
|
@ -705,11 +774,14 @@ fn test_multi_node_dynamic_network() {
|
||||||
let validator = Node::new_localhost_with_pubkey(keypair.pubkey());
|
let validator = Node::new_localhost_with_pubkey(keypair.pubkey());
|
||||||
let rd = validator.info.clone();
|
let rd = validator.info.clone();
|
||||||
info!("starting {} {}", keypair.pubkey(), rd.id);
|
info!("starting {} {}", keypair.pubkey(), rd.id);
|
||||||
|
let keypair = Arc::new(keypair);
|
||||||
|
let vote_id = register_node(signer, keypair.clone());
|
||||||
let val = Fullnode::new(
|
let val = Fullnode::new(
|
||||||
validator,
|
validator,
|
||||||
&ledger_path,
|
&ledger_path,
|
||||||
Arc::new(keypair),
|
keypair,
|
||||||
Arc::new(Keypair::new()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
Some(leader_data.gossip),
|
Some(leader_data.gossip),
|
||||||
true,
|
true,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
||||||
|
@ -794,6 +866,7 @@ fn test_multi_node_dynamic_network() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
assert_eq!(consecutive_success, 10);
|
assert_eq!(consecutive_success, 10);
|
||||||
for (_, node) in &validators {
|
for (_, node) in &validators {
|
||||||
node.exit();
|
node.exit();
|
||||||
|
@ -840,8 +913,15 @@ fn test_leader_to_validator_transition() {
|
||||||
|
|
||||||
// Write the bootstrap entries to the ledger that will cause leader rotation
|
// Write the bootstrap entries to the ledger that will cause leader rotation
|
||||||
// after the bootstrap height
|
// after the bootstrap height
|
||||||
let (bootstrap_entries, _) =
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
make_active_set_entries(&validator_keypair, &mint.keypair(), &last_id, &last_id, 0);
|
let (bootstrap_entries, _) = make_active_set_entries(
|
||||||
|
&validator_keypair,
|
||||||
|
signer,
|
||||||
|
&mint.keypair(),
|
||||||
|
&last_id,
|
||||||
|
&last_id,
|
||||||
|
0,
|
||||||
|
);
|
||||||
{
|
{
|
||||||
let db_ledger = DbLedger::open(&leader_ledger_path).unwrap();
|
let db_ledger = DbLedger::open(&leader_ledger_path).unwrap();
|
||||||
db_ledger
|
db_ledger
|
||||||
|
@ -862,11 +942,13 @@ fn test_leader_to_validator_transition() {
|
||||||
Some(bootstrap_height),
|
Some(bootstrap_height),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let vote_id = register_node(signer, leader_keypair.clone());
|
||||||
let mut leader = Fullnode::new(
|
let mut leader = Fullnode::new(
|
||||||
leader_node,
|
leader_node,
|
||||||
&leader_ledger_path,
|
&leader_ledger_path,
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
Arc::new(Keypair::new()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
Some(leader_info.gossip),
|
Some(leader_info.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::new(&leader_scheduler_config),
|
LeaderScheduler::new(&leader_scheduler_config),
|
||||||
|
@ -942,6 +1024,7 @@ fn test_leader_to_validator_transition() {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(bank.tick_height(), bootstrap_height);
|
assert_eq!(bank.tick_height(), bootstrap_height);
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
remove_dir_all(leader_ledger_path).unwrap();
|
remove_dir_all(leader_ledger_path).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -986,8 +1069,15 @@ fn test_leader_validator_basic() {
|
||||||
|
|
||||||
// Write the bootstrap entries to the ledger that will cause leader rotation
|
// Write the bootstrap entries to the ledger that will cause leader rotation
|
||||||
// after the bootstrap height
|
// after the bootstrap height
|
||||||
let (active_set_entries, vote_account_keypair) =
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
make_active_set_entries(&validator_keypair, &mint.keypair(), &last_id, &last_id, 0);
|
let (active_set_entries, _vote_account_keypair) = make_active_set_entries(
|
||||||
|
&validator_keypair,
|
||||||
|
signer,
|
||||||
|
&mint.keypair(),
|
||||||
|
&last_id,
|
||||||
|
&last_id,
|
||||||
|
0,
|
||||||
|
);
|
||||||
{
|
{
|
||||||
let db_ledger = DbLedger::open(&leader_ledger_path).unwrap();
|
let db_ledger = DbLedger::open(&leader_ledger_path).unwrap();
|
||||||
db_ledger
|
db_ledger
|
||||||
|
@ -1010,11 +1100,13 @@ fn test_leader_validator_basic() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Start the validator node
|
// Start the validator node
|
||||||
|
let vote_id = register_node(signer, validator_keypair.clone());
|
||||||
let mut validator = Fullnode::new(
|
let mut validator = Fullnode::new(
|
||||||
validator_node,
|
validator_node,
|
||||||
&validator_ledger_path,
|
&validator_ledger_path,
|
||||||
validator_keypair,
|
validator_keypair,
|
||||||
Arc::new(vote_account_keypair),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
Some(leader_info.gossip),
|
Some(leader_info.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::new(&leader_scheduler_config),
|
LeaderScheduler::new(&leader_scheduler_config),
|
||||||
|
@ -1022,11 +1114,13 @@ fn test_leader_validator_basic() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Start the leader fullnode
|
// Start the leader fullnode
|
||||||
|
let vote_id = register_node(signer, leader_keypair.clone());
|
||||||
let mut leader = Fullnode::new(
|
let mut leader = Fullnode::new(
|
||||||
leader_node,
|
leader_node,
|
||||||
&leader_ledger_path,
|
&leader_ledger_path,
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
Arc::new(Keypair::new()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
Some(leader_info.gossip),
|
Some(leader_info.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::new(&leader_scheduler_config),
|
LeaderScheduler::new(&leader_scheduler_config),
|
||||||
|
@ -1095,6 +1189,7 @@ fn test_leader_validator_basic() {
|
||||||
for (v, l) in validator_entries.iter().zip(leader_entries) {
|
for (v, l) in validator_entries.iter().zip(leader_entries) {
|
||||||
assert_eq!(*v, l);
|
assert_eq!(*v, l);
|
||||||
}
|
}
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
|
|
||||||
for path in ledger_paths {
|
for path in ledger_paths {
|
||||||
DbLedger::destroy(&path).expect("Expected successful database destruction");
|
DbLedger::destroy(&path).expect("Expected successful database destruction");
|
||||||
|
@ -1167,8 +1262,15 @@ fn test_dropped_handoff_recovery() {
|
||||||
|
|
||||||
// Make the entries to give the next_leader validator some stake so that they will be in
|
// Make the entries to give the next_leader validator some stake so that they will be in
|
||||||
// leader election active set
|
// leader election active set
|
||||||
let (active_set_entries, vote_account_keypair) =
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
make_active_set_entries(&next_leader_keypair, &mint.keypair(), &last_id, &last_id, 0);
|
let (active_set_entries, _vote_account_keypair) = make_active_set_entries(
|
||||||
|
&next_leader_keypair,
|
||||||
|
signer,
|
||||||
|
&mint.keypair(),
|
||||||
|
&last_id,
|
||||||
|
&last_id,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
// Write the entries
|
// Write the entries
|
||||||
{
|
{
|
||||||
|
@ -1204,12 +1306,14 @@ fn test_dropped_handoff_recovery() {
|
||||||
Some(leader_rotation_interval),
|
Some(leader_rotation_interval),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let vote_id = register_node(signer, bootstrap_leader_keypair.clone());
|
||||||
// Start up the bootstrap leader fullnode
|
// Start up the bootstrap leader fullnode
|
||||||
let bootstrap_leader = Fullnode::new(
|
let bootstrap_leader = Fullnode::new(
|
||||||
bootstrap_leader_node,
|
bootstrap_leader_node,
|
||||||
&bootstrap_leader_ledger_path,
|
&bootstrap_leader_ledger_path,
|
||||||
bootstrap_leader_keypair,
|
bootstrap_leader_keypair,
|
||||||
Arc::new(Keypair::new()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
Some(bootstrap_leader_info.gossip),
|
Some(bootstrap_leader_info.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::new(&leader_scheduler_config),
|
LeaderScheduler::new(&leader_scheduler_config),
|
||||||
|
@ -1228,11 +1332,13 @@ fn test_dropped_handoff_recovery() {
|
||||||
ledger_paths.push(validator_ledger_path.clone());
|
ledger_paths.push(validator_ledger_path.clone());
|
||||||
let validator_id = kp.pubkey();
|
let validator_id = kp.pubkey();
|
||||||
let validator_node = Node::new_localhost_with_pubkey(validator_id);
|
let validator_node = Node::new_localhost_with_pubkey(validator_id);
|
||||||
|
let vote_id = register_node(signer, kp.clone());
|
||||||
let validator = Fullnode::new(
|
let validator = Fullnode::new(
|
||||||
validator_node,
|
validator_node,
|
||||||
&validator_ledger_path,
|
&validator_ledger_path,
|
||||||
kp,
|
kp,
|
||||||
Arc::new(Keypair::new()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
Some(bootstrap_leader_info.gossip),
|
Some(bootstrap_leader_info.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::new(&leader_scheduler_config),
|
LeaderScheduler::new(&leader_scheduler_config),
|
||||||
|
@ -1254,11 +1360,13 @@ fn test_dropped_handoff_recovery() {
|
||||||
|
|
||||||
// Now start up the "next leader" node
|
// Now start up the "next leader" node
|
||||||
let next_leader_node = Node::new_localhost_with_pubkey(next_leader_keypair.pubkey());
|
let next_leader_node = Node::new_localhost_with_pubkey(next_leader_keypair.pubkey());
|
||||||
|
let vote_id = register_node(signer, next_leader_keypair.clone());
|
||||||
let mut next_leader = Fullnode::new(
|
let mut next_leader = Fullnode::new(
|
||||||
next_leader_node,
|
next_leader_node,
|
||||||
&next_leader_ledger_path,
|
&next_leader_ledger_path,
|
||||||
next_leader_keypair,
|
next_leader_keypair,
|
||||||
Arc::new(vote_account_keypair),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
Some(bootstrap_leader_info.gossip),
|
Some(bootstrap_leader_info.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::new(&leader_scheduler_config),
|
LeaderScheduler::new(&leader_scheduler_config),
|
||||||
|
@ -1273,6 +1381,7 @@ fn test_dropped_handoff_recovery() {
|
||||||
|
|
||||||
nodes.push(next_leader);
|
nodes.push(next_leader);
|
||||||
|
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
for node in nodes {
|
for node in nodes {
|
||||||
node.close().unwrap();
|
node.close().unwrap();
|
||||||
}
|
}
|
||||||
|
@ -1333,12 +1442,14 @@ fn test_full_leader_validator_network() {
|
||||||
let mut ledger_paths = Vec::new();
|
let mut ledger_paths = Vec::new();
|
||||||
ledger_paths.push(bootstrap_leader_ledger_path.clone());
|
ledger_paths.push(bootstrap_leader_ledger_path.clone());
|
||||||
|
|
||||||
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
let mut vote_account_keypairs = VecDeque::new();
|
let mut vote_account_keypairs = VecDeque::new();
|
||||||
for node_keypair in node_keypairs.iter() {
|
for node_keypair in node_keypairs.iter() {
|
||||||
// Make entries to give each node some stake so that they will be in the
|
// Make entries to give each node some stake so that they will be in the
|
||||||
// leader election active set
|
// leader election active set
|
||||||
let (bootstrap_entries, vote_account_keypair) = make_active_set_entries(
|
let (bootstrap_entries, vote_account_keypair) = make_active_set_entries(
|
||||||
node_keypair,
|
node_keypair,
|
||||||
|
signer,
|
||||||
&mint.keypair(),
|
&mint.keypair(),
|
||||||
&last_entry_id,
|
&last_entry_id,
|
||||||
&last_tick_id,
|
&last_tick_id,
|
||||||
|
@ -1385,7 +1496,7 @@ fn test_full_leader_validator_network() {
|
||||||
// 2) Modifying the leader ledger which validators are going to be copying
|
// 2) Modifying the leader ledger which validators are going to be copying
|
||||||
// during startup
|
// during startup
|
||||||
let leader_keypair = node_keypairs.pop_front().unwrap();
|
let leader_keypair = node_keypairs.pop_front().unwrap();
|
||||||
let leader_vote_keypair = vote_account_keypairs.pop_front().unwrap();
|
let _leader_vote_keypair = vote_account_keypairs.pop_front().unwrap();
|
||||||
let mut nodes: Vec<Arc<RwLock<Fullnode>>> = vec![];
|
let mut nodes: Vec<Arc<RwLock<Fullnode>>> = vec![];
|
||||||
let mut t_nodes = vec![];
|
let mut t_nodes = vec![];
|
||||||
|
|
||||||
|
@ -1400,11 +1511,14 @@ fn test_full_leader_validator_network() {
|
||||||
|
|
||||||
let validator_id = kp.pubkey();
|
let validator_id = kp.pubkey();
|
||||||
let validator_node = Node::new_localhost_with_pubkey(validator_id);
|
let validator_node = Node::new_localhost_with_pubkey(validator_id);
|
||||||
|
let kp = Arc::new(kp);
|
||||||
|
let vote_id = register_node(signer, kp.clone());
|
||||||
let validator = Arc::new(RwLock::new(Fullnode::new(
|
let validator = Arc::new(RwLock::new(Fullnode::new(
|
||||||
validator_node,
|
validator_node,
|
||||||
&validator_ledger_path,
|
&validator_ledger_path,
|
||||||
Arc::new(kp),
|
kp,
|
||||||
Arc::new(vote_account_keypairs.pop_front().unwrap()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
Some(bootstrap_leader_info.gossip),
|
Some(bootstrap_leader_info.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::new(&leader_scheduler_config),
|
LeaderScheduler::new(&leader_scheduler_config),
|
||||||
|
@ -1416,11 +1530,14 @@ fn test_full_leader_validator_network() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start up the bootstrap leader
|
// Start up the bootstrap leader
|
||||||
|
let leader_keypair = Arc::new(leader_keypair);
|
||||||
|
let vote_id = register_node(signer, leader_keypair.clone());
|
||||||
let bootstrap_leader = Arc::new(RwLock::new(Fullnode::new(
|
let bootstrap_leader = Arc::new(RwLock::new(Fullnode::new(
|
||||||
bootstrap_leader_node,
|
bootstrap_leader_node,
|
||||||
&bootstrap_leader_ledger_path,
|
&bootstrap_leader_ledger_path,
|
||||||
Arc::new(leader_keypair),
|
leader_keypair,
|
||||||
Arc::new(leader_vote_keypair),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
Some(bootstrap_leader_info.gossip),
|
Some(bootstrap_leader_info.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::new(&leader_scheduler_config),
|
LeaderScheduler::new(&leader_scheduler_config),
|
||||||
|
@ -1534,6 +1651,7 @@ fn test_full_leader_validator_network() {
|
||||||
|
|
||||||
assert!(shortest.unwrap() >= target_height);
|
assert!(shortest.unwrap() >= target_height);
|
||||||
|
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
for path in ledger_paths {
|
for path in ledger_paths {
|
||||||
DbLedger::destroy(&path).expect("Expected successful database destruction");
|
DbLedger::destroy(&path).expect("Expected successful database destruction");
|
||||||
remove_dir_all(path).unwrap();
|
remove_dir_all(path).unwrap();
|
||||||
|
@ -1596,11 +1714,15 @@ fn test_broadcast_last_tick() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Start up the bootstrap leader fullnode
|
// Start up the bootstrap leader fullnode
|
||||||
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
|
let bootstrap_leader_keypair = Arc::new(bootstrap_leader_keypair);
|
||||||
|
let vote_id = bootstrap_leader_keypair.pubkey();
|
||||||
let mut bootstrap_leader = Fullnode::new(
|
let mut bootstrap_leader = Fullnode::new(
|
||||||
bootstrap_leader_node,
|
bootstrap_leader_node,
|
||||||
&bootstrap_leader_ledger_path,
|
&bootstrap_leader_ledger_path,
|
||||||
Arc::new(bootstrap_leader_keypair),
|
bootstrap_leader_keypair,
|
||||||
Arc::new(Keypair::new()),
|
&vote_id,
|
||||||
|
&signer,
|
||||||
Some(bootstrap_leader_info.gossip),
|
Some(bootstrap_leader_info.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::new(&leader_scheduler_config),
|
LeaderScheduler::new(&leader_scheduler_config),
|
||||||
|
@ -1650,6 +1772,7 @@ fn test_broadcast_last_tick() {
|
||||||
bf.join().unwrap();
|
bf.join().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
// Shut down the listeners
|
// Shut down the listeners
|
||||||
for node in listening_nodes {
|
for node in listening_nodes {
|
||||||
node.0.close().unwrap();
|
node.0.close().unwrap();
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
#[cfg(feature = "chacha")]
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
|
|
||||||
use solana::client::mk_client;
|
use solana::client::mk_client;
|
||||||
use solana::cluster_info::{Node, NodeInfo};
|
use solana::cluster_info::{Node, NodeInfo};
|
||||||
|
use solana::create_vote_account::*;
|
||||||
use solana::db_ledger::DbLedger;
|
use solana::db_ledger::DbLedger;
|
||||||
use solana::fullnode::Fullnode;
|
use solana::fullnode::Fullnode;
|
||||||
use solana::leader_scheduler::LeaderScheduler;
|
use solana::leader_scheduler::LeaderScheduler;
|
||||||
use solana::ledger::{create_tmp_genesis, get_tmp_ledger_path, read_ledger, tmp_copy_ledger};
|
use solana::ledger::{create_tmp_genesis, get_tmp_ledger_path, read_ledger, tmp_copy_ledger};
|
||||||
use solana::replicator::Replicator;
|
use solana::replicator::Replicator;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana::rpc_request::{RpcClient, RpcRequest};
|
||||||
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||||
use solana_sdk::system_transaction::SystemTransaction;
|
use solana_sdk::system_transaction::SystemTransaction;
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
use std::fs::remove_dir_all;
|
use std::fs::remove_dir_all;
|
||||||
|
@ -29,7 +31,6 @@ fn test_replicator_startup() {
|
||||||
let leader_keypair = Arc::new(Keypair::new());
|
let leader_keypair = Arc::new(Keypair::new());
|
||||||
let leader_node = Node::new_localhost_with_pubkey(leader_keypair.pubkey());
|
let leader_node = Node::new_localhost_with_pubkey(leader_keypair.pubkey());
|
||||||
let leader_info = leader_node.info.clone();
|
let leader_info = leader_node.info.clone();
|
||||||
let vote_account_keypair = Arc::new(Keypair::new());
|
|
||||||
|
|
||||||
let leader_ledger_path = "replicator_test_leader_ledger";
|
let leader_ledger_path = "replicator_test_leader_ledger";
|
||||||
let (mint, leader_ledger_path) = create_tmp_genesis(leader_ledger_path, 100, leader_info.id, 1);
|
let (mint, leader_ledger_path) = create_tmp_genesis(leader_ledger_path, 100, leader_info.id, 1);
|
||||||
|
@ -38,11 +39,24 @@ fn test_replicator_startup() {
|
||||||
tmp_copy_ledger(&leader_ledger_path, "replicator_test_validator_ledger");
|
tmp_copy_ledger(&leader_ledger_path, "replicator_test_validator_ledger");
|
||||||
|
|
||||||
{
|
{
|
||||||
|
let (signer, t_signer, signer_exit) = local_vote_signer_service().unwrap();
|
||||||
|
let rpc_client = RpcClient::new_from_socket(signer);
|
||||||
|
|
||||||
|
let msg = "Registering a new node";
|
||||||
|
let sig = Signature::new(&leader_keypair.sign(msg.as_bytes()).as_ref());
|
||||||
|
|
||||||
|
let params = json!([leader_keypair.pubkey(), sig, msg.as_bytes()]);
|
||||||
|
let resp = RpcRequest::RegisterNode
|
||||||
|
.make_rpc_request(&rpc_client, 1, Some(params))
|
||||||
|
.unwrap();
|
||||||
|
let vote_account_id: Pubkey = serde_json::from_value(resp).unwrap();
|
||||||
|
|
||||||
let leader = Fullnode::new(
|
let leader = Fullnode::new(
|
||||||
leader_node,
|
leader_node,
|
||||||
&leader_ledger_path,
|
&leader_ledger_path,
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
vote_account_keypair.clone(),
|
&vote_account_id,
|
||||||
|
&signer,
|
||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_info.id.clone()),
|
LeaderScheduler::from_bootstrap_leader(leader_info.id.clone()),
|
||||||
|
@ -52,6 +66,15 @@ fn test_replicator_startup() {
|
||||||
let validator_keypair = Arc::new(Keypair::new());
|
let validator_keypair = Arc::new(Keypair::new());
|
||||||
let validator_node = Node::new_localhost_with_pubkey(validator_keypair.pubkey());
|
let validator_node = Node::new_localhost_with_pubkey(validator_keypair.pubkey());
|
||||||
|
|
||||||
|
let msg = "Registering a new node";
|
||||||
|
let sig = Signature::new(&validator_keypair.sign(msg.as_bytes()).as_ref());
|
||||||
|
|
||||||
|
let params = json!([validator_keypair.pubkey(), sig, msg.as_bytes()]);
|
||||||
|
let resp = RpcRequest::RegisterNode
|
||||||
|
.make_rpc_request(&rpc_client, 1, Some(params))
|
||||||
|
.unwrap();
|
||||||
|
let vote_account_id: Pubkey = serde_json::from_value(resp).unwrap();
|
||||||
|
|
||||||
#[cfg(feature = "chacha")]
|
#[cfg(feature = "chacha")]
|
||||||
let validator_node_info = validator_node.info.clone();
|
let validator_node_info = validator_node.info.clone();
|
||||||
|
|
||||||
|
@ -59,7 +82,8 @@ fn test_replicator_startup() {
|
||||||
validator_node,
|
validator_node,
|
||||||
&validator_ledger_path,
|
&validator_ledger_path,
|
||||||
validator_keypair,
|
validator_keypair,
|
||||||
vote_account_keypair,
|
&vote_account_id,
|
||||||
|
&signer,
|
||||||
Some(leader_info.gossip),
|
Some(leader_info.gossip),
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_info.id),
|
LeaderScheduler::from_bootstrap_leader(leader_info.id),
|
||||||
|
@ -154,6 +178,7 @@ fn test_replicator_startup() {
|
||||||
|
|
||||||
// Check that some ledger was downloaded
|
// Check that some ledger was downloaded
|
||||||
assert!(num_entries > 0);
|
assert!(num_entries > 0);
|
||||||
|
stop_local_vote_signer_service(t_signer, &signer_exit);
|
||||||
|
|
||||||
replicator.close();
|
replicator.close();
|
||||||
validator.exit();
|
validator.exit();
|
||||||
|
|
|
@ -9,7 +9,8 @@ use clap::{App, Arg};
|
||||||
use solana_vote_signer::rpc::VoteSignerRpcService;
|
use solana_vote_signer::rpc::VoteSignerRpcService;
|
||||||
use std::error;
|
use std::error;
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
|
use std::sync::atomic::AtomicBool;
|
||||||
|
use std::sync::Arc;
|
||||||
pub const RPC_PORT: u16 = 8989;
|
pub const RPC_PORT: u16 = 8989;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<error::Error>> {
|
fn main() -> Result<(), Box<error::Error>> {
|
||||||
|
@ -34,8 +35,11 @@ fn main() -> Result<(), Box<error::Error>> {
|
||||||
RPC_PORT
|
RPC_PORT
|
||||||
};
|
};
|
||||||
|
|
||||||
let service =
|
let exit = Arc::new(AtomicBool::new(false));
|
||||||
VoteSignerRpcService::new(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), port));
|
let service = VoteSignerRpcService::new(
|
||||||
|
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), port),
|
||||||
|
exit,
|
||||||
|
);
|
||||||
|
|
||||||
service.join().unwrap();
|
service.join().unwrap();
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
//! The `rpc` module implements the Vote signing service RPC interface.
|
//! The `rpc` module implements the Vote signing service RPC interface.
|
||||||
|
|
||||||
use bs58;
|
|
||||||
use jsonrpc_core::*;
|
use jsonrpc_core::*;
|
||||||
use jsonrpc_http_server::*;
|
use jsonrpc_http_server::*;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::mem;
|
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
@ -19,9 +17,8 @@ pub struct VoteSignerRpcService {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VoteSignerRpcService {
|
impl VoteSignerRpcService {
|
||||||
pub fn new(rpc_addr: SocketAddr) -> Self {
|
pub fn new(rpc_addr: SocketAddr, exit: Arc<AtomicBool>) -> Self {
|
||||||
let request_processor = VoteSignRequestProcessor::default();
|
let request_processor = VoteSignRequestProcessor::default();
|
||||||
let exit = Arc::new(AtomicBool::new(false));
|
|
||||||
let exit_ = exit.clone();
|
let exit_ = exit.clone();
|
||||||
let thread_hdl = Builder::new()
|
let thread_hdl = Builder::new()
|
||||||
.name("solana-vote-signer-jsonrpc".to_string())
|
.name("solana-vote-signer-jsonrpc".to_string())
|
||||||
|
@ -76,13 +73,13 @@ build_rpc_trait! {
|
||||||
type Metadata;
|
type Metadata;
|
||||||
|
|
||||||
#[rpc(meta, name = "registerNode")]
|
#[rpc(meta, name = "registerNode")]
|
||||||
fn register(&self, Self::Metadata, String, Signature, Vec<u8>) -> Result<Pubkey>;
|
fn register(&self, Self::Metadata, Pubkey, Signature, Vec<u8>) -> Result<Pubkey>;
|
||||||
|
|
||||||
#[rpc(meta, name = "signVote")]
|
#[rpc(meta, name = "signVote")]
|
||||||
fn sign(&self, Self::Metadata, String, Signature, Vec<u8>) -> Result<Signature>;
|
fn sign(&self, Self::Metadata, Pubkey, Signature, Vec<u8>) -> Result<Signature>;
|
||||||
|
|
||||||
#[rpc(meta, name = "deregisterNode")]
|
#[rpc(meta, name = "deregisterNode")]
|
||||||
fn deregister(&self, Self::Metadata, String, Signature, Vec<u8>) -> Result<()>;
|
fn deregister(&self, Self::Metadata, Pubkey, Signature, Vec<u8>) -> Result<()>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,40 +90,37 @@ impl VoteSignerRpc for VoteSignerRpcImpl {
|
||||||
fn register(
|
fn register(
|
||||||
&self,
|
&self,
|
||||||
meta: Self::Metadata,
|
meta: Self::Metadata,
|
||||||
id: String,
|
id: Pubkey,
|
||||||
sig: Signature,
|
sig: Signature,
|
||||||
signed_msg: Vec<u8>,
|
signed_msg: Vec<u8>,
|
||||||
) -> Result<Pubkey> {
|
) -> Result<Pubkey> {
|
||||||
info!("register rpc request received: {:?}", id);
|
info!("register rpc request received: {:?}", id);
|
||||||
let pubkey = verify_pubkey(id)?;
|
verify_signature(&sig, &id, &signed_msg)?;
|
||||||
verify_signature(&sig, &pubkey, &signed_msg)?;
|
meta.request_processor.register(id)
|
||||||
meta.request_processor.register(pubkey)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign(
|
fn sign(
|
||||||
&self,
|
&self,
|
||||||
meta: Self::Metadata,
|
meta: Self::Metadata,
|
||||||
id: String,
|
id: Pubkey,
|
||||||
sig: Signature,
|
sig: Signature,
|
||||||
signed_msg: Vec<u8>,
|
signed_msg: Vec<u8>,
|
||||||
) -> Result<Signature> {
|
) -> Result<Signature> {
|
||||||
info!("sign rpc request received: {:?}", id);
|
info!("sign rpc request received: {:?}", id);
|
||||||
let pubkey = verify_pubkey(id)?;
|
verify_signature(&sig, &id, &signed_msg)?;
|
||||||
verify_signature(&sig, &pubkey, &signed_msg)?;
|
meta.request_processor.sign(id, &signed_msg)
|
||||||
meta.request_processor.sign(pubkey, &signed_msg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deregister(
|
fn deregister(
|
||||||
&self,
|
&self,
|
||||||
meta: Self::Metadata,
|
meta: Self::Metadata,
|
||||||
id: String,
|
id: Pubkey,
|
||||||
sig: Signature,
|
sig: Signature,
|
||||||
signed_msg: Vec<u8>,
|
signed_msg: Vec<u8>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
info!("deregister rpc request received: {:?}", id);
|
info!("deregister rpc request received: {:?}", id);
|
||||||
let pubkey = verify_pubkey(id)?;
|
verify_signature(&sig, &id, &signed_msg)?;
|
||||||
verify_signature(&sig, &pubkey, &signed_msg)?;
|
meta.request_processor.deregister(id)
|
||||||
meta.request_processor.deregister(pubkey)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,6 +148,7 @@ impl VoteSignRequestProcessor {
|
||||||
let voting_pubkey = voting_keypair.pubkey();
|
let voting_pubkey = voting_keypair.pubkey();
|
||||||
self.nodes.write().unwrap().insert(pubkey, voting_keypair);
|
self.nodes.write().unwrap().insert(pubkey, voting_keypair);
|
||||||
Ok(voting_pubkey)
|
Ok(voting_pubkey)
|
||||||
|
//Ok(bs58::encode(voting_pubkey).into_string())
|
||||||
}
|
}
|
||||||
pub fn sign(&self, pubkey: Pubkey, msg: &[u8]) -> Result<Signature> {
|
pub fn sign(&self, pubkey: Pubkey, msg: &[u8]) -> Result<Signature> {
|
||||||
match self.nodes.read().unwrap().get(&pubkey) {
|
match self.nodes.read().unwrap().get(&pubkey) {
|
||||||
|
@ -178,27 +173,12 @@ impl Default for VoteSignRequestProcessor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_pubkey(input: String) -> Result<Pubkey> {
|
|
||||||
let pubkey_vec = bs58::decode(input).into_vec().map_err(|err| {
|
|
||||||
info!("verify_pubkey: invalid input: {:?}", err);
|
|
||||||
Error::invalid_request()
|
|
||||||
})?;
|
|
||||||
if pubkey_vec.len() != mem::size_of::<Pubkey>() {
|
|
||||||
info!(
|
|
||||||
"verify_pubkey: invalid pubkey_vec length: {}",
|
|
||||||
pubkey_vec.len()
|
|
||||||
);
|
|
||||||
Err(Error::invalid_request())
|
|
||||||
} else {
|
|
||||||
Ok(Pubkey::new(&pubkey_vec))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use jsonrpc_core::Response;
|
use jsonrpc_core::Response;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
fn start_rpc_handler() -> (MetaIoHandler<Meta>, Meta) {
|
fn start_rpc_handler() -> (MetaIoHandler<Meta>, Meta) {
|
||||||
let request_processor = VoteSignRequestProcessor::default();
|
let request_processor = VoteSignRequestProcessor::default();
|
||||||
|
@ -221,7 +201,7 @@ mod tests {
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"method": "registerNode",
|
"method": "registerNode",
|
||||||
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
|
"params": [node_pubkey, sig, msg.as_bytes()],
|
||||||
});
|
});
|
||||||
let res = io.handle_request_sync(&req.to_string(), meta);
|
let res = io.handle_request_sync(&req.to_string(), meta);
|
||||||
|
|
||||||
|
@ -232,11 +212,11 @@ mod tests {
|
||||||
if let Output::Success(succ) = out {
|
if let Output::Success(succ) = out {
|
||||||
assert_eq!(succ.jsonrpc.unwrap(), Version::V2);
|
assert_eq!(succ.jsonrpc.unwrap(), Version::V2);
|
||||||
assert_eq!(succ.id, Id::Num(1));
|
assert_eq!(succ.id, Id::Num(1));
|
||||||
assert!(succ.result.is_array());
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
succ.result.as_array().unwrap().len(),
|
succ.result.as_array().unwrap().len(),
|
||||||
mem::size_of::<Pubkey>()
|
mem::size_of::<Pubkey>()
|
||||||
);
|
);
|
||||||
|
let _pk: Pubkey = serde_json::from_value(succ.result).unwrap();
|
||||||
} else {
|
} else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
}
|
}
|
||||||
|
@ -258,7 +238,7 @@ mod tests {
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"method": "registerNode",
|
"method": "registerNode",
|
||||||
"params": [node_pubkey.to_string(), sig, msg1.as_bytes()],
|
"params": [node_pubkey, sig, msg1.as_bytes()],
|
||||||
});
|
});
|
||||||
let res = io.handle_request_sync(&req.to_string(), meta);
|
let res = io.handle_request_sync(&req.to_string(), meta);
|
||||||
|
|
||||||
|
@ -289,7 +269,7 @@ mod tests {
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"method": "deregisterNode",
|
"method": "deregisterNode",
|
||||||
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
|
"params": [node_pubkey, sig, msg.as_bytes()],
|
||||||
});
|
});
|
||||||
let res = io.handle_request_sync(&req.to_string(), meta);
|
let res = io.handle_request_sync(&req.to_string(), meta);
|
||||||
|
|
||||||
|
@ -321,7 +301,7 @@ mod tests {
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"method": "deregisterNode",
|
"method": "deregisterNode",
|
||||||
"params": [node_pubkey.to_string(), sig, msg1.as_bytes()],
|
"params": [node_pubkey, sig, msg1.as_bytes()],
|
||||||
});
|
});
|
||||||
let res = io.handle_request_sync(&req.to_string(), meta);
|
let res = io.handle_request_sync(&req.to_string(), meta);
|
||||||
|
|
||||||
|
@ -353,15 +333,33 @@ mod tests {
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"method": "registerNode",
|
"method": "registerNode",
|
||||||
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
|
"params": [node_pubkey, sig, msg.as_bytes()],
|
||||||
});
|
});
|
||||||
let _res = io.handle_request_sync(&req.to_string(), meta.clone());
|
let res = io.handle_request_sync(&req.to_string(), meta.clone());
|
||||||
|
let result: Response = serde_json::from_str(&res.expect("actual response"))
|
||||||
|
.expect("actual response deserialization");
|
||||||
|
let mut vote_pubkey = Keypair::new().pubkey();
|
||||||
|
if let Response::Single(out) = result {
|
||||||
|
if let Output::Success(succ) = out {
|
||||||
|
assert_eq!(succ.jsonrpc.unwrap(), Version::V2);
|
||||||
|
assert_eq!(succ.id, Id::Num(1));
|
||||||
|
assert_eq!(
|
||||||
|
succ.result.as_array().unwrap().len(),
|
||||||
|
mem::size_of::<Pubkey>()
|
||||||
|
);
|
||||||
|
vote_pubkey = serde_json::from_value(succ.result).unwrap();
|
||||||
|
} else {
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
|
||||||
let req = json!({
|
let req = json!({
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"method": "signVote",
|
"method": "signVote",
|
||||||
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
|
"params": [node_pubkey, sig, msg.as_bytes()],
|
||||||
});
|
});
|
||||||
let res = io.handle_request_sync(&req.to_string(), meta);
|
let res = io.handle_request_sync(&req.to_string(), meta);
|
||||||
|
|
||||||
|
@ -372,6 +370,12 @@ mod tests {
|
||||||
if let Output::Success(succ) = out {
|
if let Output::Success(succ) = out {
|
||||||
assert_eq!(succ.jsonrpc.unwrap(), Version::V2);
|
assert_eq!(succ.jsonrpc.unwrap(), Version::V2);
|
||||||
assert_eq!(succ.id, Id::Num(1));
|
assert_eq!(succ.id, Id::Num(1));
|
||||||
|
assert_eq!(
|
||||||
|
succ.result.as_array().unwrap().len(),
|
||||||
|
mem::size_of::<Signature>()
|
||||||
|
);
|
||||||
|
let sig: Signature = serde_json::from_value(succ.result).unwrap();
|
||||||
|
assert_eq!(verify_signature(&sig, &vote_pubkey, msg.as_bytes()), Ok(()));
|
||||||
} else {
|
} else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
}
|
}
|
||||||
|
@ -392,7 +396,7 @@ mod tests {
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"method": "signVote",
|
"method": "signVote",
|
||||||
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
|
"params": [node_pubkey, sig, msg.as_bytes()],
|
||||||
});
|
});
|
||||||
let res = io.handle_request_sync(&req.to_string(), meta);
|
let res = io.handle_request_sync(&req.to_string(), meta);
|
||||||
|
|
||||||
|
@ -424,7 +428,7 @@ mod tests {
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"method": "registerNode",
|
"method": "registerNode",
|
||||||
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
|
"params": [node_pubkey, sig, msg.as_bytes()],
|
||||||
});
|
});
|
||||||
let _res = io.handle_request_sync(&req.to_string(), meta.clone());
|
let _res = io.handle_request_sync(&req.to_string(), meta.clone());
|
||||||
|
|
||||||
|
@ -432,7 +436,7 @@ mod tests {
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"method": "deregisterNode",
|
"method": "deregisterNode",
|
||||||
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
|
"params": [node_pubkey, sig, msg.as_bytes()],
|
||||||
});
|
});
|
||||||
let _res = io.handle_request_sync(&req.to_string(), meta.clone());
|
let _res = io.handle_request_sync(&req.to_string(), meta.clone());
|
||||||
|
|
||||||
|
@ -440,7 +444,7 @@ mod tests {
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"method": "signVote",
|
"method": "signVote",
|
||||||
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
|
"params": [node_pubkey, sig, msg.as_bytes()],
|
||||||
});
|
});
|
||||||
let res = io.handle_request_sync(&req.to_string(), meta);
|
let res = io.handle_request_sync(&req.to_string(), meta);
|
||||||
|
|
||||||
|
@ -473,7 +477,7 @@ mod tests {
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"method": "registerNode",
|
"method": "registerNode",
|
||||||
"params": [node_pubkey.to_string(), sig, msg.as_bytes()],
|
"params": [node_pubkey, sig, msg.as_bytes()],
|
||||||
});
|
});
|
||||||
let _res = io.handle_request_sync(&req.to_string(), meta.clone());
|
let _res = io.handle_request_sync(&req.to_string(), meta.clone());
|
||||||
|
|
||||||
|
@ -481,7 +485,7 @@ mod tests {
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"method": "signVote",
|
"method": "signVote",
|
||||||
"params": [node_pubkey.to_string(), sig, msg1.as_bytes()],
|
"params": [node_pubkey, sig, msg1.as_bytes()],
|
||||||
});
|
});
|
||||||
let res = io.handle_request_sync(&req.to_string(), meta);
|
let res = io.handle_request_sync(&req.to_string(), meta);
|
||||||
|
|
||||||
|
|
|
@ -820,6 +820,7 @@ mod tests {
|
||||||
use solana_sdk::signature::{gen_keypair_file, read_keypair, read_pkcs8, Keypair, KeypairUtil};
|
use solana_sdk::signature::{gen_keypair_file, read_keypair, read_pkcs8, Keypair, KeypairUtil};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::fs::remove_dir_all;
|
use std::fs::remove_dir_all;
|
||||||
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
@ -838,7 +839,8 @@ mod tests {
|
||||||
leader,
|
leader,
|
||||||
&ledger_path,
|
&ledger_path,
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
Arc::new(Keypair::new()),
|
&leader_pubkey,
|
||||||
|
&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
|
||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
||||||
|
@ -1205,7 +1207,8 @@ mod tests {
|
||||||
leader,
|
leader,
|
||||||
&ledger_path,
|
&ledger_path,
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
Arc::new(Keypair::new()),
|
&leader_pubkey,
|
||||||
|
&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
|
||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
||||||
|
@ -1265,7 +1268,8 @@ mod tests {
|
||||||
leader,
|
leader,
|
||||||
&ledger_path,
|
&ledger_path,
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
Arc::new(Keypair::new()),
|
&leader_pubkey,
|
||||||
|
&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
|
||||||
None,
|
None,
|
||||||
false,
|
false,
|
||||||
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
LeaderScheduler::from_bootstrap_leader(leader_pubkey),
|
||||||
|
@ -1341,7 +1345,8 @@ mod tests {
|
||||||
let last_id = bank.last_id();
|
let last_id = bank.last_id();
|
||||||
let server = Fullnode::new_with_bank(
|
let server = Fullnode::new_with_bank(
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
vote_account_keypair,
|
&vote_account_keypair.pubkey(),
|
||||||
|
&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
|
||||||
bank,
|
bank,
|
||||||
None,
|
None,
|
||||||
0,
|
0,
|
||||||
|
@ -1467,7 +1472,8 @@ mod tests {
|
||||||
let last_id = bank.last_id();
|
let last_id = bank.last_id();
|
||||||
let server = Fullnode::new_with_bank(
|
let server = Fullnode::new_with_bank(
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
vote_account_keypair,
|
&vote_account_keypair.pubkey(),
|
||||||
|
&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
|
||||||
bank,
|
bank,
|
||||||
None,
|
None,
|
||||||
0,
|
0,
|
||||||
|
@ -1582,7 +1588,8 @@ mod tests {
|
||||||
let last_id = bank.last_id();
|
let last_id = bank.last_id();
|
||||||
let server = Fullnode::new_with_bank(
|
let server = Fullnode::new_with_bank(
|
||||||
leader_keypair,
|
leader_keypair,
|
||||||
vote_account_keypair,
|
&vote_account_keypair.pubkey(),
|
||||||
|
&SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0),
|
||||||
bank,
|
bank,
|
||||||
None,
|
None,
|
||||||
0,
|
0,
|
||||||
|
|
Loading…
Reference in New Issue