1use std::collections::HashMap;
58
59use borsh::{BorshDeserialize, BorshSerialize};
60
61use super::hash_comparison::TreeLeafData;
62
63pub const MAX_LEVELWISE_DEPTH: usize = 64;
72
73pub const MAX_PARENTS_PER_REQUEST: usize = 1000;
78
79pub const MAX_NODES_PER_LEVEL: usize = 10_000;
84
85pub const MAX_REQUESTS_PER_SESSION: u64 = 128;
91
92#[derive(Clone, Debug, PartialEq, BorshSerialize, BorshDeserialize)]
106pub struct LevelWiseRequest {
107 pub level: usize,
109
110 pub parent_ids: Option<Vec<[u8; 32]>>,
116}
117
118impl LevelWiseRequest {
119 #[must_use]
121 pub fn at_level(level: usize) -> Self {
122 Self {
123 level,
124 parent_ids: None,
125 }
126 }
127
128 #[must_use]
130 pub fn for_parents(level: usize, parent_ids: Vec<[u8; 32]>) -> Self {
131 debug_assert!(
132 parent_ids.len() <= MAX_PARENTS_PER_REQUEST,
133 "parent_ids exceeds MAX_PARENTS_PER_REQUEST ({MAX_PARENTS_PER_REQUEST})"
134 );
135 Self {
136 level,
137 parent_ids: Some(parent_ids),
138 }
139 }
140
141 #[must_use]
143 pub fn is_full_level(&self) -> bool {
144 self.parent_ids.is_none()
145 }
146
147 #[must_use]
149 pub fn parent_count(&self) -> Option<usize> {
150 self.parent_ids.as_ref().map(|p| p.len())
151 }
152
153 #[must_use]
158 pub fn is_valid(&self) -> bool {
159 if self.level > MAX_LEVELWISE_DEPTH {
161 return false;
162 }
163
164 if let Some(ref parents) = self.parent_ids {
166 if parents.len() > MAX_PARENTS_PER_REQUEST {
167 return false;
168 }
169 }
170
171 true
172 }
173}
174
175#[derive(Clone, Debug, PartialEq, BorshSerialize, BorshDeserialize)]
177pub struct LevelWiseResponse {
178 pub level: usize,
180
181 pub nodes: Vec<LevelNode>,
186
187 pub has_more_levels: bool,
189}
190
191impl LevelWiseResponse {
192 #[must_use]
194 pub fn new(level: usize, nodes: Vec<LevelNode>, has_more_levels: bool) -> Self {
195 Self {
196 level,
197 nodes,
198 has_more_levels,
199 }
200 }
201
202 #[must_use]
204 pub fn empty(level: usize) -> Self {
205 Self {
206 level,
207 nodes: vec![],
208 has_more_levels: false,
209 }
210 }
211
212 #[must_use]
214 pub fn node_count(&self) -> usize {
215 self.nodes.len()
216 }
217
218 #[must_use]
220 pub fn is_empty(&self) -> bool {
221 self.nodes.is_empty()
222 }
223
224 pub fn leaves(&self) -> impl Iterator<Item = &LevelNode> {
226 self.nodes.iter().filter(|n| n.is_leaf())
227 }
228
229 pub fn internal_nodes(&self) -> impl Iterator<Item = &LevelNode> {
231 self.nodes.iter().filter(|n| n.is_internal())
232 }
233
234 #[must_use]
236 pub fn internal_node_ids(&self) -> Vec<[u8; 32]> {
237 self.nodes
238 .iter()
239 .filter(|n| n.is_internal())
240 .map(|n| n.id)
241 .collect()
242 }
243
244 #[must_use]
250 pub fn is_valid(&self) -> bool {
251 if self.level > MAX_LEVELWISE_DEPTH {
253 return false;
254 }
255
256 if self.nodes.len() > MAX_NODES_PER_LEVEL {
258 return false;
259 }
260
261 self.nodes.iter().all(LevelNode::is_valid)
263 }
264}
265
266#[derive(Clone, Debug, PartialEq, BorshSerialize, BorshDeserialize)]
275pub struct LevelNode {
276 pub id: [u8; 32],
278
279 pub hash: [u8; 32],
281
282 pub parent_id: Option<[u8; 32]>,
284
285 pub leaf_data: Option<TreeLeafData>,
288}
289
290impl LevelNode {
291 #[must_use]
293 pub fn internal(id: [u8; 32], hash: [u8; 32], parent_id: Option<[u8; 32]>) -> Self {
294 Self {
295 id,
296 hash,
297 parent_id,
298 leaf_data: None,
299 }
300 }
301
302 #[must_use]
304 pub fn leaf(
305 id: [u8; 32],
306 hash: [u8; 32],
307 parent_id: Option<[u8; 32]>,
308 data: TreeLeafData,
309 ) -> Self {
310 Self {
311 id,
312 hash,
313 parent_id,
314 leaf_data: Some(data),
315 }
316 }
317
318 #[must_use]
320 pub fn is_leaf(&self) -> bool {
321 self.leaf_data.is_some()
322 }
323
324 #[must_use]
326 pub fn is_internal(&self) -> bool {
327 self.leaf_data.is_none()
328 }
329
330 #[must_use]
334 pub fn is_valid(&self) -> bool {
335 if let Some(ref leaf_data) = self.leaf_data {
337 if !leaf_data.is_valid() {
338 return false;
339 }
340 }
341
342 true
343 }
344}
345
346#[derive(Clone, Debug, Default)]
352pub struct LevelCompareResult {
353 pub matching: Vec<[u8; 32]>,
355
356 pub differing: Vec<[u8; 32]>,
358
359 pub local_missing: Vec<[u8; 32]>,
361
362 pub remote_missing: Vec<[u8; 32]>,
364}
365
366impl LevelCompareResult {
367 #[must_use]
369 pub fn needs_sync(&self) -> bool {
370 !self.differing.is_empty() || !self.local_missing.is_empty()
371 }
372
373 #[must_use]
377 pub fn nodes_to_process(&self) -> Vec<[u8; 32]> {
378 let mut result = Vec::with_capacity(self.differing.len() + self.local_missing.len());
379 result.extend(self.differing.iter().copied());
380 result.extend(self.local_missing.iter().copied());
381 result
382 }
383
384 #[must_use]
386 pub fn total_compared(&self) -> usize {
387 self.matching.len()
388 + self.differing.len()
389 + self.local_missing.len()
390 + self.remote_missing.len()
391 }
392}
393
394#[must_use]
404pub fn compare_level_nodes(
405 local_hashes: &HashMap<[u8; 32], [u8; 32]>,
406 remote_nodes: &[LevelNode],
407) -> LevelCompareResult {
408 let mut result = LevelCompareResult::default();
409
410 let mut remote_by_id: HashMap<[u8; 32], &LevelNode> = HashMap::new();
412 for node in remote_nodes {
413 remote_by_id.entry(node.id).or_insert(node);
414 }
415
416 for node in remote_by_id.values() {
418 match local_hashes.get(&node.id) {
419 Some(local_hash) if *local_hash == node.hash => {
420 result.matching.push(node.id);
421 }
422 Some(_) => {
423 result.differing.push(node.id);
424 }
425 None => {
426 result.local_missing.push(node.id);
427 }
428 }
429 }
430
431 for local_id in local_hashes.keys() {
433 if !remote_by_id.contains_key(local_id) {
434 result.remote_missing.push(*local_id);
435 }
436 }
437
438 result
439}
440
441#[must_use]
450pub fn should_use_levelwise(max_depth: usize, avg_children_per_level: usize) -> bool {
451 (1..=2).contains(&max_depth) && avg_children_per_level > 10
454}
455
456#[cfg(test)]
461mod tests {
462 use super::*;
463 use crate::sync::hash_comparison::{CrdtType, LeafMetadata, MAX_LEAF_VALUE_SIZE};
464
465 fn make_leaf_data(key: u8, value: Vec<u8>) -> TreeLeafData {
470 let metadata = LeafMetadata::new(CrdtType::lww_register("test"), 100, [key; 32]);
471 TreeLeafData::new([key; 32], value, metadata)
472 }
473
474 #[test]
479 fn test_levelwise_request_at_level() {
480 let request = LevelWiseRequest::at_level(2);
481
482 assert_eq!(request.level, 2);
483 assert!(request.is_full_level());
484 assert!(request.parent_count().is_none());
485 assert!(request.is_valid());
486 }
487
488 #[test]
489 fn test_levelwise_request_for_parents() {
490 let parents = vec![[1u8; 32], [2u8; 32]];
491 let request = LevelWiseRequest::for_parents(1, parents.clone());
492
493 assert_eq!(request.level, 1);
494 assert!(!request.is_full_level());
495 assert_eq!(request.parent_count(), Some(2));
496 assert_eq!(request.parent_ids, Some(parents));
497 assert!(request.is_valid());
498 }
499
500 #[test]
501 fn test_levelwise_request_roundtrip() {
502 let request = LevelWiseRequest::for_parents(3, vec![[1u8; 32]]);
503
504 let encoded = borsh::to_vec(&request).expect("serialize");
505 let decoded: LevelWiseRequest = borsh::from_slice(&encoded).expect("deserialize");
506
507 assert_eq!(request, decoded);
508 }
509
510 #[test]
511 fn test_levelwise_request_validation() {
512 let at_limit = LevelWiseRequest::at_level(MAX_LEVELWISE_DEPTH);
514 assert!(at_limit.is_valid());
515
516 let over_level = LevelWiseRequest::at_level(MAX_LEVELWISE_DEPTH + 1);
518 assert!(!over_level.is_valid());
519
520 let parents: Vec<[u8; 32]> = (0..MAX_PARENTS_PER_REQUEST)
522 .map(|i| [i as u8; 32])
523 .collect();
524 let at_parent_limit = LevelWiseRequest::for_parents(0, parents);
525 assert!(at_parent_limit.is_valid());
526
527 let parents: Vec<[u8; 32]> = (0..=MAX_PARENTS_PER_REQUEST)
529 .map(|i| [i as u8; 32])
530 .collect();
531 let over_parent_limit = LevelWiseRequest {
532 level: 0,
533 parent_ids: Some(parents),
534 };
535 assert!(!over_parent_limit.is_valid());
536 }
537
538 #[test]
543 fn test_level_node_internal() {
544 let node = LevelNode::internal([1; 32], [2; 32], Some([0; 32]));
545
546 assert!(node.is_internal());
547 assert!(!node.is_leaf());
548 assert_eq!(node.parent_id, Some([0; 32]));
549 assert!(node.is_valid());
550 }
551
552 #[test]
553 fn test_level_node_leaf() {
554 let leaf_data = make_leaf_data(3, vec![1, 2, 3]);
555 let node = LevelNode::leaf([1; 32], [2; 32], None, leaf_data);
556
557 assert!(node.is_leaf());
558 assert!(!node.is_internal());
559 assert!(node.parent_id.is_none());
560 assert!(node.is_valid());
561 }
562
563 #[test]
564 fn test_level_node_roundtrip() {
565 let leaf_data = make_leaf_data(4, vec![4, 5, 6]);
566 let node = LevelNode::leaf([1; 32], [2; 32], Some([0; 32]), leaf_data);
567
568 let encoded = borsh::to_vec(&node).expect("serialize");
569 let decoded: LevelNode = borsh::from_slice(&encoded).expect("deserialize");
570
571 assert_eq!(node, decoded);
572 }
573
574 #[test]
575 fn test_level_node_validation() {
576 let internal = LevelNode::internal([1; 32], [2; 32], None);
578 assert!(internal.is_valid());
579
580 let leaf_data = make_leaf_data(1, vec![1, 2, 3]);
582 let valid_leaf = LevelNode::leaf([1; 32], [2; 32], None, leaf_data);
583 assert!(valid_leaf.is_valid());
584
585 let metadata = LeafMetadata::new(CrdtType::lww_register("test"), 100, [1; 32]);
587 let invalid_leaf_data =
588 TreeLeafData::new([1; 32], vec![0u8; MAX_LEAF_VALUE_SIZE + 1], metadata);
589 let invalid_leaf = LevelNode::leaf([1; 32], [2; 32], None, invalid_leaf_data);
590 assert!(!invalid_leaf.is_valid());
591 }
592
593 #[test]
598 fn test_levelwise_response_new() {
599 let node1 = LevelNode::internal([1; 32], [2; 32], None);
600 let node2 = LevelNode::internal([3; 32], [4; 32], None);
601
602 let response = LevelWiseResponse::new(0, vec![node1, node2], true);
603
604 assert_eq!(response.level, 0);
605 assert_eq!(response.node_count(), 2);
606 assert!(response.has_more_levels);
607 assert!(!response.is_empty());
608 assert!(response.is_valid());
609 }
610
611 #[test]
612 fn test_levelwise_response_empty() {
613 let response = LevelWiseResponse::empty(3);
614
615 assert_eq!(response.level, 3);
616 assert!(response.is_empty());
617 assert!(!response.has_more_levels);
618 assert!(response.is_valid());
619 }
620
621 #[test]
622 fn test_levelwise_response_leaves_and_internal() {
623 let internal = LevelNode::internal([1; 32], [2; 32], None);
624 let leaf_data = make_leaf_data(6, vec![7, 8]);
625 let leaf = LevelNode::leaf([3; 32], [4; 32], None, leaf_data);
626
627 let response = LevelWiseResponse::new(1, vec![internal, leaf], false);
628
629 assert_eq!(response.leaves().count(), 1);
630 assert_eq!(response.internal_nodes().count(), 1);
631 assert_eq!(response.internal_node_ids(), vec![[1; 32]]);
632 }
633
634 #[test]
635 fn test_levelwise_response_roundtrip() {
636 let node = LevelNode::internal([1; 32], [2; 32], Some([0; 32]));
637 let response = LevelWiseResponse::new(2, vec![node], true);
638
639 let encoded = borsh::to_vec(&response).expect("serialize");
640 let decoded: LevelWiseResponse = borsh::from_slice(&encoded).expect("deserialize");
641
642 assert_eq!(response, decoded);
643 }
644
645 #[test]
646 fn test_levelwise_response_validation() {
647 let nodes: Vec<LevelNode> = (0..MAX_NODES_PER_LEVEL)
649 .map(|i| LevelNode::internal([i as u8; 32], [i as u8; 32], None))
650 .collect();
651 let at_limit = LevelWiseResponse::new(0, nodes, false);
652 assert!(at_limit.is_valid());
653
654 let nodes: Vec<LevelNode> = (0..=MAX_NODES_PER_LEVEL)
656 .map(|i| LevelNode::internal([i as u8; 32], [i as u8; 32], None))
657 .collect();
658 let over_limit = LevelWiseResponse::new(0, nodes, false);
659 assert!(!over_limit.is_valid());
660
661 let over_level = LevelWiseResponse::new(MAX_LEVELWISE_DEPTH + 1, vec![], false);
663 assert!(!over_level.is_valid());
664
665 let metadata = LeafMetadata::new(CrdtType::lww_register("test"), 100, [1; 32]);
667 let invalid_leaf_data =
668 TreeLeafData::new([1; 32], vec![0u8; MAX_LEAF_VALUE_SIZE + 1], metadata);
669 let invalid_node = LevelNode::leaf([1; 32], [2; 32], None, invalid_leaf_data);
670 let response_with_invalid = LevelWiseResponse::new(0, vec![invalid_node], false);
671 assert!(!response_with_invalid.is_valid());
672 }
673
674 #[test]
679 fn test_level_compare_result() {
680 let mut result = LevelCompareResult::default();
681 result.matching.push([1; 32]);
682 result.differing.push([2; 32]);
683 result.local_missing.push([3; 32]);
684 result.remote_missing.push([4; 32]);
685
686 assert!(result.needs_sync());
687 assert_eq!(result.total_compared(), 4);
688 assert_eq!(result.nodes_to_process().len(), 2); }
690
691 #[test]
692 fn test_level_compare_result_no_sync() {
693 let mut result = LevelCompareResult::default();
694 result.matching.push([1; 32]);
695 result.remote_missing.push([2; 32]);
696
697 assert!(!result.needs_sync());
698 assert!(result.nodes_to_process().is_empty());
699 }
700
701 #[test]
706 fn test_compare_level_nodes() {
707 let mut local_hashes = HashMap::new();
708 local_hashes.insert([1; 32], [10; 32]); local_hashes.insert([2; 32], [20; 32]); local_hashes.insert([4; 32], [40; 32]); let remote_nodes = vec![
713 LevelNode::internal([1; 32], [10; 32], None), LevelNode::internal([2; 32], [21; 32], None), LevelNode::internal([3; 32], [30; 32], None), ];
717 let response = LevelWiseResponse::new(0, remote_nodes, true);
718
719 let result = compare_level_nodes(&local_hashes, &response.nodes);
720
721 assert_eq!(result.matching, vec![[1; 32]]);
722 assert_eq!(result.differing, vec![[2; 32]]);
723 assert_eq!(result.local_missing, vec![[3; 32]]);
724 assert_eq!(result.remote_missing, vec![[4; 32]]);
725 }
726
727 #[test]
728 fn test_compare_level_nodes_all_matching() {
729 let mut local_hashes = HashMap::new();
730 local_hashes.insert([1; 32], [10; 32]);
731 local_hashes.insert([2; 32], [20; 32]);
732
733 let remote_nodes = vec![
734 LevelNode::internal([1; 32], [10; 32], None),
735 LevelNode::internal([2; 32], [20; 32], None),
736 ];
737 let response = LevelWiseResponse::new(0, remote_nodes, false);
738
739 let result = compare_level_nodes(&local_hashes, &response.nodes);
740
741 assert_eq!(result.matching.len(), 2);
742 assert!(result.differing.is_empty());
743 assert!(result.local_missing.is_empty());
744 assert!(result.remote_missing.is_empty());
745 assert!(!result.needs_sync());
746 }
747
748 #[test]
749 fn test_compare_level_nodes_all_local_missing() {
750 let local_hashes: HashMap<[u8; 32], [u8; 32]> = HashMap::new();
751
752 let remote_nodes = vec![
753 LevelNode::internal([1; 32], [10; 32], None),
754 LevelNode::internal([2; 32], [20; 32], None),
755 ];
756 let response = LevelWiseResponse::new(0, remote_nodes, false);
757
758 let result = compare_level_nodes(&local_hashes, &response.nodes);
759
760 assert!(result.matching.is_empty());
761 assert!(result.differing.is_empty());
762 assert_eq!(result.local_missing.len(), 2);
763 assert!(result.remote_missing.is_empty());
764 assert!(result.needs_sync());
765 }
766
767 #[test]
768 fn test_compare_level_nodes_empty_response() {
769 let mut local_hashes = HashMap::new();
770 local_hashes.insert([1; 32], [10; 32]);
771 local_hashes.insert([2; 32], [20; 32]);
772
773 let response = LevelWiseResponse::empty(0);
774
775 let result = compare_level_nodes(&local_hashes, &response.nodes);
776
777 assert!(result.matching.is_empty());
778 assert!(result.differing.is_empty());
779 assert!(result.local_missing.is_empty());
780 assert_eq!(result.remote_missing.len(), 2);
781 assert!(!result.needs_sync());
782 }
783
784 #[test]
789 fn test_should_use_levelwise() {
790 assert!(should_use_levelwise(2, 15));
792 assert!(should_use_levelwise(1, 100));
793
794 assert!(!should_use_levelwise(0, 50));
796
797 assert!(!should_use_levelwise(3, 15));
799 assert!(!should_use_levelwise(5, 100));
800
801 assert!(!should_use_levelwise(2, 5));
803 assert!(!should_use_levelwise(1, 10)); }
805
806 #[test]
807 fn test_should_use_levelwise_boundary_conditions() {
808 assert!(should_use_levelwise(1, 15)); assert!(should_use_levelwise(2, 15)); assert!(!should_use_levelwise(3, 15)); assert!(!should_use_levelwise(2, 10)); assert!(should_use_levelwise(2, 11)); assert!(!should_use_levelwise(0, 100)); assert!(!should_use_levelwise(0, 0)); }
821
822 #[test]
827 fn test_levelwise_request_memory_exhaustion_prevention() {
828 let parents: Vec<[u8; 32]> = (0..MAX_PARENTS_PER_REQUEST)
830 .map(|i| [i as u8; 32])
831 .collect();
832 let valid = LevelWiseRequest::for_parents(0, parents);
833 assert!(valid.is_valid());
834
835 let parents: Vec<[u8; 32]> = (0..=MAX_PARENTS_PER_REQUEST)
837 .map(|i| [i as u8; 32])
838 .collect();
839 let invalid = LevelWiseRequest {
840 level: 0,
841 parent_ids: Some(parents),
842 };
843 assert!(!invalid.is_valid());
844 }
845
846 #[test]
847 fn test_levelwise_response_memory_exhaustion_prevention() {
848 let nodes: Vec<LevelNode> = (0..MAX_NODES_PER_LEVEL)
850 .map(|i| LevelNode::internal([i as u8; 32], [i as u8; 32], None))
851 .collect();
852 let valid = LevelWiseResponse::new(0, nodes, false);
853 assert!(valid.is_valid());
854
855 let nodes: Vec<LevelNode> = (0..=MAX_NODES_PER_LEVEL)
857 .map(|i| LevelNode::internal([i as u8; 32], [i as u8; 32], None))
858 .collect();
859 let invalid = LevelWiseResponse::new(0, nodes, false);
860 assert!(!invalid.is_valid());
861 }
862
863 #[test]
864 fn test_levelwise_special_values() {
865 let zeros_node = LevelNode::internal([0u8; 32], [0u8; 32], Some([0u8; 32]));
867 assert!(zeros_node.is_valid());
868
869 let ones_node = LevelNode::internal([0xFF; 32], [0xFF; 32], Some([0xFF; 32]));
871 assert!(ones_node.is_valid());
872
873 let request = LevelWiseRequest::at_level(0);
875 assert!(request.is_valid());
876
877 let response = LevelWiseResponse::new(0, vec![zeros_node], false);
879 assert!(response.is_valid());
880 assert!(!response.has_more_levels);
881 }
882
883 #[test]
884 fn test_levelwise_cross_validation_consistency() {
885 let metadata = LeafMetadata::new(CrdtType::lww_register("test"), 100, [1; 32]);
887 let oversized_leaf_data =
888 TreeLeafData::new([1; 32], vec![0u8; MAX_LEAF_VALUE_SIZE + 1], metadata);
889 let invalid_node = LevelNode::leaf([1; 32], [2; 32], None, oversized_leaf_data);
890
891 assert!(!invalid_node.is_valid());
893
894 let response = LevelWiseResponse::new(0, vec![invalid_node], false);
896 assert!(!response.is_valid());
897 }
898
899 #[test]
904 fn test_levelwise_request_empty_parent_ids() {
905 let request = LevelWiseRequest::for_parents(0, vec![]);
907 assert!(request.is_valid());
908 assert!(!request.is_full_level()); assert_eq!(request.parent_count(), Some(0));
910 }
911
912 #[test]
913 fn test_levelwise_request_zero_level() {
914 let request = LevelWiseRequest::at_level(0);
915 assert_eq!(request.level, 0);
916 assert!(request.is_valid());
917 }
918
919 #[test]
920 fn test_levelwise_request_single_parent() {
921 let request = LevelWiseRequest::for_parents(1, vec![[42u8; 32]]);
922 assert_eq!(request.parent_count(), Some(1));
923 assert!(request.is_valid());
924 }
925
926 #[test]
927 fn test_levelwise_response_single_node() {
928 let node = LevelNode::internal([1; 32], [2; 32], None);
929 let response = LevelWiseResponse::new(0, vec![node], true);
930
931 assert_eq!(response.node_count(), 1);
932 assert!(response.is_valid());
933 }
934
935 #[test]
936 fn test_levelwise_response_all_leaves() {
937 let leaves: Vec<LevelNode> = (0..5)
938 .map(|i| {
939 let leaf_data = make_leaf_data(i as u8, vec![i as u8]);
940 LevelNode::leaf([i as u8; 32], [(i + 100) as u8; 32], None, leaf_data)
941 })
942 .collect();
943 let response = LevelWiseResponse::new(0, leaves, false);
944
945 assert_eq!(response.leaves().count(), 5);
946 assert_eq!(response.internal_nodes().count(), 0);
947 assert!(response.internal_node_ids().is_empty());
948 assert!(response.is_valid());
949 }
950
951 #[test]
952 fn test_levelwise_response_all_internal() {
953 let nodes: Vec<LevelNode> = (0..5)
954 .map(|i| LevelNode::internal([i as u8; 32], [(i + 100) as u8; 32], None))
955 .collect();
956 let response = LevelWiseResponse::new(0, nodes, true);
957
958 assert_eq!(response.leaves().count(), 0);
959 assert_eq!(response.internal_nodes().count(), 5);
960 assert_eq!(response.internal_node_ids().len(), 5);
961 assert!(response.is_valid());
962 }
963
964 #[test]
965 fn test_level_node_with_various_parent_ids() {
966 let node_no_parent = LevelNode::internal([1; 32], [2; 32], None);
968 assert!(node_no_parent.parent_id.is_none());
969 assert!(node_no_parent.is_valid());
970
971 let node_with_parent = LevelNode::internal([1; 32], [2; 32], Some([99; 32]));
973 assert_eq!(node_with_parent.parent_id, Some([99; 32]));
974 assert!(node_with_parent.is_valid());
975
976 let node_zeros_parent = LevelNode::internal([1; 32], [2; 32], Some([0; 32]));
978 assert!(node_zeros_parent.is_valid());
979
980 let node_ones_parent = LevelNode::internal([1; 32], [2; 32], Some([0xFF; 32]));
982 assert!(node_ones_parent.is_valid());
983 }
984
985 #[test]
986 fn test_level_node_leaf_with_empty_value() {
987 let metadata = LeafMetadata::new(CrdtType::lww_register("test"), 100, [1; 32]);
988 let leaf_data = TreeLeafData::new([1; 32], vec![], metadata);
989 let node = LevelNode::leaf([1; 32], [2; 32], None, leaf_data);
990
991 assert!(node.is_leaf());
992 assert!(node.is_valid());
993 }
994
995 #[test]
996 fn test_level_node_leaf_at_max_value_size() {
997 let metadata = LeafMetadata::new(CrdtType::lww_register("test"), 100, [1; 32]);
998 let leaf_data = TreeLeafData::new([1; 32], vec![0u8; MAX_LEAF_VALUE_SIZE], metadata);
999 let node = LevelNode::leaf([1; 32], [2; 32], None, leaf_data);
1000
1001 assert!(node.is_valid());
1002 }
1003
1004 #[test]
1005 fn test_compare_level_nodes_both_empty() {
1006 let local_hashes: HashMap<[u8; 32], [u8; 32]> = HashMap::new();
1007 let response = LevelWiseResponse::empty(0);
1008
1009 let result = compare_level_nodes(&local_hashes, &response.nodes);
1010
1011 assert!(result.matching.is_empty());
1012 assert!(result.differing.is_empty());
1013 assert!(result.local_missing.is_empty());
1014 assert!(result.remote_missing.is_empty());
1015 assert_eq!(result.total_compared(), 0);
1016 assert!(!result.needs_sync());
1017 }
1018
1019 #[test]
1020 fn test_compare_level_nodes_all_differing() {
1021 let mut local_hashes = HashMap::new();
1022 local_hashes.insert([1; 32], [10; 32]);
1023 local_hashes.insert([2; 32], [20; 32]);
1024 local_hashes.insert([3; 32], [30; 32]);
1025
1026 let remote_nodes = vec![
1028 LevelNode::internal([1; 32], [11; 32], None), LevelNode::internal([2; 32], [21; 32], None), LevelNode::internal([3; 32], [31; 32], None), ];
1032 let response = LevelWiseResponse::new(0, remote_nodes, false);
1033
1034 let result = compare_level_nodes(&local_hashes, &response.nodes);
1035
1036 assert!(result.matching.is_empty());
1037 assert_eq!(result.differing.len(), 3);
1038 assert!(result.local_missing.is_empty());
1039 assert!(result.remote_missing.is_empty());
1040 assert!(result.needs_sync());
1041 }
1042
1043 #[test]
1044 fn test_compare_level_nodes_all_remote_missing() {
1045 let mut local_hashes = HashMap::new();
1046 local_hashes.insert([1; 32], [10; 32]);
1047 local_hashes.insert([2; 32], [20; 32]);
1048 local_hashes.insert([3; 32], [30; 32]);
1049
1050 let response = LevelWiseResponse::empty(0);
1052
1053 let result = compare_level_nodes(&local_hashes, &response.nodes);
1054
1055 assert!(result.matching.is_empty());
1056 assert!(result.differing.is_empty());
1057 assert!(result.local_missing.is_empty());
1058 assert_eq!(result.remote_missing.len(), 3);
1059 assert!(!result.needs_sync()); }
1061
1062 #[test]
1063 fn test_level_compare_result_only_differing() {
1064 let mut result = LevelCompareResult::default();
1065 result.differing.push([1; 32]);
1066 result.differing.push([2; 32]);
1067
1068 assert!(result.needs_sync());
1069 assert_eq!(result.nodes_to_process().len(), 2);
1070 assert_eq!(result.total_compared(), 2);
1071 }
1072
1073 #[test]
1074 fn test_level_compare_result_only_local_missing() {
1075 let mut result = LevelCompareResult::default();
1076 result.local_missing.push([1; 32]);
1077 result.local_missing.push([2; 32]);
1078
1079 assert!(result.needs_sync());
1080 assert_eq!(result.nodes_to_process().len(), 2);
1081 assert_eq!(result.total_compared(), 2);
1082 }
1083
1084 #[test]
1085 fn test_level_compare_result_only_matching() {
1086 let mut result = LevelCompareResult::default();
1087 result.matching.push([1; 32]);
1088 result.matching.push([2; 32]);
1089 result.matching.push([3; 32]);
1090
1091 assert!(!result.needs_sync());
1092 assert!(result.nodes_to_process().is_empty());
1093 assert_eq!(result.total_compared(), 3);
1094 }
1095
1096 #[test]
1101 fn test_levelwise_request_level_overflow_prevention() {
1102 let mut request = LevelWiseRequest::at_level(0);
1105 request.level = usize::MAX;
1106
1107 assert!(!request.is_valid());
1108 }
1109
1110 #[test]
1111 fn test_levelwise_response_level_overflow_prevention() {
1112 let mut response = LevelWiseResponse::empty(0);
1114 response.level = usize::MAX;
1115
1116 assert!(!response.is_valid());
1117 }
1118
1119 #[test]
1120 fn test_levelwise_request_both_limits_at_boundary() {
1121 let parents: Vec<[u8; 32]> = (0..MAX_PARENTS_PER_REQUEST)
1123 .map(|i| [i as u8; 32])
1124 .collect();
1125 let request = LevelWiseRequest {
1126 level: MAX_LEVELWISE_DEPTH,
1127 parent_ids: Some(parents),
1128 };
1129
1130 assert!(request.is_valid());
1131
1132 let parents_over: Vec<[u8; 32]> = (0..=MAX_PARENTS_PER_REQUEST)
1134 .map(|i| [i as u8; 32])
1135 .collect();
1136 let request_over = LevelWiseRequest {
1137 level: MAX_LEVELWISE_DEPTH,
1138 parent_ids: Some(parents_over),
1139 };
1140 assert!(!request_over.is_valid());
1141 }
1142
1143 #[test]
1144 fn test_levelwise_response_with_mixed_valid_invalid_nodes() {
1145 let valid_nodes: Vec<LevelNode> = (0..5)
1147 .map(|i| LevelNode::internal([i as u8; 32], [i as u8; 32], None))
1148 .collect();
1149
1150 let metadata = LeafMetadata::new(CrdtType::lww_register("test"), 100, [1; 32]);
1151 let oversized_leaf_data =
1152 TreeLeafData::new([1; 32], vec![0u8; MAX_LEAF_VALUE_SIZE + 1], metadata);
1153 let invalid_node = LevelNode::leaf([99; 32], [99; 32], None, oversized_leaf_data);
1154
1155 let mut all_nodes = valid_nodes;
1156 all_nodes.push(invalid_node);
1157
1158 let response = LevelWiseResponse::new(0, all_nodes, false);
1159
1160 assert!(!response.is_valid());
1162 }
1163
1164 #[test]
1165 fn test_levelwise_serialization_roundtrip_with_edge_values() {
1166 let parents: Vec<[u8; 32]> = vec![[0xFF; 32], [0u8; 32]];
1168 let request = LevelWiseRequest {
1169 level: MAX_LEVELWISE_DEPTH,
1170 parent_ids: Some(parents),
1171 };
1172
1173 let encoded = borsh::to_vec(&request).expect("serialize");
1174 let decoded: LevelWiseRequest = borsh::from_slice(&encoded).expect("deserialize");
1175
1176 assert_eq!(request, decoded);
1177 assert!(decoded.is_valid());
1178 }
1179
1180 #[test]
1181 fn test_levelwise_response_serialization_roundtrip_with_max_level() {
1182 let node = LevelNode::internal([0xFF; 32], [0u8; 32], Some([0x55; 32]));
1183 let response = LevelWiseResponse::new(MAX_LEVELWISE_DEPTH, vec![node], false);
1184
1185 let encoded = borsh::to_vec(&response).expect("serialize");
1186 let decoded: LevelWiseResponse = borsh::from_slice(&encoded).expect("deserialize");
1187
1188 assert_eq!(response, decoded);
1189 assert!(decoded.is_valid());
1190 assert_eq!(decoded.level, MAX_LEVELWISE_DEPTH);
1191 }
1192
1193 #[test]
1194 fn test_levelwise_malicious_deserialization_level() {
1195 let node = LevelNode::internal([1; 32], [2; 32], None);
1200 let mut response = LevelWiseResponse::new(0, vec![node], false);
1201 response.level = MAX_LEVELWISE_DEPTH + 100; assert!(!response.is_valid());
1205 }
1206
1207 #[test]
1208 fn test_compare_level_nodes_with_duplicate_ids_in_response() {
1209 let mut local_hashes = HashMap::new();
1211 local_hashes.insert([1; 32], [10; 32]);
1212
1213 let remote_nodes = vec![
1215 LevelNode::internal([1; 32], [10; 32], None), LevelNode::internal([1; 32], [11; 32], None), ];
1218 let response = LevelWiseResponse::new(0, remote_nodes, false);
1219
1220 let result = compare_level_nodes(&local_hashes, &response.nodes);
1221
1222 assert_eq!(result.matching.len(), 1);
1225 assert_eq!(result.differing.len(), 0);
1226 assert_eq!(result.local_missing.len(), 0);
1227 assert_eq!(result.remote_missing.len(), 0);
1228 assert_eq!(result.total_compared(), 1);
1229 }
1230
1231 #[test]
1232 fn test_levelwise_node_with_zero_hash() {
1233 let node = LevelNode::internal([1; 32], [0u8; 32], None);
1235 assert!(node.is_valid());
1236
1237 let node_zero_id = LevelNode::internal([0u8; 32], [1; 32], None);
1239 assert!(node_zero_id.is_valid());
1240 }
1241
1242 #[test]
1243 fn test_levelwise_leaf_with_all_metadata_variants() {
1244 let crdt_types = [
1246 CrdtType::lww_register("test"),
1247 CrdtType::GCounter,
1248 CrdtType::PnCounter,
1249 CrdtType::Rga,
1250 CrdtType::unordered_map("String", "u64"),
1251 CrdtType::unordered_set("String"),
1252 CrdtType::vector("u64"),
1253 ];
1254
1255 for crdt_type in crdt_types {
1256 let metadata = LeafMetadata::new(crdt_type.clone(), 12345, [1; 32])
1257 .with_version(100)
1258 .with_parent([2; 32]);
1259 let leaf_data = TreeLeafData::new([1; 32], vec![1, 2, 3], metadata);
1260 let node = LevelNode::leaf([1; 32], [2; 32], None, leaf_data);
1261
1262 assert!(node.is_valid());
1263
1264 let encoded = borsh::to_vec(&node).expect("serialize");
1266 let decoded: LevelNode = borsh::from_slice(&encoded).expect("deserialize");
1267 assert_eq!(node, decoded);
1268 }
1269 }
1270
1271 #[test]
1272 fn test_should_use_levelwise_extreme_values() {
1273 assert!(!should_use_levelwise(usize::MAX, 100));
1275
1276 assert!(should_use_levelwise(2, usize::MAX));
1278
1279 assert!(!should_use_levelwise(usize::MAX, usize::MAX));
1281
1282 assert!(!should_use_levelwise(0, 0));
1284 assert!(!should_use_levelwise(0, usize::MAX));
1285 }
1286
1287 #[test]
1288 fn test_levelwise_response_validation_with_deeply_nested_invalid_data() {
1289 let metadata = LeafMetadata::new(CrdtType::lww_register("test"), 100, [1; 32]);
1291
1292 let valid_leaf_data =
1294 TreeLeafData::new([1; 32], vec![0u8; MAX_LEAF_VALUE_SIZE], metadata.clone());
1295 let valid_node = LevelNode::leaf([1; 32], [2; 32], None, valid_leaf_data);
1296 assert!(valid_node.is_valid());
1297
1298 let invalid_leaf_data =
1300 TreeLeafData::new([2; 32], vec![0u8; MAX_LEAF_VALUE_SIZE + 1], metadata);
1301 let invalid_node = LevelNode::leaf([2; 32], [3; 32], None, invalid_leaf_data);
1302 assert!(!invalid_node.is_valid());
1303
1304 let valid_response = LevelWiseResponse::new(0, vec![valid_node.clone()], false);
1306 assert!(valid_response.is_valid());
1307
1308 let invalid_response = LevelWiseResponse::new(0, vec![invalid_node], false);
1310 assert!(!invalid_response.is_valid());
1311 }
1312
1313 #[test]
1314 fn test_level_compare_result_nodes_to_process_order() {
1315 let mut result = LevelCompareResult::default();
1317 result.differing.push([1; 32]);
1318 result.differing.push([2; 32]);
1319 result.local_missing.push([3; 32]);
1320 result.local_missing.push([4; 32]);
1321
1322 let to_process = result.nodes_to_process();
1323 assert_eq!(to_process.len(), 4);
1324 assert_eq!(to_process[0], [1; 32]);
1326 assert_eq!(to_process[1], [2; 32]);
1327 assert_eq!(to_process[2], [3; 32]);
1329 assert_eq!(to_process[3], [4; 32]);
1330 }
1331
1332 #[test]
1333 fn test_levelwise_response_multiple_invalid_nodes() {
1334 let metadata = LeafMetadata::new(CrdtType::lww_register("test"), 100, [1; 32]);
1336 let oversized_data = vec![0u8; MAX_LEAF_VALUE_SIZE + 1];
1337
1338 let nodes = vec![
1339 LevelNode::internal([1; 32], [1; 32], None), LevelNode::leaf(
1341 [2; 32],
1342 [2; 32],
1343 None,
1344 TreeLeafData::new([2; 32], oversized_data.clone(), metadata.clone()),
1345 ), LevelNode::internal([3; 32], [3; 32], None), LevelNode::leaf(
1348 [4; 32],
1349 [4; 32],
1350 None,
1351 TreeLeafData::new([4; 32], oversized_data, metadata),
1352 ), ];
1354
1355 let response = LevelWiseResponse::new(0, nodes, false);
1356 assert!(!response.is_valid());
1357 }
1358
1359 #[test]
1360 fn test_levelwise_empty_structures_are_valid() {
1361 let empty_request = LevelWiseRequest::at_level(0);
1363 assert!(empty_request.is_valid());
1364
1365 let empty_response = LevelWiseResponse::empty(0);
1367 assert!(empty_response.is_valid());
1368 assert!(empty_response.is_empty());
1369
1370 let empty_result = LevelCompareResult::default();
1372 assert!(!empty_result.needs_sync());
1373 assert!(empty_result.nodes_to_process().is_empty());
1374 assert_eq!(empty_result.total_compared(), 0);
1375 }
1376}