2021-12-03 09:00:31 -08:00
|
|
|
use {
|
|
|
|
crossbeam_channel::{Receiver, RecvTimeoutError, Sender},
|
|
|
|
solana_ledger::blockstore::Blockstore,
|
|
|
|
solana_runtime::bank::RewardInfo,
|
|
|
|
solana_sdk::{clock::Slot, pubkey::Pubkey},
|
|
|
|
solana_transaction_status::Reward,
|
|
|
|
std::{
|
|
|
|
sync::{
|
2023-03-14 11:08:48 -07:00
|
|
|
atomic::{AtomicBool, AtomicU64, Ordering},
|
2021-12-03 09:00:31 -08:00
|
|
|
Arc,
|
|
|
|
},
|
|
|
|
thread::{self, Builder, JoinHandle},
|
|
|
|
time::Duration,
|
2020-02-04 18:50:24 -08:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2023-03-14 11:08:48 -07:00
|
|
|
pub type RewardsBatch = (Slot, Vec<(Pubkey, RewardInfo)>);
|
|
|
|
pub type RewardsRecorderReceiver = Receiver<RewardsMessage>;
|
|
|
|
pub type RewardsRecorderSender = Sender<RewardsMessage>;
|
|
|
|
|
|
|
|
pub enum RewardsMessage {
|
|
|
|
Batch(RewardsBatch),
|
|
|
|
Complete(Slot),
|
|
|
|
}
|
2020-02-04 18:50:24 -08:00
|
|
|
|
|
|
|
pub struct RewardsRecorderService {
|
|
|
|
thread_hdl: JoinHandle<()>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl RewardsRecorderService {
|
|
|
|
pub fn new(
|
|
|
|
rewards_receiver: RewardsRecorderReceiver,
|
2023-03-14 11:08:48 -07:00
|
|
|
max_complete_rewards_slot: Arc<AtomicU64>,
|
2020-02-04 18:50:24 -08:00
|
|
|
blockstore: Arc<Blockstore>,
|
|
|
|
exit: &Arc<AtomicBool>,
|
|
|
|
) -> Self {
|
|
|
|
let exit = exit.clone();
|
|
|
|
let thread_hdl = Builder::new()
|
2022-08-17 08:40:23 -07:00
|
|
|
.name("solRewardsWritr".to_string())
|
2020-02-04 18:50:24 -08:00
|
|
|
.spawn(move || loop {
|
|
|
|
if exit.load(Ordering::Relaxed) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if let Err(RecvTimeoutError::Disconnected) =
|
2023-03-14 11:08:48 -07:00
|
|
|
Self::write_rewards(&rewards_receiver, &max_complete_rewards_slot, &blockstore)
|
2020-02-04 18:50:24 -08:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.unwrap();
|
|
|
|
Self { thread_hdl }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write_rewards(
|
|
|
|
rewards_receiver: &RewardsRecorderReceiver,
|
2023-03-14 11:08:48 -07:00
|
|
|
max_complete_rewards_slot: &Arc<AtomicU64>,
|
2020-02-04 18:50:24 -08:00
|
|
|
blockstore: &Arc<Blockstore>,
|
|
|
|
) -> Result<(), RecvTimeoutError> {
|
2023-03-14 11:08:48 -07:00
|
|
|
match rewards_receiver.recv_timeout(Duration::from_secs(1))? {
|
|
|
|
RewardsMessage::Batch((slot, rewards)) => {
|
|
|
|
let rpc_rewards = rewards
|
|
|
|
.into_iter()
|
|
|
|
.map(|(pubkey, reward_info)| Reward {
|
|
|
|
pubkey: pubkey.to_string(),
|
|
|
|
lamports: reward_info.lamports,
|
|
|
|
post_balance: reward_info.post_balance,
|
|
|
|
reward_type: Some(reward_info.reward_type),
|
|
|
|
commission: reward_info.commission,
|
|
|
|
})
|
|
|
|
.collect();
|
2020-02-04 18:50:24 -08:00
|
|
|
|
2023-03-14 11:08:48 -07:00
|
|
|
blockstore
|
|
|
|
.write_rewards(slot, rpc_rewards)
|
|
|
|
.expect("Expect database write to succeed");
|
|
|
|
}
|
|
|
|
RewardsMessage::Complete(slot) => {
|
|
|
|
max_complete_rewards_slot.fetch_max(slot, Ordering::SeqCst);
|
|
|
|
}
|
|
|
|
}
|
2020-02-04 18:50:24 -08:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn join(self) -> thread::Result<()> {
|
|
|
|
self.thread_hdl.join()
|
|
|
|
}
|
|
|
|
}
|