1
+ public class MerkleTree {
2
+
3
+ /*
4
+ Merkle trees allow for effecient and secure verification of large data structures.
5
+ With the structure of tree, we can easily identify map large amounts of data and
6
+ easily identify where changes in the data occur.
7
+ */
8
+
9
+ private static class Node {
10
+ String data ;
11
+ Node left ;
12
+ Node right ;
13
+ Node (String value ) {
14
+ this .data = value ;
15
+ }
16
+
17
+ }
18
+
19
+ private Node root ;
20
+
21
+ public static void main (String [] args ) {
22
+ Queue <Node > q = new LinkedList <>();
23
+ q .add (new Node ("A" ));
24
+ q .add (new Node ("B" ));
25
+ q .add (new Node ("C" ));
26
+ q .add (new Node ("D" ));
27
+ q .add (new Node ("E" ));
28
+ MerkleTree mt = new MerkleTree ();
29
+ Node root1 = mt .buildTree (q );
30
+
31
+ Queue <Node > q2 = new LinkedList <>();
32
+ q2 .add (new Node ("AA" )); // data changed here
33
+ q2 .add (new Node ("B" ));
34
+ q2 .add (new Node ("C" ));
35
+ q2 .add (new Node ("D" ));
36
+ q2 .add (new Node ("E" ));
37
+ MerkleTree mt2 = new MerkleTree ();
38
+ Node root2 = mt .buildTree (q );
39
+
40
+ if (mt .detectChange (root1 , root2 )) {
41
+ root1 = mt .mergeChange (root1 , root2 );
42
+ }
43
+
44
+ }
45
+
46
+
47
+ public Node buildTree (Queue <Node > q ) {
48
+ if (q .pop () == null ) {
49
+ return ;
50
+ }
51
+ Node new_node = q .pop ();
52
+ new_node .left = buildTree (q );
53
+ new_node .right = buildTree (q );
54
+
55
+ CRC32 crc = new CRC32 ();
56
+ crc .update ((new_node .left .data + (new_node .right != null ) ? new_node .right .data : "" ).getBytes ());
57
+ Node root = new Node (crc .getValue () + "" );
58
+ return root ;
59
+ }
60
+
61
+ public boolean detectChange (Node refNode , Node newNode ) {
62
+ if (refNode == null && new_node == null ) return false ; // no change, base check
63
+ if (refNode == null || new_node == null ) return true ; // change detected, data added/deleted
64
+
65
+ boolean leftChanged = detectChange (refNode .left , new_node .left );
66
+ boolean rightChanged = detectChange (refNode .right , new_node .right );
67
+ if (refNode .data != new_node .data ) return true ;
68
+
69
+ return leftChanged || rightChanged ;
70
+ }
71
+
72
+
73
+ public Node mergeChange (Node refNode , Node new_node ) {
74
+ if (refNode == null && new_node == null ) return null ;
75
+ else if (refNode != null && new_node == null ) {
76
+ return null ; //changed detected. Data deleted
77
+ }
78
+
79
+ else if (refNode == null && new_node != null ) {
80
+ return new_node ; // change deteced. Data added
81
+ }
82
+ else if (refNode .data != new_node .data ) {
83
+ refNode .data = new_node .data ;
84
+ }
85
+ refNode .left = mergeChange (refNode .left , new_node .left );
86
+ refNode .right = mergeChange (refNode .right , new_node .right );
87
+
88
+ return refNode ;
89
+ }
90
+
91
+
92
+ }
0 commit comments