use super::{HashMap, HashSet};
use crate::client::error::GroupChannelError;
use mining_sv2::{NewExtendedMiningJob, SetNewPrevHash as SetNewPrevHashMp};
#[derive(Debug, Clone)]
pub struct GroupChannel<'a> {
group_channel_id: u32,
channel_ids: HashSet<u32>,
future_jobs: HashMap<u32, NewExtendedMiningJob<'a>>,
active_job: Option<NewExtendedMiningJob<'a>>,
full_extranonce_size: Option<usize>,
}
impl<'a> GroupChannel<'a> {
pub fn new(group_channel_id: u32) -> Self {
Self {
group_channel_id,
channel_ids: HashSet::new(),
future_jobs: HashMap::new(),
active_job: None,
full_extranonce_size: None,
}
}
pub fn add_channel_id(
&mut self,
channel_id: u32,
full_extranonce_size: usize,
) -> Result<(), GroupChannelError> {
self.channel_ids.insert(channel_id);
match self.full_extranonce_size {
Some(existing_size) => {
if existing_size != full_extranonce_size {
return Err(GroupChannelError::FullExtranonceSizeMismatch);
}
}
None => {
self.full_extranonce_size = Some(full_extranonce_size);
}
}
Ok(())
}
pub fn remove_channel_id(&mut self, channel_id: u32) {
self.channel_ids.remove(&channel_id);
}
pub fn get_group_channel_id(&self) -> u32 {
self.group_channel_id
}
pub fn get_channel_ids(&self) -> &HashSet<u32> {
&self.channel_ids
}
pub fn get_active_job(&self) -> Option<&NewExtendedMiningJob<'a>> {
self.active_job.as_ref()
}
pub fn get_future_jobs(&self) -> &HashMap<u32, NewExtendedMiningJob<'a>> {
&self.future_jobs
}
pub fn get_full_extranonce_size(&self) -> Option<usize> {
self.full_extranonce_size
}
pub fn on_new_extended_mining_job(
&mut self,
new_extended_mining_job: NewExtendedMiningJob<'a>,
) {
match new_extended_mining_job.min_ntime.clone().into_inner() {
Some(_min_ntime) => {
self.active_job = Some(new_extended_mining_job);
}
None => {
self.future_jobs
.insert(new_extended_mining_job.job_id, new_extended_mining_job);
}
}
}
pub fn on_set_new_prev_hash(
&mut self,
set_new_prev_hash: SetNewPrevHashMp<'a>,
) -> Result<(), GroupChannelError> {
match self.future_jobs.remove(&set_new_prev_hash.job_id) {
Some(job) => {
self.active_job = Some(job);
}
None => return Err(GroupChannelError::JobIdNotFound),
}
self.future_jobs.clear();
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add_channel_id() {
let mut group_channel = GroupChannel::new(1);
group_channel.add_channel_id(1, 10).unwrap();
assert_eq!(group_channel.get_full_extranonce_size(), Some(10));
group_channel.add_channel_id(2, 10).unwrap();
assert_eq!(group_channel.get_full_extranonce_size(), Some(10));
assert!(group_channel.add_channel_id(3, 12).is_err());
}
}