use crate::network::LogEntry;
use crate::raft::{OxirsNodeId, RdfApp};
use anyhow::Result;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use std::time::{SystemTime, UNIX_EPOCH};
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct RaftState {
pub current_term: u64,
pub voted_for: Option<OxirsNodeId>,
pub log: Vec<LogEntry>,
pub commit_index: u64,
pub last_applied: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SnapshotMetadata {
pub last_included_index: u64,
pub last_included_term: u64,
pub configuration: Vec<OxirsNodeId>,
pub timestamp: u64,
pub size: u64,
pub checksum: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WalEntry {
pub sequence: u64,
pub timestamp: u64,
pub operation: WalOperation,
pub checksum: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum WalOperation {
WriteRaftState(RaftState),
WriteAppState(RdfApp),
CreateSnapshot(SnapshotMetadata),
TruncateLog(u64),
Commit(u64),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChecksummedData<T> {
pub data: T,
pub checksum: String,
pub timestamp: u64,
}
impl<T> ChecksummedData<T>
where
T: Serialize,
{
pub fn new(data: T) -> Result<Self> {
let data_bytes = oxicode::serde::encode_to_vec(&data, oxicode::config::standard())?;
let mut hasher = Sha256::new();
hasher.update(&data_bytes);
let checksum = format!("{:x}", hasher.finalize());
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("SystemTime should be after UNIX_EPOCH")
.as_secs();
Ok(Self {
data,
checksum,
timestamp,
})
}
pub fn verify(&self) -> Result<bool> {
let data_bytes = oxicode::serde::encode_to_vec(&self.data, oxicode::config::standard())?;
let mut hasher = Sha256::new();
hasher.update(&data_bytes);
let computed_checksum = format!("{:x}", hasher.finalize());
Ok(computed_checksum == self.checksum)
}
}