Forward transactions to the expected leader instead of your own TPU port (#12012)
Co-authored-by: Carl <carl@solana.com>
This commit is contained in:
@ -2664,6 +2664,7 @@ pub mod tests {
|
|||||||
Arc::new(SendTransactionService::new(
|
Arc::new(SendTransactionService::new(
|
||||||
&cluster_info,
|
&cluster_info,
|
||||||
&bank_forks,
|
&bank_forks,
|
||||||
|
None,
|
||||||
&exit,
|
&exit,
|
||||||
)),
|
)),
|
||||||
&runtime::Runtime::new().unwrap(),
|
&runtime::Runtime::new().unwrap(),
|
||||||
@ -2717,6 +2718,7 @@ pub mod tests {
|
|||||||
Arc::new(SendTransactionService::new(
|
Arc::new(SendTransactionService::new(
|
||||||
&cluster_info,
|
&cluster_info,
|
||||||
&bank_forks,
|
&bank_forks,
|
||||||
|
None,
|
||||||
&exit,
|
&exit,
|
||||||
)),
|
)),
|
||||||
&runtime::Runtime::new().unwrap(),
|
&runtime::Runtime::new().unwrap(),
|
||||||
@ -3983,6 +3985,7 @@ pub mod tests {
|
|||||||
Arc::new(SendTransactionService::new(
|
Arc::new(SendTransactionService::new(
|
||||||
&cluster_info,
|
&cluster_info,
|
||||||
&bank_forks,
|
&bank_forks,
|
||||||
|
None,
|
||||||
&exit,
|
&exit,
|
||||||
)),
|
)),
|
||||||
&runtime::Runtime::new().unwrap(),
|
&runtime::Runtime::new().unwrap(),
|
||||||
@ -4029,6 +4032,7 @@ pub mod tests {
|
|||||||
Arc::new(SendTransactionService::new(
|
Arc::new(SendTransactionService::new(
|
||||||
&cluster_info,
|
&cluster_info,
|
||||||
&bank_forks,
|
&bank_forks,
|
||||||
|
None,
|
||||||
&exit,
|
&exit,
|
||||||
)),
|
)),
|
||||||
&runtime::Runtime::new().unwrap(),
|
&runtime::Runtime::new().unwrap(),
|
||||||
@ -4225,6 +4229,7 @@ pub mod tests {
|
|||||||
Arc::new(SendTransactionService::new(
|
Arc::new(SendTransactionService::new(
|
||||||
&cluster_info,
|
&cluster_info,
|
||||||
&bank_forks,
|
&bank_forks,
|
||||||
|
None,
|
||||||
&exit,
|
&exit,
|
||||||
)),
|
)),
|
||||||
&runtime::Runtime::new().unwrap(),
|
&runtime::Runtime::new().unwrap(),
|
||||||
@ -4259,6 +4264,7 @@ pub mod tests {
|
|||||||
Arc::new(SendTransactionService::new(
|
Arc::new(SendTransactionService::new(
|
||||||
&cluster_info,
|
&cluster_info,
|
||||||
&bank_forks,
|
&bank_forks,
|
||||||
|
None,
|
||||||
&exit,
|
&exit,
|
||||||
)),
|
)),
|
||||||
&runtime::Runtime::new().unwrap(),
|
&runtime::Runtime::new().unwrap(),
|
||||||
@ -4352,6 +4358,7 @@ pub mod tests {
|
|||||||
Arc::new(SendTransactionService::new(
|
Arc::new(SendTransactionService::new(
|
||||||
&cluster_info,
|
&cluster_info,
|
||||||
&bank_forks,
|
&bank_forks,
|
||||||
|
None,
|
||||||
&exit,
|
&exit,
|
||||||
)),
|
)),
|
||||||
&runtime::Runtime::new().unwrap(),
|
&runtime::Runtime::new().unwrap(),
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
//! The `rpc_service` module implements the Solana JSON RPC service.
|
//! The `rpc_service` module implements the Solana JSON RPC service.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cluster_info::ClusterInfo, commitment::BlockCommitmentCache, rpc::*, rpc_health::*,
|
cluster_info::ClusterInfo, commitment::BlockCommitmentCache, poh_recorder::PohRecorder, rpc::*,
|
||||||
|
rpc_health::*, send_transaction_service::LeaderInfo,
|
||||||
send_transaction_service::SendTransactionService, validator::ValidatorExit,
|
send_transaction_service::SendTransactionService, validator::ValidatorExit,
|
||||||
};
|
};
|
||||||
use jsonrpc_core::MetaIoHandler;
|
use jsonrpc_core::MetaIoHandler;
|
||||||
@ -21,7 +22,7 @@ use std::{
|
|||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
sync::{mpsc::channel, Arc, RwLock},
|
sync::{mpsc::channel, Arc, Mutex, RwLock},
|
||||||
thread::{self, Builder, JoinHandle},
|
thread::{self, Builder, JoinHandle},
|
||||||
};
|
};
|
||||||
use tokio::runtime;
|
use tokio::runtime;
|
||||||
@ -237,6 +238,7 @@ impl JsonRpcService {
|
|||||||
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
|
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
|
||||||
blockstore: Arc<Blockstore>,
|
blockstore: Arc<Blockstore>,
|
||||||
cluster_info: Arc<ClusterInfo>,
|
cluster_info: Arc<ClusterInfo>,
|
||||||
|
poh_recorder: Option<Arc<Mutex<PohRecorder>>>,
|
||||||
genesis_hash: Hash,
|
genesis_hash: Hash,
|
||||||
ledger_path: &Path,
|
ledger_path: &Path,
|
||||||
validator_exit: Arc<RwLock<Option<ValidatorExit>>>,
|
validator_exit: Arc<RwLock<Option<ValidatorExit>>>,
|
||||||
@ -254,9 +256,12 @@ impl JsonRpcService {
|
|||||||
));
|
));
|
||||||
|
|
||||||
let exit_send_transaction_service = Arc::new(AtomicBool::new(false));
|
let exit_send_transaction_service = Arc::new(AtomicBool::new(false));
|
||||||
|
let leader_info =
|
||||||
|
poh_recorder.map(|recorder| LeaderInfo::new(cluster_info.clone(), recorder));
|
||||||
let send_transaction_service = Arc::new(SendTransactionService::new(
|
let send_transaction_service = Arc::new(SendTransactionService::new(
|
||||||
&cluster_info,
|
&cluster_info,
|
||||||
&bank_forks,
|
&bank_forks,
|
||||||
|
leader_info,
|
||||||
&exit_send_transaction_service,
|
&exit_send_transaction_service,
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -418,6 +423,7 @@ mod tests {
|
|||||||
block_commitment_cache,
|
block_commitment_cache,
|
||||||
blockstore,
|
blockstore,
|
||||||
cluster_info,
|
cluster_info,
|
||||||
|
None,
|
||||||
Hash::default(),
|
Hash::default(),
|
||||||
&PathBuf::from("farf"),
|
&PathBuf::from("farf"),
|
||||||
validator_exit,
|
validator_exit,
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use crate::cluster_info::ClusterInfo;
|
use crate::{cluster_info::ClusterInfo, poh_recorder::PohRecorder};
|
||||||
|
use log::*;
|
||||||
use solana_ledger::bank_forks::BankForks;
|
use solana_ledger::bank_forks::BankForks;
|
||||||
use solana_metrics::{datapoint_warn, inc_new_counter_info};
|
use solana_metrics::{datapoint_warn, inc_new_counter_info};
|
||||||
use solana_runtime::bank::Bank;
|
use solana_runtime::bank::Bank;
|
||||||
use solana_sdk::{clock::Slot, signature::Signature};
|
use solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
net::{SocketAddr, UdpSocket},
|
net::{SocketAddr, UdpSocket},
|
||||||
@ -25,6 +26,39 @@ pub struct SendTransactionService {
|
|||||||
tpu_address: SocketAddr,
|
tpu_address: SocketAddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct LeaderInfo {
|
||||||
|
cluster_info: Arc<ClusterInfo>,
|
||||||
|
poh_recorder: Arc<Mutex<PohRecorder>>,
|
||||||
|
recent_peers: HashMap<Pubkey, SocketAddr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LeaderInfo {
|
||||||
|
pub fn new(cluster_info: Arc<ClusterInfo>, poh_recorder: Arc<Mutex<PohRecorder>>) -> Self {
|
||||||
|
Self {
|
||||||
|
cluster_info,
|
||||||
|
poh_recorder,
|
||||||
|
recent_peers: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn refresh_recent_peers(&mut self) {
|
||||||
|
self.recent_peers = self
|
||||||
|
.cluster_info
|
||||||
|
.tpu_peers()
|
||||||
|
.into_iter()
|
||||||
|
.map(|ci| (ci.id, ci.tpu))
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_leader_tpu(&self) -> Option<&SocketAddr> {
|
||||||
|
self.poh_recorder
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.leader_after_n_slots(0)
|
||||||
|
.and_then(|leader| self.recent_peers.get(&leader))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct TransactionInfo {
|
struct TransactionInfo {
|
||||||
signature: Signature,
|
signature: Signature,
|
||||||
wire_transaction: Vec<u8>,
|
wire_transaction: Vec<u8>,
|
||||||
@ -44,12 +78,19 @@ impl SendTransactionService {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
cluster_info: &Arc<ClusterInfo>,
|
cluster_info: &Arc<ClusterInfo>,
|
||||||
bank_forks: &Arc<RwLock<BankForks>>,
|
bank_forks: &Arc<RwLock<BankForks>>,
|
||||||
|
leader_info: Option<LeaderInfo>,
|
||||||
exit: &Arc<AtomicBool>,
|
exit: &Arc<AtomicBool>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let (sender, receiver) = channel::<TransactionInfo>();
|
let (sender, receiver) = channel::<TransactionInfo>();
|
||||||
let tpu_address = cluster_info.my_contact_info().tpu;
|
let tpu_address = cluster_info.my_contact_info().tpu;
|
||||||
|
|
||||||
let thread = Self::retry_thread(receiver, bank_forks.clone(), tpu_address, exit.clone());
|
let thread = Self::retry_thread(
|
||||||
|
receiver,
|
||||||
|
bank_forks.clone(),
|
||||||
|
leader_info,
|
||||||
|
tpu_address,
|
||||||
|
exit.clone(),
|
||||||
|
);
|
||||||
Self {
|
Self {
|
||||||
thread,
|
thread,
|
||||||
sender: Mutex::new(sender),
|
sender: Mutex::new(sender),
|
||||||
@ -61,6 +102,7 @@ impl SendTransactionService {
|
|||||||
fn retry_thread(
|
fn retry_thread(
|
||||||
receiver: Receiver<TransactionInfo>,
|
receiver: Receiver<TransactionInfo>,
|
||||||
bank_forks: Arc<RwLock<BankForks>>,
|
bank_forks: Arc<RwLock<BankForks>>,
|
||||||
|
mut leader_info: Option<LeaderInfo>,
|
||||||
tpu_address: SocketAddr,
|
tpu_address: SocketAddr,
|
||||||
exit: Arc<AtomicBool>,
|
exit: Arc<AtomicBool>,
|
||||||
) -> JoinHandle<()> {
|
) -> JoinHandle<()> {
|
||||||
@ -68,6 +110,10 @@ impl SendTransactionService {
|
|||||||
let mut transactions = HashMap::new();
|
let mut transactions = HashMap::new();
|
||||||
let send_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
let send_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||||
|
|
||||||
|
if let Some(leader_info) = leader_info.as_mut() {
|
||||||
|
leader_info.refresh_recent_peers();
|
||||||
|
}
|
||||||
|
|
||||||
Builder::new()
|
Builder::new()
|
||||||
.name("send-tx-svc".to_string())
|
.name("send-tx-svc".to_string())
|
||||||
.spawn(move || loop {
|
.spawn(move || loop {
|
||||||
@ -76,6 +122,15 @@ impl SendTransactionService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(transaction_info) = receiver.recv_timeout(Duration::from_secs(1)) {
|
if let Ok(transaction_info) = receiver.recv_timeout(Duration::from_secs(1)) {
|
||||||
|
let address = leader_info
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|leader_info| leader_info.get_leader_tpu())
|
||||||
|
.unwrap_or(&tpu_address);
|
||||||
|
Self::send_transaction(
|
||||||
|
&send_socket,
|
||||||
|
address,
|
||||||
|
&transaction_info.wire_transaction,
|
||||||
|
);
|
||||||
if transactions.len() < MAX_TRANSACTION_QUEUE_SIZE {
|
if transactions.len() < MAX_TRANSACTION_QUEUE_SIZE {
|
||||||
transactions.insert(transaction_info.signature, transaction_info);
|
transactions.insert(transaction_info.signature, transaction_info);
|
||||||
} else {
|
} else {
|
||||||
@ -99,9 +154,13 @@ impl SendTransactionService {
|
|||||||
&send_socket,
|
&send_socket,
|
||||||
&tpu_address,
|
&tpu_address,
|
||||||
&mut transactions,
|
&mut transactions,
|
||||||
|
&leader_info,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
last_status_check = Instant::now();
|
last_status_check = Instant::now();
|
||||||
|
if let Some(leader_info) = leader_info.as_mut() {
|
||||||
|
leader_info.refresh_recent_peers();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -113,6 +172,7 @@ impl SendTransactionService {
|
|||||||
send_socket: &UdpSocket,
|
send_socket: &UdpSocket,
|
||||||
tpu_address: &SocketAddr,
|
tpu_address: &SocketAddr,
|
||||||
transactions: &mut HashMap<Signature, TransactionInfo>,
|
transactions: &mut HashMap<Signature, TransactionInfo>,
|
||||||
|
leader_info: &Option<LeaderInfo>,
|
||||||
) -> ProcessTransactionsResult {
|
) -> ProcessTransactionsResult {
|
||||||
let mut result = ProcessTransactionsResult::default();
|
let mut result = ProcessTransactionsResult::default();
|
||||||
|
|
||||||
@ -137,7 +197,10 @@ impl SendTransactionService {
|
|||||||
inc_new_counter_info!("send_transaction_service-retry", 1);
|
inc_new_counter_info!("send_transaction_service-retry", 1);
|
||||||
Self::send_transaction(
|
Self::send_transaction(
|
||||||
&send_socket,
|
&send_socket,
|
||||||
&tpu_address,
|
leader_info
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|leader_info| leader_info.get_leader_tpu())
|
||||||
|
.unwrap_or(&tpu_address),
|
||||||
&transaction_info.wire_transaction,
|
&transaction_info.wire_transaction,
|
||||||
);
|
);
|
||||||
true
|
true
|
||||||
@ -203,7 +266,7 @@ mod test {
|
|||||||
let exit = Arc::new(AtomicBool::new(false));
|
let exit = Arc::new(AtomicBool::new(false));
|
||||||
|
|
||||||
let send_tranaction_service =
|
let send_tranaction_service =
|
||||||
SendTransactionService::new(&cluster_info, &bank_forks, &exit);
|
SendTransactionService::new(&cluster_info, &bank_forks, None, &exit);
|
||||||
|
|
||||||
exit.store(true, Ordering::Relaxed);
|
exit.store(true, Ordering::Relaxed);
|
||||||
send_tranaction_service.join().unwrap();
|
send_tranaction_service.join().unwrap();
|
||||||
@ -211,8 +274,6 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn process_transactions() {
|
fn process_transactions() {
|
||||||
solana_logger::setup();
|
|
||||||
|
|
||||||
let (bank_forks, mint_keypair, _voting_keypair) = new_bank_forks();
|
let (bank_forks, mint_keypair, _voting_keypair) = new_bank_forks();
|
||||||
let cluster_info = ClusterInfo::default();
|
let cluster_info = ClusterInfo::default();
|
||||||
let send_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
let send_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||||
@ -263,6 +324,7 @@ mod test {
|
|||||||
&send_socket,
|
&send_socket,
|
||||||
&tpu_address,
|
&tpu_address,
|
||||||
&mut transactions,
|
&mut transactions,
|
||||||
|
&None,
|
||||||
);
|
);
|
||||||
assert!(transactions.is_empty());
|
assert!(transactions.is_empty());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -288,6 +350,7 @@ mod test {
|
|||||||
&send_socket,
|
&send_socket,
|
||||||
&tpu_address,
|
&tpu_address,
|
||||||
&mut transactions,
|
&mut transactions,
|
||||||
|
&None,
|
||||||
);
|
);
|
||||||
assert!(transactions.is_empty());
|
assert!(transactions.is_empty());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -313,6 +376,7 @@ mod test {
|
|||||||
&send_socket,
|
&send_socket,
|
||||||
&tpu_address,
|
&tpu_address,
|
||||||
&mut transactions,
|
&mut transactions,
|
||||||
|
&None,
|
||||||
);
|
);
|
||||||
assert!(transactions.is_empty());
|
assert!(transactions.is_empty());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -338,6 +402,7 @@ mod test {
|
|||||||
&send_socket,
|
&send_socket,
|
||||||
&tpu_address,
|
&tpu_address,
|
||||||
&mut transactions,
|
&mut transactions,
|
||||||
|
&None,
|
||||||
);
|
);
|
||||||
assert_eq!(transactions.len(), 1);
|
assert_eq!(transactions.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -364,6 +429,7 @@ mod test {
|
|||||||
&send_socket,
|
&send_socket,
|
||||||
&tpu_address,
|
&tpu_address,
|
||||||
&mut transactions,
|
&mut transactions,
|
||||||
|
&None,
|
||||||
);
|
);
|
||||||
assert_eq!(transactions.len(), 1);
|
assert_eq!(transactions.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -279,38 +279,6 @@ impl Validator {
|
|||||||
block_commitment_cache.clone(),
|
block_commitment_cache.clone(),
|
||||||
));
|
));
|
||||||
|
|
||||||
let rpc_override_health_check = Arc::new(AtomicBool::new(false));
|
|
||||||
let rpc_service = config.rpc_ports.map(|(rpc_port, rpc_pubsub_port)| {
|
|
||||||
if ContactInfo::is_valid_address(&node.info.rpc) {
|
|
||||||
assert!(ContactInfo::is_valid_address(&node.info.rpc_pubsub));
|
|
||||||
assert_eq!(rpc_port, node.info.rpc.port());
|
|
||||||
assert_eq!(rpc_pubsub_port, node.info.rpc_pubsub.port());
|
|
||||||
} else {
|
|
||||||
assert!(!ContactInfo::is_valid_address(&node.info.rpc_pubsub));
|
|
||||||
}
|
|
||||||
(
|
|
||||||
JsonRpcService::new(
|
|
||||||
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), rpc_port),
|
|
||||||
config.rpc_config.clone(),
|
|
||||||
config.snapshot_config.clone(),
|
|
||||||
bank_forks.clone(),
|
|
||||||
block_commitment_cache.clone(),
|
|
||||||
blockstore.clone(),
|
|
||||||
cluster_info.clone(),
|
|
||||||
genesis_config.hash(),
|
|
||||||
ledger_path,
|
|
||||||
validator_exit.clone(),
|
|
||||||
config.trusted_validators.clone(),
|
|
||||||
rpc_override_health_check.clone(),
|
|
||||||
),
|
|
||||||
PubSubService::new(
|
|
||||||
&subscriptions,
|
|
||||||
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), rpc_pubsub_port),
|
|
||||||
&exit,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"Starting PoH: epoch={} slot={} tick_height={} blockhash={} leader={:?}",
|
"Starting PoH: epoch={} slot={} tick_height={} blockhash={} leader={:?}",
|
||||||
bank.epoch(),
|
bank.epoch(),
|
||||||
@ -333,7 +301,7 @@ impl Validator {
|
|||||||
std::thread::park();
|
std::thread::park();
|
||||||
}
|
}
|
||||||
|
|
||||||
let poh_config = Arc::new(genesis_config.poh_config);
|
let poh_config = Arc::new(genesis_config.poh_config.clone());
|
||||||
let (mut poh_recorder, entry_receiver) = PohRecorder::new_with_clear_signal(
|
let (mut poh_recorder, entry_receiver) = PohRecorder::new_with_clear_signal(
|
||||||
bank.tick_height(),
|
bank.tick_height(),
|
||||||
bank.last_blockhash(),
|
bank.last_blockhash(),
|
||||||
@ -357,6 +325,39 @@ impl Validator {
|
|||||||
}
|
}
|
||||||
let poh_recorder = Arc::new(Mutex::new(poh_recorder));
|
let poh_recorder = Arc::new(Mutex::new(poh_recorder));
|
||||||
|
|
||||||
|
let rpc_override_health_check = Arc::new(AtomicBool::new(false));
|
||||||
|
let rpc_service = config.rpc_ports.map(|(rpc_port, rpc_pubsub_port)| {
|
||||||
|
if ContactInfo::is_valid_address(&node.info.rpc) {
|
||||||
|
assert!(ContactInfo::is_valid_address(&node.info.rpc_pubsub));
|
||||||
|
assert_eq!(rpc_port, node.info.rpc.port());
|
||||||
|
assert_eq!(rpc_pubsub_port, node.info.rpc_pubsub.port());
|
||||||
|
} else {
|
||||||
|
assert!(!ContactInfo::is_valid_address(&node.info.rpc_pubsub));
|
||||||
|
}
|
||||||
|
(
|
||||||
|
JsonRpcService::new(
|
||||||
|
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), rpc_port),
|
||||||
|
config.rpc_config.clone(),
|
||||||
|
config.snapshot_config.clone(),
|
||||||
|
bank_forks.clone(),
|
||||||
|
block_commitment_cache.clone(),
|
||||||
|
blockstore.clone(),
|
||||||
|
cluster_info.clone(),
|
||||||
|
Some(poh_recorder.clone()),
|
||||||
|
genesis_config.hash(),
|
||||||
|
ledger_path,
|
||||||
|
validator_exit.clone(),
|
||||||
|
config.trusted_validators.clone(),
|
||||||
|
rpc_override_health_check.clone(),
|
||||||
|
),
|
||||||
|
PubSubService::new(
|
||||||
|
&subscriptions,
|
||||||
|
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), rpc_pubsub_port),
|
||||||
|
&exit,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
let ip_echo_server = solana_net_utils::ip_echo_server(node.sockets.ip_echo.unwrap());
|
let ip_echo_server = solana_net_utils::ip_echo_server(node.sockets.ip_echo.unwrap());
|
||||||
|
|
||||||
let gossip_service = GossipService::new(
|
let gossip_service = GossipService::new(
|
||||||
|
Reference in New Issue
Block a user