1use super::error::ProtocolError;
4use super::link::LinkMessageType;
5use crate::NodeAddr;
6use crate::tree::{CoordEntry, ParentDeclaration, TreeCoordinate, TreeError};
7use secp256k1::schnorr::Signature;
8
9#[derive(Clone, Debug)]
15pub struct TreeAnnounce {
16 pub declaration: ParentDeclaration,
18 pub ancestry: TreeCoordinate,
20}
21
22impl TreeAnnounce {
23 pub const VERSION_1: u8 = 0x01;
25
26 const MIN_PAYLOAD_SIZE: usize = 99;
29
30 pub fn new(declaration: ParentDeclaration, ancestry: TreeCoordinate) -> Self {
32 Self {
33 declaration,
34 ancestry,
35 }
36 }
37
38 pub fn validate_semantics(&self) -> Result<(), TreeError> {
49 let entries = self.ancestry.entries();
50 let declared_node = *self.declaration.node_addr();
51 let declared_parent = *self.declaration.parent_id();
52
53 if entries[0].node_addr != declared_node {
54 return Err(TreeError::AncestryNodeMismatch {
55 declared: declared_node,
56 ancestry: entries[0].node_addr,
57 });
58 }
59
60 if self.declaration.is_root() {
61 if entries.len() != 1 {
62 return Err(TreeError::RootDeclarationMismatch);
63 }
64 } else {
65 let ancestry_parent = entries.get(1).ok_or(TreeError::AncestryTooShort)?.node_addr;
66 if ancestry_parent != declared_parent {
67 return Err(TreeError::AncestryParentMismatch {
68 declared: declared_parent,
69 ancestry: ancestry_parent,
70 });
71 }
72 }
73
74 let advertised_root = *self.ancestry.root_id();
75 let minimum = entries
76 .iter()
77 .map(|entry| entry.node_addr)
78 .min()
79 .expect("TreeCoordinate is never empty");
80 if advertised_root != minimum {
81 return Err(TreeError::AncestryRootNotMinimum {
82 advertised: advertised_root,
83 minimum,
84 });
85 }
86
87 Ok(())
88 }
89
90 pub fn encode(&self) -> Result<Vec<u8>, ProtocolError> {
98 let signature = self
99 .declaration
100 .signature()
101 .ok_or(ProtocolError::InvalidSignature)?;
102
103 let entries = self.ancestry.entries();
104 let ancestry_count = entries.len() as u16;
105 let size = 1 + Self::MIN_PAYLOAD_SIZE + entries.len() * CoordEntry::WIRE_SIZE;
106 let mut buf = Vec::with_capacity(size);
107
108 buf.push(LinkMessageType::TreeAnnounce.to_byte());
110 buf.push(Self::VERSION_1);
112 buf.extend_from_slice(&self.declaration.sequence().to_le_bytes());
114 buf.extend_from_slice(&self.declaration.timestamp().to_le_bytes());
116 buf.extend_from_slice(self.declaration.parent_id().as_bytes());
118 buf.extend_from_slice(&ancestry_count.to_le_bytes());
120 for entry in entries {
122 buf.extend_from_slice(entry.node_addr.as_bytes()); buf.extend_from_slice(&entry.sequence.to_le_bytes()); buf.extend_from_slice(&entry.timestamp.to_le_bytes()); }
126 buf.extend_from_slice(signature.as_ref());
128
129 Ok(buf)
130 }
131
132 pub fn decode(payload: &[u8]) -> Result<Self, ProtocolError> {
136 if payload.len() < Self::MIN_PAYLOAD_SIZE {
137 return Err(ProtocolError::MessageTooShort {
138 expected: Self::MIN_PAYLOAD_SIZE,
139 got: payload.len(),
140 });
141 }
142
143 let mut pos = 0;
144
145 let version = payload[pos];
147 pos += 1;
148 if version != Self::VERSION_1 {
149 return Err(ProtocolError::UnsupportedVersion(version));
150 }
151
152 let sequence = u64::from_le_bytes(
154 payload[pos..pos + 8]
155 .try_into()
156 .map_err(|_| ProtocolError::Malformed("bad sequence".into()))?,
157 );
158 pos += 8;
159
160 let timestamp = u64::from_le_bytes(
162 payload[pos..pos + 8]
163 .try_into()
164 .map_err(|_| ProtocolError::Malformed("bad timestamp".into()))?,
165 );
166 pos += 8;
167
168 let parent = NodeAddr::from_bytes(
170 payload[pos..pos + 16]
171 .try_into()
172 .map_err(|_| ProtocolError::Malformed("bad parent".into()))?,
173 );
174 pos += 16;
175
176 let ancestry_count = u16::from_le_bytes(
178 payload[pos..pos + 2]
179 .try_into()
180 .map_err(|_| ProtocolError::Malformed("bad ancestry count".into()))?,
181 ) as usize;
182 pos += 2;
183
184 let expected_remaining = ancestry_count * CoordEntry::WIRE_SIZE + 64;
186 if payload.len() - pos < expected_remaining {
187 return Err(ProtocolError::MessageTooShort {
188 expected: pos + expected_remaining,
189 got: payload.len(),
190 });
191 }
192
193 let mut entries = Vec::with_capacity(ancestry_count);
195 for _ in 0..ancestry_count {
196 let node_addr = NodeAddr::from_bytes(
197 payload[pos..pos + 16]
198 .try_into()
199 .map_err(|_| ProtocolError::Malformed("bad entry node_addr".into()))?,
200 );
201 pos += 16;
202 let entry_seq = u64::from_le_bytes(
203 payload[pos..pos + 8]
204 .try_into()
205 .map_err(|_| ProtocolError::Malformed("bad entry sequence".into()))?,
206 );
207 pos += 8;
208 let entry_ts = u64::from_le_bytes(
209 payload[pos..pos + 8]
210 .try_into()
211 .map_err(|_| ProtocolError::Malformed("bad entry timestamp".into()))?,
212 );
213 pos += 8;
214 entries.push(CoordEntry::new(node_addr, entry_seq, entry_ts));
215 }
216
217 let sig_bytes: [u8; 64] = payload[pos..pos + 64]
219 .try_into()
220 .map_err(|_| ProtocolError::Malformed("bad signature".into()))?;
221 let signature =
222 Signature::from_slice(&sig_bytes).map_err(|_| ProtocolError::InvalidSignature)?;
223
224 if entries.is_empty() {
226 return Err(ProtocolError::Malformed(
227 "ancestry must have at least one entry".into(),
228 ));
229 }
230 let node_addr = entries[0].node_addr;
231
232 let declaration =
233 ParentDeclaration::with_signature(node_addr, parent, sequence, timestamp, signature);
234
235 let ancestry = TreeCoordinate::new(entries)
236 .map_err(|e| ProtocolError::Malformed(format!("bad ancestry: {}", e)))?;
237
238 Ok(Self {
239 declaration,
240 ancestry,
241 })
242 }
243}
244
245#[cfg(test)]
246mod tests {
247 use super::*;
248
249 fn make_node_addr(val: u8) -> NodeAddr {
250 let mut bytes = [0u8; 16];
251 bytes[0] = val;
252 NodeAddr::from_bytes(bytes)
253 }
254
255 fn make_coords(ids: &[u8]) -> TreeCoordinate {
256 TreeCoordinate::from_addrs(ids.iter().map(|&v| make_node_addr(v)).collect()).unwrap()
257 }
258
259 #[test]
260 fn test_tree_announce() {
261 let node = make_node_addr(1);
262 let parent = make_node_addr(2);
263 let decl = ParentDeclaration::new(node, parent, 1, 1000);
264 let ancestry = make_coords(&[1, 2, 0]);
265
266 let announce = TreeAnnounce::new(decl, ancestry);
267
268 assert_eq!(announce.declaration.node_addr(), &node);
269 assert_eq!(announce.ancestry.depth(), 2);
270 }
271
272 #[test]
273 fn test_tree_announce_encode_decode_root() {
274 use crate::identity::Identity;
275
276 let identity = Identity::generate();
277 let node_addr = *identity.node_addr();
278
279 let mut decl = ParentDeclaration::new(node_addr, node_addr, 1, 5000);
281 decl.sign(&identity).unwrap();
282
283 let ancestry = TreeCoordinate::new(vec![CoordEntry::new(node_addr, 1, 5000)]).unwrap();
285
286 let announce = TreeAnnounce::new(decl, ancestry);
287 let encoded = announce.encode().unwrap();
288
289 assert_eq!(encoded.len(), 132);
291 assert_eq!(encoded[0], 0x10); let decoded = TreeAnnounce::decode(&encoded[1..]).unwrap();
295
296 assert_eq!(decoded.declaration.node_addr(), &node_addr);
297 assert_eq!(decoded.declaration.parent_id(), &node_addr);
298 assert_eq!(decoded.declaration.sequence(), 1);
299 assert_eq!(decoded.declaration.timestamp(), 5000);
300 assert!(decoded.declaration.is_root());
301 assert!(decoded.declaration.is_signed());
302 assert_eq!(decoded.ancestry.depth(), 0); assert_eq!(decoded.ancestry.entries().len(), 1);
304 assert_eq!(decoded.ancestry.entries()[0].node_addr, node_addr);
305 assert_eq!(decoded.ancestry.entries()[0].sequence, 1);
306 assert_eq!(decoded.ancestry.entries()[0].timestamp, 5000);
307 }
308
309 #[test]
310 fn test_tree_announce_encode_decode_depth3() {
311 use crate::identity::Identity;
312
313 let identity = Identity::generate();
314 let node_addr = *identity.node_addr();
315 let parent = make_node_addr(2);
316 let grandparent = make_node_addr(3);
317 let root = make_node_addr(4);
318
319 let mut decl = ParentDeclaration::new(node_addr, parent, 5, 10000);
320 decl.sign(&identity).unwrap();
321
322 let ancestry = TreeCoordinate::new(vec![
323 CoordEntry::new(node_addr, 5, 10000),
324 CoordEntry::new(parent, 4, 9000),
325 CoordEntry::new(grandparent, 3, 8000),
326 CoordEntry::new(root, 2, 7000),
327 ])
328 .unwrap();
329
330 let announce = TreeAnnounce::new(decl, ancestry);
331 let encoded = announce.encode().unwrap();
332
333 assert_eq!(encoded.len(), 228);
335
336 let decoded = TreeAnnounce::decode(&encoded[1..]).unwrap();
337
338 assert_eq!(decoded.declaration.node_addr(), &node_addr);
339 assert_eq!(decoded.declaration.parent_id(), &parent);
340 assert_eq!(decoded.declaration.sequence(), 5);
341 assert_eq!(decoded.declaration.timestamp(), 10000);
342 assert!(!decoded.declaration.is_root());
343 assert_eq!(decoded.ancestry.depth(), 3);
344 assert_eq!(decoded.ancestry.entries().len(), 4);
345
346 let entries = decoded.ancestry.entries();
348 assert_eq!(entries[0].node_addr, node_addr);
349 assert_eq!(entries[0].sequence, 5);
350 assert_eq!(entries[1].node_addr, parent);
351 assert_eq!(entries[1].sequence, 4);
352 assert_eq!(entries[2].node_addr, grandparent);
353 assert_eq!(entries[2].timestamp, 8000);
354 assert_eq!(entries[3].node_addr, root);
355 assert_eq!(entries[3].timestamp, 7000);
356
357 assert_eq!(decoded.ancestry.root_id(), &root);
359 }
360
361 #[test]
362 fn test_tree_announce_decode_unsupported_version() {
363 use crate::identity::Identity;
364
365 let identity = Identity::generate();
366 let node_addr = *identity.node_addr();
367
368 let mut decl = ParentDeclaration::new(node_addr, node_addr, 1, 1000);
369 decl.sign(&identity).unwrap();
370
371 let ancestry = TreeCoordinate::new(vec![CoordEntry::new(node_addr, 1, 1000)]).unwrap();
372 let announce = TreeAnnounce::new(decl, ancestry);
373 let mut encoded = announce.encode().unwrap();
374
375 encoded[1] = 0xFF;
377
378 let result = TreeAnnounce::decode(&encoded[1..]);
379 assert!(matches!(
380 result,
381 Err(ProtocolError::UnsupportedVersion(0xFF))
382 ));
383 }
384
385 #[test]
386 fn test_tree_announce_decode_truncated() {
387 let result = TreeAnnounce::decode(&[0x01]);
389 assert!(matches!(
390 result,
391 Err(ProtocolError::MessageTooShort { expected: 99, .. })
392 ));
393
394 let short = vec![0u8; 98];
396 let result = TreeAnnounce::decode(&short);
397 assert!(matches!(
398 result,
399 Err(ProtocolError::MessageTooShort { expected: 99, .. })
400 ));
401 }
402
403 #[test]
404 fn test_tree_announce_decode_ancestry_count_mismatch() {
405 use crate::identity::Identity;
406
407 let identity = Identity::generate();
408 let node_addr = *identity.node_addr();
409
410 let mut decl = ParentDeclaration::new(node_addr, node_addr, 1, 1000);
411 decl.sign(&identity).unwrap();
412
413 let ancestry = TreeCoordinate::new(vec![CoordEntry::new(node_addr, 1, 1000)]).unwrap();
414 let announce = TreeAnnounce::new(decl, ancestry);
415 let mut encoded = announce.encode().unwrap();
416
417 encoded[34] = 5;
420 encoded[35] = 0;
421
422 let result = TreeAnnounce::decode(&encoded[1..]);
423 assert!(matches!(result, Err(ProtocolError::MessageTooShort { .. })));
424 }
425
426 #[test]
427 fn test_tree_announce_encode_unsigned_fails() {
428 let node = make_node_addr(1);
429 let decl = ParentDeclaration::new(node, node, 1, 1000);
430 let ancestry = make_coords(&[1, 0]);
431
432 let announce = TreeAnnounce::new(decl, ancestry);
433 let result = announce.encode();
434 assert!(matches!(result, Err(ProtocolError::InvalidSignature)));
435 }
436
437 #[test]
439 fn test_tree_announce_validate_semantics_accepts_valid_non_root() {
440 use crate::identity::Identity;
441
442 let identity = loop {
446 let id = Identity::generate();
447 if id.node_addr().as_bytes()[0] > 1 {
448 break id;
449 }
450 };
451 let node_addr = *identity.node_addr();
452 let parent = make_node_addr(2);
453 let root = make_node_addr(1);
454
455 let mut decl = ParentDeclaration::new(node_addr, parent, 5, 1000);
456 decl.sign(&identity).unwrap();
457
458 let ancestry = TreeCoordinate::new(vec![
459 CoordEntry::new(node_addr, 5, 1000),
460 CoordEntry::new(parent, 4, 900),
461 CoordEntry::new(root, 3, 800),
462 ])
463 .unwrap();
464
465 let announce = TreeAnnounce::new(decl, ancestry);
466 assert!(announce.validate_semantics().is_ok());
467 }
468
469 #[test]
471 fn test_tree_announce_validate_semantics_rejects_non_minimal_root() {
472 use crate::identity::Identity;
473
474 let identity = Identity::generate();
475 let node_addr = *identity.node_addr();
476 let smaller = make_node_addr(0);
477 let advertised_root = make_node_addr(1);
478
479 let mut decl = ParentDeclaration::new(node_addr, smaller, 5, 1000);
480 decl.sign(&identity).unwrap();
481
482 let ancestry = TreeCoordinate::new(vec![
483 CoordEntry::new(node_addr, 5, 1000),
484 CoordEntry::new(smaller, 4, 900),
485 CoordEntry::new(advertised_root, 3, 800),
486 ])
487 .unwrap();
488
489 let announce = TreeAnnounce::new(decl, ancestry);
490 assert!(matches!(
491 announce.validate_semantics(),
492 Err(TreeError::AncestryRootNotMinimum {
493 advertised,
494 minimum,
495 }) if advertised == advertised_root && minimum == smaller
496 ));
497 }
498
499 #[test]
501 fn test_tree_announce_validate_semantics_rejects_parent_mismatch() {
502 use crate::identity::Identity;
503
504 let identity = Identity::generate();
505 let node_addr = *identity.node_addr();
506 let declared_parent = make_node_addr(2);
507 let ancestry_parent = make_node_addr(3);
508
509 let mut decl = ParentDeclaration::new(node_addr, declared_parent, 5, 1000);
510 decl.sign(&identity).unwrap();
511
512 let ancestry = TreeCoordinate::new(vec![
513 CoordEntry::new(node_addr, 5, 1000),
514 CoordEntry::new(ancestry_parent, 4, 900),
515 CoordEntry::new(make_node_addr(1), 3, 800),
516 ])
517 .unwrap();
518
519 let announce = TreeAnnounce::new(decl, ancestry);
520 assert!(matches!(
521 announce.validate_semantics(),
522 Err(TreeError::AncestryParentMismatch {
523 declared,
524 ancestry,
525 }) if declared == declared_parent && ancestry == ancestry_parent
526 ));
527 }
528
529 #[test]
531 fn test_tree_announce_validate_semantics_rejects_sender_mismatch() {
532 use crate::identity::Identity;
533
534 let identity = Identity::generate();
535 let node_addr = *identity.node_addr();
536 let ancestry_sender = make_node_addr(9);
537 let parent = make_node_addr(2);
538
539 let mut decl = ParentDeclaration::new(node_addr, parent, 5, 1000);
540 decl.sign(&identity).unwrap();
541
542 let ancestry = TreeCoordinate::new(vec![
543 CoordEntry::new(ancestry_sender, 5, 1000),
544 CoordEntry::new(parent, 4, 900),
545 CoordEntry::new(make_node_addr(1), 3, 800),
546 ])
547 .unwrap();
548
549 let announce = TreeAnnounce::new(decl, ancestry);
550 assert!(matches!(
551 announce.validate_semantics(),
552 Err(TreeError::AncestryNodeMismatch {
553 declared,
554 ancestry,
555 }) if declared == node_addr && ancestry == ancestry_sender
556 ));
557 }
558
559 #[test]
561 fn test_tree_announce_validate_semantics_rejects_root_with_ancestors() {
562 use crate::identity::Identity;
563
564 let identity = Identity::generate();
565 let node_addr = *identity.node_addr();
566
567 let mut decl = ParentDeclaration::self_root(node_addr, 5, 1000);
568 decl.sign(&identity).unwrap();
569
570 let ancestry = TreeCoordinate::new(vec![
571 CoordEntry::new(node_addr, 5, 1000),
572 CoordEntry::new(make_node_addr(0), 4, 900),
573 ])
574 .unwrap();
575
576 let announce = TreeAnnounce::new(decl, ancestry);
577 assert!(matches!(
578 announce.validate_semantics(),
579 Err(TreeError::RootDeclarationMismatch)
580 ));
581 }
582}