Add SingleGossip commitment level to use for subscriptions (#10147)
automerge
This commit is contained in:
parent
2324eb9ff9
commit
2928c5d103
|
@ -92,7 +92,10 @@ impl JsonRpcRequestProcessor {
|
||||||
debug!("RPC using node root: {:?}", slot);
|
debug!("RPC using node root: {:?}", slot);
|
||||||
Ok(r_bank_forks.get(slot).cloned().unwrap())
|
Ok(r_bank_forks.get(slot).cloned().unwrap())
|
||||||
}
|
}
|
||||||
Some(commitment_config) if commitment_config.commitment == CommitmentLevel::Single => {
|
Some(commitment_config)
|
||||||
|
if commitment_config.commitment == CommitmentLevel::Single
|
||||||
|
|| commitment_config.commitment == CommitmentLevel::SingleGossip =>
|
||||||
|
{
|
||||||
let slot = self
|
let slot = self
|
||||||
.block_commitment_cache
|
.block_commitment_cache
|
||||||
.read()
|
.read()
|
||||||
|
|
|
@ -57,6 +57,7 @@ enum NotificationEntry {
|
||||||
Vote(Vote),
|
Vote(Vote),
|
||||||
Root(Slot),
|
Root(Slot),
|
||||||
Bank(CacheSlotInfo),
|
Bank(CacheSlotInfo),
|
||||||
|
Gossip(Slot),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for NotificationEntry {
|
impl std::fmt::Debug for NotificationEntry {
|
||||||
|
@ -70,6 +71,7 @@ impl std::fmt::Debug for NotificationEntry {
|
||||||
"Bank({{current_slot: {:?}}})",
|
"Bank({{current_slot: {:?}}})",
|
||||||
cache_slot_info.current_slot
|
cache_slot_info.current_slot
|
||||||
),
|
),
|
||||||
|
NotificationEntry::Gossip(slot) => write!(f, "Gossip({:?})", slot),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,7 +173,9 @@ where
|
||||||
CommitmentLevel::Max => cache_slot_info.largest_confirmed_root,
|
CommitmentLevel::Max => cache_slot_info.largest_confirmed_root,
|
||||||
CommitmentLevel::Recent => cache_slot_info.current_slot,
|
CommitmentLevel::Recent => cache_slot_info.current_slot,
|
||||||
CommitmentLevel::Root => cache_slot_info.node_root,
|
CommitmentLevel::Root => cache_slot_info.node_root,
|
||||||
CommitmentLevel::Single => cache_slot_info.highest_confirmed_slot,
|
CommitmentLevel::Single | CommitmentLevel::SingleGossip => {
|
||||||
|
cache_slot_info.highest_confirmed_slot
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let results = {
|
let results = {
|
||||||
let bank_forks = bank_forks.read().unwrap();
|
let bank_forks = bank_forks.read().unwrap();
|
||||||
|
@ -258,6 +262,9 @@ struct Subscriptions {
|
||||||
account_subscriptions: Arc<RpcAccountSubscriptions>,
|
account_subscriptions: Arc<RpcAccountSubscriptions>,
|
||||||
program_subscriptions: Arc<RpcProgramSubscriptions>,
|
program_subscriptions: Arc<RpcProgramSubscriptions>,
|
||||||
signature_subscriptions: Arc<RpcSignatureSubscriptions>,
|
signature_subscriptions: Arc<RpcSignatureSubscriptions>,
|
||||||
|
gossip_account_subscriptions: Arc<RpcAccountSubscriptions>,
|
||||||
|
gossip_program_subscriptions: Arc<RpcProgramSubscriptions>,
|
||||||
|
gossip_signature_subscriptions: Arc<RpcSignatureSubscriptions>,
|
||||||
slot_subscriptions: Arc<RpcSlotSubscriptions>,
|
slot_subscriptions: Arc<RpcSlotSubscriptions>,
|
||||||
vote_subscriptions: Arc<RpcVoteSubscriptions>,
|
vote_subscriptions: Arc<RpcVoteSubscriptions>,
|
||||||
root_subscriptions: Arc<RpcRootSubscriptions>,
|
root_subscriptions: Arc<RpcRootSubscriptions>,
|
||||||
|
@ -270,6 +277,7 @@ pub struct RpcSubscriptions {
|
||||||
notifier_runtime: Option<Runtime>,
|
notifier_runtime: Option<Runtime>,
|
||||||
bank_forks: Arc<RwLock<BankForks>>,
|
bank_forks: Arc<RwLock<BankForks>>,
|
||||||
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
|
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
|
||||||
|
last_checked_slots: Arc<RwLock<HashMap<CommitmentLevel, Slot>>>,
|
||||||
exit: Arc<AtomicBool>,
|
exit: Arc<AtomicBool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,6 +303,9 @@ impl RpcSubscriptions {
|
||||||
let account_subscriptions = Arc::new(RpcAccountSubscriptions::default());
|
let account_subscriptions = Arc::new(RpcAccountSubscriptions::default());
|
||||||
let program_subscriptions = Arc::new(RpcProgramSubscriptions::default());
|
let program_subscriptions = Arc::new(RpcProgramSubscriptions::default());
|
||||||
let signature_subscriptions = Arc::new(RpcSignatureSubscriptions::default());
|
let signature_subscriptions = Arc::new(RpcSignatureSubscriptions::default());
|
||||||
|
let gossip_account_subscriptions = Arc::new(RpcAccountSubscriptions::default());
|
||||||
|
let gossip_program_subscriptions = Arc::new(RpcProgramSubscriptions::default());
|
||||||
|
let gossip_signature_subscriptions = Arc::new(RpcSignatureSubscriptions::default());
|
||||||
let slot_subscriptions = Arc::new(RpcSlotSubscriptions::default());
|
let slot_subscriptions = Arc::new(RpcSlotSubscriptions::default());
|
||||||
let vote_subscriptions = Arc::new(RpcVoteSubscriptions::default());
|
let vote_subscriptions = Arc::new(RpcVoteSubscriptions::default());
|
||||||
let root_subscriptions = Arc::new(RpcRootSubscriptions::default());
|
let root_subscriptions = Arc::new(RpcRootSubscriptions::default());
|
||||||
|
@ -307,12 +318,18 @@ impl RpcSubscriptions {
|
||||||
account_subscriptions,
|
account_subscriptions,
|
||||||
program_subscriptions,
|
program_subscriptions,
|
||||||
signature_subscriptions,
|
signature_subscriptions,
|
||||||
|
gossip_account_subscriptions,
|
||||||
|
gossip_program_subscriptions,
|
||||||
|
gossip_signature_subscriptions,
|
||||||
slot_subscriptions,
|
slot_subscriptions,
|
||||||
vote_subscriptions,
|
vote_subscriptions,
|
||||||
root_subscriptions,
|
root_subscriptions,
|
||||||
};
|
};
|
||||||
let _subscriptions = subscriptions.clone();
|
let _subscriptions = subscriptions.clone();
|
||||||
|
|
||||||
|
let last_checked_slots = Arc::new(RwLock::new(HashMap::new()));
|
||||||
|
let _last_checked_slots = last_checked_slots.clone();
|
||||||
|
|
||||||
let notifier_runtime = RuntimeBuilder::new()
|
let notifier_runtime = RuntimeBuilder::new()
|
||||||
.core_threads(1)
|
.core_threads(1)
|
||||||
.name_prefix("solana-rpc-notifier-")
|
.name_prefix("solana-rpc-notifier-")
|
||||||
|
@ -329,6 +346,7 @@ impl RpcSubscriptions {
|
||||||
notification_receiver,
|
notification_receiver,
|
||||||
_subscriptions,
|
_subscriptions,
|
||||||
_bank_forks,
|
_bank_forks,
|
||||||
|
_last_checked_slots,
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -340,6 +358,7 @@ impl RpcSubscriptions {
|
||||||
t_cleanup: Some(t_cleanup),
|
t_cleanup: Some(t_cleanup),
|
||||||
bank_forks,
|
bank_forks,
|
||||||
block_commitment_cache,
|
block_commitment_cache,
|
||||||
|
last_checked_slots,
|
||||||
exit: exit.clone(),
|
exit: exit.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -427,11 +446,10 @@ impl RpcSubscriptions {
|
||||||
sub_id: SubscriptionId,
|
sub_id: SubscriptionId,
|
||||||
subscriber: Subscriber<Response<RpcAccount>>,
|
subscriber: Subscriber<Response<RpcAccount>>,
|
||||||
) {
|
) {
|
||||||
let mut subscriptions = self.subscriptions.account_subscriptions.write().unwrap();
|
let commitment_level = commitment
|
||||||
let slot = match commitment
|
|
||||||
.unwrap_or_else(CommitmentConfig::single)
|
.unwrap_or_else(CommitmentConfig::single)
|
||||||
.commitment
|
.commitment;
|
||||||
{
|
let slot = match commitment_level {
|
||||||
CommitmentLevel::Max => self
|
CommitmentLevel::Max => self
|
||||||
.block_commitment_cache
|
.block_commitment_cache
|
||||||
.read()
|
.read()
|
||||||
|
@ -444,6 +462,12 @@ impl RpcSubscriptions {
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.highest_confirmed_slot(),
|
.highest_confirmed_slot(),
|
||||||
|
CommitmentLevel::SingleGossip => *self
|
||||||
|
.last_checked_slots
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.get(&CommitmentLevel::SingleGossip)
|
||||||
|
.unwrap_or(&0),
|
||||||
};
|
};
|
||||||
let last_notified_slot = if let Some((_account, slot)) = self
|
let last_notified_slot = if let Some((_account, slot)) = self
|
||||||
.bank_forks
|
.bank_forks
|
||||||
|
@ -456,6 +480,15 @@ impl RpcSubscriptions {
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut subscriptions = if commitment_level == CommitmentLevel::SingleGossip {
|
||||||
|
self.subscriptions
|
||||||
|
.gossip_account_subscriptions
|
||||||
|
.write()
|
||||||
|
.unwrap()
|
||||||
|
} else {
|
||||||
|
self.subscriptions.account_subscriptions.write().unwrap()
|
||||||
|
};
|
||||||
add_subscription(
|
add_subscription(
|
||||||
&mut subscriptions,
|
&mut subscriptions,
|
||||||
pubkey,
|
pubkey,
|
||||||
|
@ -468,8 +501,17 @@ impl RpcSubscriptions {
|
||||||
|
|
||||||
pub fn remove_account_subscription(&self, id: &SubscriptionId) -> bool {
|
pub fn remove_account_subscription(&self, id: &SubscriptionId) -> bool {
|
||||||
let mut subscriptions = self.subscriptions.account_subscriptions.write().unwrap();
|
let mut subscriptions = self.subscriptions.account_subscriptions.write().unwrap();
|
||||||
|
if remove_subscription(&mut subscriptions, id) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
let mut subscriptions = self
|
||||||
|
.subscriptions
|
||||||
|
.gossip_account_subscriptions
|
||||||
|
.write()
|
||||||
|
.unwrap();
|
||||||
remove_subscription(&mut subscriptions, id)
|
remove_subscription(&mut subscriptions, id)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_program_subscription(
|
pub fn add_program_subscription(
|
||||||
&self,
|
&self,
|
||||||
|
@ -478,7 +520,17 @@ impl RpcSubscriptions {
|
||||||
sub_id: SubscriptionId,
|
sub_id: SubscriptionId,
|
||||||
subscriber: Subscriber<Response<RpcKeyedAccount>>,
|
subscriber: Subscriber<Response<RpcKeyedAccount>>,
|
||||||
) {
|
) {
|
||||||
let mut subscriptions = self.subscriptions.program_subscriptions.write().unwrap();
|
let commitment_level = commitment
|
||||||
|
.unwrap_or_else(CommitmentConfig::recent)
|
||||||
|
.commitment;
|
||||||
|
let mut subscriptions = if commitment_level == CommitmentLevel::SingleGossip {
|
||||||
|
self.subscriptions
|
||||||
|
.gossip_program_subscriptions
|
||||||
|
.write()
|
||||||
|
.unwrap()
|
||||||
|
} else {
|
||||||
|
self.subscriptions.program_subscriptions.write().unwrap()
|
||||||
|
};
|
||||||
add_subscription(
|
add_subscription(
|
||||||
&mut subscriptions,
|
&mut subscriptions,
|
||||||
program_id,
|
program_id,
|
||||||
|
@ -491,8 +543,17 @@ impl RpcSubscriptions {
|
||||||
|
|
||||||
pub fn remove_program_subscription(&self, id: &SubscriptionId) -> bool {
|
pub fn remove_program_subscription(&self, id: &SubscriptionId) -> bool {
|
||||||
let mut subscriptions = self.subscriptions.program_subscriptions.write().unwrap();
|
let mut subscriptions = self.subscriptions.program_subscriptions.write().unwrap();
|
||||||
|
if remove_subscription(&mut subscriptions, id) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
let mut subscriptions = self
|
||||||
|
.subscriptions
|
||||||
|
.gossip_program_subscriptions
|
||||||
|
.write()
|
||||||
|
.unwrap();
|
||||||
remove_subscription(&mut subscriptions, id)
|
remove_subscription(&mut subscriptions, id)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_signature_subscription(
|
pub fn add_signature_subscription(
|
||||||
&self,
|
&self,
|
||||||
|
@ -501,7 +562,17 @@ impl RpcSubscriptions {
|
||||||
sub_id: SubscriptionId,
|
sub_id: SubscriptionId,
|
||||||
subscriber: Subscriber<Response<RpcSignatureResult>>,
|
subscriber: Subscriber<Response<RpcSignatureResult>>,
|
||||||
) {
|
) {
|
||||||
let mut subscriptions = self.subscriptions.signature_subscriptions.write().unwrap();
|
let commitment_level = commitment
|
||||||
|
.unwrap_or_else(CommitmentConfig::recent)
|
||||||
|
.commitment;
|
||||||
|
let mut subscriptions = if commitment_level == CommitmentLevel::SingleGossip {
|
||||||
|
self.subscriptions
|
||||||
|
.gossip_signature_subscriptions
|
||||||
|
.write()
|
||||||
|
.unwrap()
|
||||||
|
} else {
|
||||||
|
self.subscriptions.signature_subscriptions.write().unwrap()
|
||||||
|
};
|
||||||
add_subscription(
|
add_subscription(
|
||||||
&mut subscriptions,
|
&mut subscriptions,
|
||||||
signature,
|
signature,
|
||||||
|
@ -514,8 +585,17 @@ impl RpcSubscriptions {
|
||||||
|
|
||||||
pub fn remove_signature_subscription(&self, id: &SubscriptionId) -> bool {
|
pub fn remove_signature_subscription(&self, id: &SubscriptionId) -> bool {
|
||||||
let mut subscriptions = self.subscriptions.signature_subscriptions.write().unwrap();
|
let mut subscriptions = self.subscriptions.signature_subscriptions.write().unwrap();
|
||||||
|
if remove_subscription(&mut subscriptions, id) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
let mut subscriptions = self
|
||||||
|
.subscriptions
|
||||||
|
.gossip_signature_subscriptions
|
||||||
|
.write()
|
||||||
|
.unwrap();
|
||||||
remove_subscription(&mut subscriptions, id)
|
remove_subscription(&mut subscriptions, id)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Notify subscribers of changes to any accounts or new signatures since
|
/// Notify subscribers of changes to any accounts or new signatures since
|
||||||
/// the bank's last checkpoint.
|
/// the bank's last checkpoint.
|
||||||
|
@ -523,6 +603,12 @@ impl RpcSubscriptions {
|
||||||
self.enqueue_notification(NotificationEntry::Bank(cache_slot_info));
|
self.enqueue_notification(NotificationEntry::Bank(cache_slot_info));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Notify SingleGossip commitment-level subscribers of changes to any accounts or new
|
||||||
|
/// signatures.
|
||||||
|
pub fn notify_gossip_subscribers(&self, slot: Slot) {
|
||||||
|
self.enqueue_notification(NotificationEntry::Gossip(slot));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_slot_subscription(&self, sub_id: SubscriptionId, subscriber: Subscriber<SlotInfo>) {
|
pub fn add_slot_subscription(&self, sub_id: SubscriptionId, subscriber: Subscriber<SlotInfo>) {
|
||||||
let sink = subscriber.assign_id(sub_id.clone()).unwrap();
|
let sink = subscriber.assign_id(sub_id.clone()).unwrap();
|
||||||
let mut subscriptions = self.subscriptions.slot_subscriptions.write().unwrap();
|
let mut subscriptions = self.subscriptions.slot_subscriptions.write().unwrap();
|
||||||
|
@ -594,6 +680,7 @@ impl RpcSubscriptions {
|
||||||
notification_receiver: Receiver<NotificationEntry>,
|
notification_receiver: Receiver<NotificationEntry>,
|
||||||
subscriptions: Subscriptions,
|
subscriptions: Subscriptions,
|
||||||
bank_forks: Arc<RwLock<BankForks>>,
|
bank_forks: Arc<RwLock<BankForks>>,
|
||||||
|
last_checked_slots: Arc<RwLock<HashMap<CommitmentLevel, Slot>>>,
|
||||||
) {
|
) {
|
||||||
loop {
|
loop {
|
||||||
if exit.load(Ordering::Relaxed) {
|
if exit.load(Ordering::Relaxed) {
|
||||||
|
@ -627,47 +714,32 @@ impl RpcSubscriptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NotificationEntry::Bank(cache_slot_info) => {
|
NotificationEntry::Bank(cache_slot_info) => {
|
||||||
let pubkeys: Vec<_> = {
|
RpcSubscriptions::notify_accounts_programs_signatures(
|
||||||
let subs = subscriptions.account_subscriptions.read().unwrap();
|
&subscriptions.account_subscriptions,
|
||||||
subs.keys().cloned().collect()
|
&subscriptions.program_subscriptions,
|
||||||
};
|
&subscriptions.signature_subscriptions,
|
||||||
for pubkey in &pubkeys {
|
|
||||||
Self::check_account(
|
|
||||||
pubkey,
|
|
||||||
&bank_forks,
|
&bank_forks,
|
||||||
subscriptions.account_subscriptions.clone(),
|
|
||||||
¬ifier,
|
|
||||||
&cache_slot_info,
|
&cache_slot_info,
|
||||||
);
|
¬ifier,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
NotificationEntry::Gossip(slot) => {
|
||||||
let programs: Vec<_> = {
|
let _ = last_checked_slots
|
||||||
let subs = subscriptions.program_subscriptions.read().unwrap();
|
.write()
|
||||||
subs.keys().cloned().collect()
|
.unwrap()
|
||||||
|
.insert(CommitmentLevel::SingleGossip, slot);
|
||||||
|
let cache_slot_info = CacheSlotInfo {
|
||||||
|
highest_confirmed_slot: slot,
|
||||||
|
..CacheSlotInfo::default()
|
||||||
};
|
};
|
||||||
for program_id in &programs {
|
RpcSubscriptions::notify_accounts_programs_signatures(
|
||||||
Self::check_program(
|
&subscriptions.gossip_account_subscriptions,
|
||||||
program_id,
|
&subscriptions.gossip_program_subscriptions,
|
||||||
|
&subscriptions.gossip_signature_subscriptions,
|
||||||
&bank_forks,
|
&bank_forks,
|
||||||
subscriptions.program_subscriptions.clone(),
|
|
||||||
¬ifier,
|
|
||||||
&cache_slot_info,
|
&cache_slot_info,
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let signatures: Vec<_> = {
|
|
||||||
let subs = subscriptions.signature_subscriptions.read().unwrap();
|
|
||||||
subs.keys().cloned().collect()
|
|
||||||
};
|
|
||||||
for signature in &signatures {
|
|
||||||
Self::check_signature(
|
|
||||||
signature,
|
|
||||||
&bank_forks,
|
|
||||||
subscriptions.signature_subscriptions.clone(),
|
|
||||||
¬ifier,
|
¬ifier,
|
||||||
&cache_slot_info,
|
)
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(RecvTimeoutError::Timeout) => {
|
Err(RecvTimeoutError::Timeout) => {
|
||||||
|
@ -681,6 +753,57 @@ impl RpcSubscriptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn notify_accounts_programs_signatures(
|
||||||
|
account_subscriptions: &Arc<RpcAccountSubscriptions>,
|
||||||
|
program_subscriptions: &Arc<RpcProgramSubscriptions>,
|
||||||
|
signature_subscriptions: &Arc<RpcSignatureSubscriptions>,
|
||||||
|
bank_forks: &Arc<RwLock<BankForks>>,
|
||||||
|
cache_slot_info: &CacheSlotInfo,
|
||||||
|
notifier: &RpcNotifier,
|
||||||
|
) {
|
||||||
|
let pubkeys: Vec<_> = {
|
||||||
|
let subs = account_subscriptions.read().unwrap();
|
||||||
|
subs.keys().cloned().collect()
|
||||||
|
};
|
||||||
|
for pubkey in &pubkeys {
|
||||||
|
Self::check_account(
|
||||||
|
pubkey,
|
||||||
|
&bank_forks,
|
||||||
|
account_subscriptions.clone(),
|
||||||
|
¬ifier,
|
||||||
|
&cache_slot_info,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let programs: Vec<_> = {
|
||||||
|
let subs = program_subscriptions.read().unwrap();
|
||||||
|
subs.keys().cloned().collect()
|
||||||
|
};
|
||||||
|
for program_id in &programs {
|
||||||
|
Self::check_program(
|
||||||
|
program_id,
|
||||||
|
&bank_forks,
|
||||||
|
program_subscriptions.clone(),
|
||||||
|
¬ifier,
|
||||||
|
&cache_slot_info,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let signatures: Vec<_> = {
|
||||||
|
let subs = signature_subscriptions.read().unwrap();
|
||||||
|
subs.keys().cloned().collect()
|
||||||
|
};
|
||||||
|
for signature in &signatures {
|
||||||
|
Self::check_signature(
|
||||||
|
signature,
|
||||||
|
&bank_forks,
|
||||||
|
signature_subscriptions.clone(),
|
||||||
|
¬ifier,
|
||||||
|
&cache_slot_info,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn shutdown(&mut self) -> std::thread::Result<()> {
|
fn shutdown(&mut self) -> std::thread::Result<()> {
|
||||||
if let Some(runtime) = self.notifier_runtime.take() {
|
if let Some(runtime) = self.notifier_runtime.take() {
|
||||||
info!("RPC Notifier runtime - shutting down");
|
info!("RPC Notifier runtime - shutting down");
|
||||||
|
@ -1232,4 +1355,135 @@ pub(crate) mod tests {
|
||||||
assert_eq!(subscriptions.len(), (num_keys - 1) as usize);
|
assert_eq!(subscriptions.len(), (num_keys - 1) as usize);
|
||||||
assert!(subscriptions.get(&0).is_none());
|
assert!(subscriptions.get(&0).is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn test_gossip_separate_account_notifications() {
|
||||||
|
let GenesisConfigInfo {
|
||||||
|
genesis_config,
|
||||||
|
mint_keypair,
|
||||||
|
..
|
||||||
|
} = create_genesis_config(100);
|
||||||
|
let ledger_path = get_tmp_ledger_path!();
|
||||||
|
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
|
||||||
|
let bank = Bank::new(&genesis_config);
|
||||||
|
let blockhash = bank.last_blockhash();
|
||||||
|
let bank_forks = Arc::new(RwLock::new(BankForks::new(0, bank)));
|
||||||
|
let bank0 = bank_forks.read().unwrap().get(0).unwrap().clone();
|
||||||
|
let bank1 = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
|
||||||
|
bank_forks.write().unwrap().insert(bank1);
|
||||||
|
let alice = Keypair::new();
|
||||||
|
|
||||||
|
let (subscriber0, _id_receiver, transport_receiver0) =
|
||||||
|
Subscriber::new_test("accountNotification");
|
||||||
|
let (subscriber1, _id_receiver, transport_receiver1) =
|
||||||
|
Subscriber::new_test("accountNotification");
|
||||||
|
let exit = Arc::new(AtomicBool::new(false));
|
||||||
|
let subscriptions = RpcSubscriptions::new(
|
||||||
|
&exit,
|
||||||
|
bank_forks.clone(),
|
||||||
|
Arc::new(RwLock::new(
|
||||||
|
BlockCommitmentCache::new_for_tests_with_blockstore_bank(
|
||||||
|
blockstore,
|
||||||
|
bank_forks.read().unwrap().get(1).unwrap().clone(),
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
let sub_id0 = SubscriptionId::Number(0 as u64);
|
||||||
|
subscriptions.add_account_subscription(
|
||||||
|
alice.pubkey(),
|
||||||
|
Some(CommitmentConfig::single_gossip()),
|
||||||
|
sub_id0.clone(),
|
||||||
|
subscriber0,
|
||||||
|
);
|
||||||
|
let sub_id1 = SubscriptionId::Number(1 as u64);
|
||||||
|
subscriptions.add_account_subscription(
|
||||||
|
alice.pubkey(),
|
||||||
|
Some(CommitmentConfig::recent()),
|
||||||
|
sub_id1.clone(),
|
||||||
|
subscriber1,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(subscriptions
|
||||||
|
.subscriptions
|
||||||
|
.account_subscriptions
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.contains_key(&alice.pubkey()));
|
||||||
|
|
||||||
|
let tx = system_transaction::create_account(
|
||||||
|
&mint_keypair,
|
||||||
|
&alice,
|
||||||
|
blockhash,
|
||||||
|
1,
|
||||||
|
16,
|
||||||
|
&solana_budget_program::id(),
|
||||||
|
);
|
||||||
|
bank_forks
|
||||||
|
.write()
|
||||||
|
.unwrap()
|
||||||
|
.get(1)
|
||||||
|
.unwrap()
|
||||||
|
.process_transaction(&tx)
|
||||||
|
.unwrap();
|
||||||
|
let mut cache_slot_info = CacheSlotInfo::default();
|
||||||
|
cache_slot_info.current_slot = 1;
|
||||||
|
subscriptions.notify_subscribers(cache_slot_info);
|
||||||
|
let (response, _) = robust_poll_or_panic(transport_receiver1);
|
||||||
|
let expected = json!({
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": "accountNotification",
|
||||||
|
"params": {
|
||||||
|
"result": {
|
||||||
|
"context": { "slot": 1 },
|
||||||
|
"value": {
|
||||||
|
"data": "1111111111111111",
|
||||||
|
"executable": false,
|
||||||
|
"lamports": 1,
|
||||||
|
"owner": "Budget1111111111111111111111111111111111111",
|
||||||
|
"rentEpoch": 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"subscription": 1,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assert_eq!(serde_json::to_string(&expected).unwrap(), response);
|
||||||
|
|
||||||
|
subscriptions.notify_gossip_subscribers(1);
|
||||||
|
let (response, _) = robust_poll_or_panic(transport_receiver0);
|
||||||
|
let expected = json!({
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": "accountNotification",
|
||||||
|
"params": {
|
||||||
|
"result": {
|
||||||
|
"context": { "slot": 1 },
|
||||||
|
"value": {
|
||||||
|
"data": "1111111111111111",
|
||||||
|
"executable": false,
|
||||||
|
"lamports": 1,
|
||||||
|
"owner": "Budget1111111111111111111111111111111111111",
|
||||||
|
"rentEpoch": 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"subscription": 0,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assert_eq!(serde_json::to_string(&expected).unwrap(), response);
|
||||||
|
|
||||||
|
subscriptions.remove_account_subscription(&sub_id0);
|
||||||
|
assert!(subscriptions
|
||||||
|
.subscriptions
|
||||||
|
.account_subscriptions
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.contains_key(&alice.pubkey()));
|
||||||
|
subscriptions.remove_account_subscription(&sub_id1);
|
||||||
|
assert!(!subscriptions
|
||||||
|
.subscriptions
|
||||||
|
.account_subscriptions
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.contains_key(&alice.pubkey()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,12 @@ impl CommitmentConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn single_gossip() -> Self {
|
||||||
|
Self {
|
||||||
|
commitment: CommitmentLevel::SingleGossip,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ok(self) -> Option<Self> {
|
pub fn ok(self) -> Option<Self> {
|
||||||
if self == Self::default() {
|
if self == Self::default() {
|
||||||
None
|
None
|
||||||
|
@ -46,11 +52,12 @@ impl CommitmentConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq)]
|
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub enum CommitmentLevel {
|
pub enum CommitmentLevel {
|
||||||
Max,
|
Max,
|
||||||
Recent,
|
Recent,
|
||||||
Root,
|
Root,
|
||||||
Single,
|
Single,
|
||||||
|
SingleGossip,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue