2025-06-12 15:50:42 -04:00
|
|
|
use crate::{oracle, utils, AssetPair, OracleId, PriceAttestation};
|
2025-06-12 15:49:04 -04:00
|
|
|
use rand::Rng;
|
2025-06-12 15:50:42 -04:00
|
|
|
use std::sync::{Arc, Mutex};
|
2025-06-12 15:49:04 -04:00
|
|
|
|
|
|
|
|
pub(crate) struct OracleNode {
|
|
|
|
|
pub(crate) id: OracleId,
|
2025-06-12 15:50:42 -04:00
|
|
|
pub(crate) crdt: Arc<Mutex<oracle::NetworkCRDT>>,
|
2025-06-12 15:49:04 -04:00
|
|
|
pub(crate) is_byzantine: bool,
|
|
|
|
|
pub(crate) base_price: f64,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl OracleNode {
|
|
|
|
|
pub(crate) fn new(id: String, is_byzantine: bool) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
id: OracleId(id),
|
2025-06-12 15:50:42 -04:00
|
|
|
crdt: Arc::new(Mutex::new(oracle::NetworkCRDT::new())),
|
2025-06-12 15:49:04 -04:00
|
|
|
is_byzantine,
|
|
|
|
|
base_price: 2500.0,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn submit_price(&self) {
|
|
|
|
|
let mut rng = rand::rng();
|
|
|
|
|
|
|
|
|
|
let price = if self.is_byzantine {
|
|
|
|
|
self.base_price * 1.2 // Try to manipulate 20% higher
|
|
|
|
|
} else {
|
|
|
|
|
self.base_price * (1.0 + rng.random_range(-0.01..0.01))
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let attestation = PriceAttestation {
|
|
|
|
|
id: format!("{}_{}", self.id.0, utils::timestamp()),
|
|
|
|
|
oracle_id: self.id.clone(),
|
|
|
|
|
asset_pair: AssetPair("ETH/USD".to_string()),
|
|
|
|
|
price,
|
|
|
|
|
confidence: if self.is_byzantine { 50 } else { 95 },
|
|
|
|
|
timestamp: utils::timestamp(),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let mut crdt = self.crdt.lock().unwrap();
|
|
|
|
|
crdt.submit_attestation(attestation);
|
|
|
|
|
}
|
|
|
|
|
}
|