darkfi/event_graph/
event.rs1use std::{collections::HashSet, time::UNIX_EPOCH};
20
21use darkfi_serial::{async_trait, deserialize_async, Encodable, SerialDecodable, SerialEncodable};
22use sled_overlay::{sled, SledTreeOverlay};
23
24use crate::Result;
25
26use super::{
27 util::next_rotation_timestamp, EventGraph, EVENT_TIME_DRIFT, INITIAL_GENESIS, NULL_ID,
28 N_EVENT_PARENTS,
29};
30
31#[derive(Debug, Clone, PartialEq, SerialEncodable, SerialDecodable)]
33pub struct Event {
34 pub timestamp: u64,
36 pub content: Vec<u8>,
38 pub parents: [blake3::Hash; N_EVENT_PARENTS],
40 pub layer: u64,
42}
43
44impl Event {
45 pub async fn new(data: Vec<u8>, event_graph: &EventGraph) -> Self {
51 let (layer, parents) = event_graph.get_next_layer_with_parents().await;
52 Self {
53 timestamp: UNIX_EPOCH.elapsed().unwrap().as_millis() as u64,
54 content: data,
55 parents,
56 layer,
57 }
58 }
59
60 pub async fn with_timestamp(timestamp: u64, data: Vec<u8>, event_graph: &EventGraph) -> Self {
62 let (layer, parents) = event_graph.get_next_layer_with_parents().await;
63 Self { timestamp, content: data, parents, layer }
64 }
65
66 pub fn id(&self) -> blake3::Hash {
68 let mut hasher = blake3::Hasher::new();
69 self.timestamp.encode(&mut hasher).unwrap();
70 self.content.encode(&mut hasher).unwrap();
71 self.parents.encode(&mut hasher).unwrap();
72 self.layer.encode(&mut hasher).unwrap();
73 hasher.finalize()
74 }
75
76 pub fn content(&self) -> &[u8] {
78 &self.content
79 }
80
81 pub async fn validate(
93 &self,
94 dag: &sled::Tree,
95 genesis_timestamp: u64,
96 days_rotation: u64,
97 overlay: Option<&SledTreeOverlay>,
98 ) -> Result<bool> {
99 if self.content.is_empty() {
101 return Ok(false)
102 }
103
104 if self.timestamp < genesis_timestamp - EVENT_TIME_DRIFT {
106 return Ok(false)
107 }
108
109 if days_rotation > 0 {
112 let next_genesis_timestamp = next_rotation_timestamp(INITIAL_GENESIS, days_rotation);
113 if self.timestamp > next_genesis_timestamp + EVENT_TIME_DRIFT {
114 return Ok(false)
115 }
116 }
117
118 let mut seen = HashSet::new();
123 let self_id = self.id();
124
125 for parent_id in self.parents.iter() {
126 if parent_id == &NULL_ID {
127 continue
128 }
129
130 if parent_id == &self_id {
131 return Ok(false)
132 }
133
134 if seen.contains(parent_id) {
135 return Ok(false)
136 }
137
138 let parent_bytes = if let Some(overlay) = overlay {
139 overlay.get(parent_id.as_bytes())?
140 } else {
141 dag.get(parent_id.as_bytes())?
142 };
143 if parent_bytes.is_none() {
144 return Ok(false)
145 }
146
147 let parent: Event = deserialize_async(&parent_bytes.unwrap()).await?;
148 if self.layer <= parent.layer {
149 return Ok(false)
150 }
151
152 seen.insert(parent_id);
153 }
154
155 Ok(!seen.is_empty())
156 }
157
158 pub async fn dag_validate(&self, event_graph: &EventGraph) -> Result<bool> {
162 let genesis_timestamp = event_graph.current_genesis.read().await.timestamp;
164
165 self.validate(&event_graph.dag, genesis_timestamp, event_graph.days_rotation, None).await
167 }
168
169 pub fn validate_new(&self) -> bool {
174 if self.content.is_empty() {
176 return false
177 }
178
179 let now = UNIX_EPOCH.elapsed().unwrap().as_millis() as u64;
181 let too_old = self.timestamp < now - EVENT_TIME_DRIFT;
182 let too_new = self.timestamp > now + EVENT_TIME_DRIFT;
183 if too_old || too_new {
184 return false
185 }
186
187 let mut seen = HashSet::new();
190 let self_id = self.id();
191
192 for parent_id in self.parents.iter() {
193 if parent_id == &NULL_ID {
194 continue
195 }
196
197 if parent_id == &self_id {
198 return false
199 }
200
201 if seen.contains(parent_id) {
202 return false
203 }
204
205 seen.insert(parent_id);
206 }
207
208 !seen.is_empty()
209 }
210}
211
212#[cfg(test)]
213mod tests {
214 use std::sync::Arc;
215
216 use smol::Executor;
217
218 use crate::{
219 event_graph::{EventGraph, EventGraphPtr},
220 net::{P2p, Settings},
221 };
222
223 use super::*;
224
225 async fn make_event_graph() -> Result<EventGraphPtr> {
226 let ex = Arc::new(Executor::new());
227 let p2p = P2p::new(Settings::default(), ex.clone()).await?;
228 let sled_db = sled::Config::new().temporary(true).open().unwrap();
229 EventGraph::new(p2p, sled_db, "/tmp".into(), false, "dag", 1, ex).await
230 }
231
232 #[test]
233 fn event_is_valid() -> Result<()> {
234 smol::block_on(async {
235 let event_graph = make_event_graph().await?;
237
238 let valid_event = Event::new(vec![1u8], &event_graph).await;
240
241 assert!(valid_event.dag_validate(&event_graph).await?);
243
244 Ok(())
246 })
247 }
248
249 #[test]
250 fn invalid_events() -> Result<()> {
251 smol::block_on(async {
252 let event_graph = make_event_graph().await?;
254
255 let valid_event = Event::new(vec![1u8], &event_graph).await;
257
258 let mut event_empty_content = valid_event.clone();
259 event_empty_content.content = vec![];
260 assert!(!event_empty_content.dag_validate(&event_graph).await?);
261
262 let mut event_timestamp_too_old = valid_event.clone();
263 event_timestamp_too_old.timestamp = 0;
264 assert!(!event_timestamp_too_old.dag_validate(&event_graph).await?);
265
266 let mut event_timestamp_too_new = valid_event.clone();
267 event_timestamp_too_new.timestamp = u64::MAX;
268 assert!(!event_timestamp_too_new.dag_validate(&event_graph).await?);
269
270 let mut event_duplicated_parents = valid_event.clone();
271 event_duplicated_parents.parents[1] = valid_event.parents[0];
272 assert!(!event_duplicated_parents.dag_validate(&event_graph).await?);
273
274 let mut event_null_parents = valid_event.clone();
275 let all_null_parents = [NULL_ID, NULL_ID, NULL_ID, NULL_ID, NULL_ID];
276 event_null_parents.parents = all_null_parents;
277 assert!(!event_null_parents.dag_validate(&event_graph).await?);
278
279 let mut event_same_layer_as_parents = valid_event.clone();
280 event_same_layer_as_parents.layer = 0;
281 assert!(!event_same_layer_as_parents.dag_validate(&event_graph).await?);
282
283 Ok(())
285 })
286 }
287}