use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
use crate::{
rex_info::{RexId, RexUpdateResult, TimestampMs},
websocket::BLS12381_PUBLIC_KEY_SIZE,
RexDutyConfig,
};
pub type AuthorityKeyBytes = [u8; BLS12381_PUBLIC_KEY_SIZE];
pub type CommitIndex = u64;
pub type RexDutiesMap = BTreeMap<RexDutiesMapKey, RexDutiesMapValue>;
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Eq, PartialEq, Hash)]
pub struct RexDutiesMapKey {
pub target_timestamp: TimestampMs,
pub rex_id: RexId,
}
impl Ord for RexDutiesMapKey {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.target_timestamp
.cmp(&other.target_timestamp)
.then_with(|| self.rex_id.cmp(&other.rex_id))
}
}
impl PartialOrd for RexDutiesMapKey {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
#[derive(Clone, Debug, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct RexDutiesMapValue {
#[serde(with = "serde_utils")]
pub updates: BTreeMap<AuthorityKeyBytes, Option<RexUpdateResult>>,
pub config: RexDutyConfig,
}
mod serde_utils {
use std::collections::BTreeMap;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_big_array::BigArray;
use crate::{rex_info::RexUpdateResult, AuthorityKeyBytes};
pub fn serialize<S>(
map: &BTreeMap<AuthorityKeyBytes, Option<RexUpdateResult>>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
#[derive(Serialize)]
struct Entry {
#[serde(with = "BigArray")]
key: AuthorityKeyBytes,
value: Option<RexUpdateResult>,
}
let entries: Vec<_> = map
.iter()
.map(|(key, value)| Entry {
key: *key,
value: value.clone(),
})
.collect();
entries.serialize(serializer)
}
pub fn deserialize<'de, D>(
deserializer: D,
) -> Result<BTreeMap<AuthorityKeyBytes, Option<RexUpdateResult>>, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
struct Entry {
#[serde(with = "BigArray")]
key: AuthorityKeyBytes,
value: Option<RexUpdateResult>,
}
let entries = Vec::<Entry>::deserialize(deserializer)?;
Ok(entries.into_iter().map(|e| (e.key, e.value)).collect())
}
}
#[cfg(test)]
mod tests {
use std::cmp::{max, min};
use rialo_s_pubkey::Pubkey;
use super::*;
#[test]
fn test_rex_duties_map_key_ordering() {
let creator1 = Pubkey::new_unique();
let creator2 = Pubkey::new_unique();
let rex_id1 = RexId::new(creator1, "nonce1");
let rex_id2 = RexId::new(creator2, "nonce2");
let [rex_id1, rex_id2] = [min(rex_id1, rex_id2), max(rex_id1, rex_id2)];
let key1 = RexDutiesMapKey {
target_timestamp: 100,
rex_id: rex_id1,
};
let key2 = RexDutiesMapKey {
target_timestamp: 200,
rex_id: rex_id1,
};
assert!(key1 < key2);
assert!(key2 > key1);
let key3 = RexDutiesMapKey {
target_timestamp: 100,
rex_id: rex_id1,
};
let key4 = RexDutiesMapKey {
target_timestamp: 100,
rex_id: rex_id2,
};
assert!(key3 < key4);
assert!(key4 > key3);
let key5 = RexDutiesMapKey {
target_timestamp: 100,
rex_id: rex_id2,
};
let key6 = RexDutiesMapKey {
target_timestamp: 200,
rex_id: rex_id1,
};
assert!(key5 < key6);
assert!(key6 > key5);
let key7 = RexDutiesMapKey {
target_timestamp: 100,
rex_id: rex_id1,
};
let key8 = RexDutiesMapKey {
target_timestamp: 100,
rex_id: rex_id1,
};
assert_eq!(key7, key8);
assert!(key7 >= key8);
assert!(key7 <= key8);
let mut map = BTreeMap::new();
let key9 = RexDutiesMapKey {
target_timestamp: 200,
rex_id: rex_id1,
};
let key10 = RexDutiesMapKey {
target_timestamp: 100,
rex_id: rex_id2,
};
let key11 = RexDutiesMapKey {
target_timestamp: 100,
rex_id: rex_id1,
};
map.insert(key9, "first");
map.insert(key10, "second");
map.insert(key11, "third");
let keys: Vec<_> = map.keys().copied().collect();
assert_eq!(keys[0], key11);
assert_eq!(keys[1], key10);
assert_eq!(keys[2], key9);
}
}