use async_trait::async_trait;
use crate::state_commit::{error::StateCommitError, orchestrator::OperatorEntry};
#[derive(Clone)]
pub struct OperatorSetSnapshot {
pub operators: Vec<OperatorEntry>,
pub reference_timestamp: u32,
}
impl std::fmt::Debug for OperatorSetSnapshot {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("OperatorSetSnapshot")
.field("operators", &self.operators.len())
.field("reference_timestamp", &self.reference_timestamp)
.finish()
}
}
#[async_trait]
pub trait OperatorSetSnapshotReader: Send + Sync + 'static {
async fn snapshot(&self) -> Result<OperatorSetSnapshot, StateCommitError>;
}
#[cfg(any(test, feature = "dev-stub"))]
#[derive(Debug, Clone)]
pub struct StubOperatorSetSnapshotReader {
snapshot: OperatorSetSnapshot,
}
#[cfg(any(test, feature = "dev-stub"))]
impl StubOperatorSetSnapshotReader {
pub fn new(operators: Vec<OperatorEntry>, reference_timestamp: u32) -> Self {
Self {
snapshot: OperatorSetSnapshot {
operators,
reference_timestamp,
},
}
}
}
#[cfg(any(test, feature = "dev-stub"))]
#[async_trait]
impl OperatorSetSnapshotReader for StubOperatorSetSnapshotReader {
async fn snapshot(&self) -> Result<OperatorSetSnapshot, StateCommitError> {
Ok(self.snapshot.clone())
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloy::primitives::U256;
use ark_bn254::{G1Affine, G2Affine};
use eigensdk::{
crypto_bls::{BlsG1Point, BlsG2Point},
types::operator::OperatorId,
};
use std::sync::Arc;
fn make_entry(id_byte: u8) -> OperatorEntry {
let mut id = OperatorId::default();
id[0] = id_byte;
OperatorEntry {
operator_id: id,
stake: U256::from(1_000u64),
g1_pubkey: BlsG1Point::new(G1Affine::identity()),
g2_pubkey: BlsG2Point::new(G2Affine::identity()),
}
}
#[tokio::test]
async fn stub_returns_configured_snapshot() {
let reader = StubOperatorSetSnapshotReader::new(vec![make_entry(0x01), make_entry(0x02)], 42);
let snap = reader.snapshot().await.expect("stub never errors");
assert_eq!(snap.operators.len(), 2);
assert_eq!(snap.reference_timestamp, 42);
}
#[tokio::test]
async fn stub_is_object_safe_behind_arc() {
let reader: Arc<dyn OperatorSetSnapshotReader> = Arc::new(StubOperatorSetSnapshotReader::new(vec![], 0));
let snap = reader.snapshot().await.expect("stub never errors");
assert!(snap.operators.is_empty());
assert_eq!(snap.reference_timestamp, 0);
}
#[tokio::test]
async fn stub_returns_independent_clones_per_call() {
let reader = StubOperatorSetSnapshotReader::new(vec![make_entry(0x01)], 7);
let mut s1 = reader.snapshot().await.expect("call 1");
s1.operators.clear();
let s2 = reader.snapshot().await.expect("call 2");
assert_eq!(s2.operators.len(), 1);
assert_eq!(s2.reference_timestamp, 7);
}
}