1
1
package org .tron .core .capsule .utils ;
2
2
3
- import static org .junit .Assert .assertEquals ;
4
-
5
- import com .google .protobuf .ByteString ;
3
+ import java .util .ArrayList ;
6
4
import java .util .List ;
7
- import java .util .Vector ;
8
- import java .util .stream .Collectors ;
9
5
import lombok .extern .slf4j .Slf4j ;
10
- import org .junit .Ignore ;
6
+ import org .junit .Assert ;
11
7
import org .junit .Test ;
12
8
import org .tron .common .utils .ByteArray ;
13
9
import org .tron .common .utils .Sha256Hash ;
14
- import org .tron .core .capsule .BlockCapsule ;
15
- import org .tron .core .capsule .TransactionCapsule ;
16
- import org .tron .protos .Protocol ;
10
+ import org .tron .core .capsule .utils .MerkleTree .Leaf ;
17
11
18
12
@ Slf4j
19
13
public class MerkleTreeTest {
20
14
21
- private static BlockCapsule blockCapsule0 = new BlockCapsule (1 , ByteString
22
- .copyFrom (ByteArray
23
- .fromHexString ("9938a342238077182498b464ac0292229938a342238077182498b464ac029222" )), 1234 ,
24
- ByteString .copyFrom ("1234567" .getBytes ()));
25
-
26
- private static BlockCapsule blockCapsule1 = new BlockCapsule (1 , ByteString
27
- .copyFrom (ByteArray
28
- .fromHexString ("9938a342238077182498b464ac0292229938a342238077182498b464ac029222" )), 1234 ,
29
- ByteString .copyFrom ("1234567" .getBytes ()));
30
-
31
- /* private TransactionCapsule transactionCapsule1 = new TransactionCapsule(
32
- ByteArray.fromHexString(
33
- Wallet.getAddressPreFixString() + "A389132D6639FBDA4FBC8B659264E6B7C90DB086"), 1L);
34
- private TransactionCapsule transactionCapsule2 = new TransactionCapsule(
35
- ByteArray.fromHexString(
36
- Wallet.getAddressPreFixString() + "ED738B3A0FE390EAA71B768B6D02CDBD18FB207B"), 2L);
37
- private TransactionCapsule transactionCapsule3 = new TransactionCapsule(
38
- ByteArray.fromHexString(
39
- Wallet.getAddressPreFixString() + "F25675B364B0E45E2668C1CDD59370136AD8EC2F"), 2L);
40
- */
41
-
42
- public MerkleTreeTest () throws Exception {
43
- }
44
-
45
- @ Ignore
46
- @ Test
47
- public void testMerkleTreeTest () {
48
- Sha256Hash hash1 = getBeforeZeroHash ();
49
- MerkleTree tree = MerkleTree .getInstance ().createTree (getZeroIds ());
50
-
51
- logger .info ("Transaction[X] Compare :" );
52
- logger .info ("left: {}" , hash1 );
53
- logger .info ("right: {}" , tree .getRoot ().getHash ());
54
-
55
- assertEquals (hash1 , tree .getRoot ().getHash ());
56
-
57
- Sha256Hash hash2 = getBeforeTxHash ();
58
- tree .createTree (getTxIds2 (blockCapsule1 ));
59
-
60
- logger .info ("Transaction[O] Compare :" );
61
- logger .info ("left: {}" , hash2 );
62
- logger .info ("right: {}" , tree .getRoot ().getHash ());
63
-
64
- assertEquals (hash2 , tree .getRoot ().getHash ());
65
- }
66
-
67
- private Sha256Hash getBeforeHash (Vector <Sha256Hash > ids ) {
68
- int hashNum = ids .size ();
69
-
70
- while (hashNum > 1 ) {
71
- int max = hashNum - (hashNum & 1 );
72
- int k = 0 ;
73
- for (int i = 0 ; i < max ; i += 2 ) {
74
- ids .set (k ++, Sha256Hash .of ((ids .get (i ).getByteString ()
75
- .concat (ids .get (i + 1 ).getByteString ()))
76
- .toByteArray ()));
77
- }
78
-
79
- if (hashNum % 2 == 1 ) {
80
- ids .set (k ++, ids .get (max ));
81
- }
82
- hashNum = k ;
15
+ private static List <Sha256Hash > getHash (int hashNum ) {
16
+ List <Sha256Hash > hashList = new ArrayList <Sha256Hash >();
17
+ for (int i = 0 ; i < hashNum ; i ++) {
18
+ byte [] bytes = new byte [4 ];
19
+ bytes [3 ] = (byte ) (i & 0xFF );
20
+ bytes [2 ] = (byte ) ((i >> 8 ) & 0xFF );
21
+ bytes [1 ] = (byte ) ((i >> 16 ) & 0xFF );
22
+ bytes [0 ] = (byte ) ((i >> 24 ) & 0xFF );
23
+ hashList .add (Sha256Hash .of (bytes ));
83
24
}
84
-
85
- return ids .firstElement ();
25
+ return hashList ;
86
26
}
87
27
88
- private Sha256Hash getBeforeZeroHash ( ) {
89
- return getBeforeHash ( getZeroIds ());
28
+ private static Sha256Hash computeHash ( Sha256Hash leftHash , Sha256Hash rightHash ) {
29
+ return Sha256Hash . of ( leftHash . getByteString (). concat ( rightHash . getByteString ()). toByteArray ());
90
30
}
91
31
92
- private Sha256Hash getBeforeTxHash () {
93
- return getBeforeHash (getTxIds1 (blockCapsule0 ));
32
+ @ Test
33
+ /**
34
+ * Make a merkletree with no hash.
35
+ * Will throw a exception.
36
+ */
37
+ public void test0HashNum () {
38
+ List <Sha256Hash > hashList = getHash (0 ); //Empty list.
39
+ try {
40
+ MerkleTree .getInstance ().createTree (hashList );
41
+ Assert .assertFalse (true );
42
+ } catch (Exception e ) {
43
+ Assert .assertTrue (e instanceof IndexOutOfBoundsException );
44
+ }
94
45
}
95
46
96
- private Vector <Sha256Hash > getZeroIds () {
97
- Vector <Sha256Hash > ids = new Vector <>();
98
- ids .add (Sha256Hash .ZERO_HASH );
99
- return ids ;
47
+ @ Test
48
+ /**
49
+ * Make a merkletree with 1 hash.
50
+ * root
51
+ * / \
52
+ * H1 null
53
+ * / \
54
+ * null null
55
+ */
56
+ public void test1HashNum () {
57
+ List <Sha256Hash > hashList = getHash (1 );
58
+ MerkleTree tree = MerkleTree .getInstance ().createTree (hashList );
59
+ Leaf root = tree .getRoot ();
60
+ Assert .assertEquals (root .getHash (), hashList .get (0 ));
61
+
62
+ Leaf left = root .getLeft ();
63
+ Assert .assertEquals (left .getHash (), hashList .get (0 ));
64
+ Assert .assertTrue (left .getLeft () == null );
65
+ Assert .assertTrue (left .getRight () == null );
66
+
67
+ Assert .assertTrue (root .getRight () == null );
100
68
}
101
69
102
- private Vector <Sha256Hash > getTxIds1 (BlockCapsule blockCapsule ) {
103
- return getSha256Hashes (blockCapsule );
70
+ @ Test
71
+ /**
72
+ * Make a merkletree with 2 hash.
73
+ * root
74
+ * / \
75
+ * H1 H2
76
+ * / \ / \
77
+ *null null null null
78
+ */
79
+ public void test2HashNum () {
80
+ List <Sha256Hash > hashList = getHash (2 );
81
+ MerkleTree tree = MerkleTree .getInstance ().createTree (hashList );
82
+ Leaf root = tree .getRoot ();
83
+ Assert .assertEquals (root .getHash (), computeHash (hashList .get (0 ), hashList .get (1 )));
84
+
85
+ Leaf left = root .getLeft ();
86
+ Assert .assertEquals (left .getHash (), hashList .get (0 ));
87
+ Assert .assertTrue (left .getLeft () == null );
88
+ Assert .assertTrue (left .getRight () == null );
89
+
90
+ Leaf right = root .getRight ();
91
+ Assert .assertEquals (right .getHash (), hashList .get (1 ));
92
+ Assert .assertTrue (right .getLeft () == null );
93
+ Assert .assertTrue (right .getRight () == null );
104
94
}
105
95
106
- private Vector <Sha256Hash > getTxIds2 (BlockCapsule blockCapsule ) {
107
- return getSha256Hashes (blockCapsule );
96
+ @ Test
97
+ /**
98
+ * Make a merkletree with any num hash.
99
+ *
100
+ *rank0 root
101
+ *rank1 0 1
102
+ *rank2 0 1 2
103
+ *rank3 0 1 2 3 4
104
+ *rank4 0 1 2 3 4 5 6 7 8 9
105
+ *rank5 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
106
+ *
107
+ * leftNum = 2 * headNum
108
+ * rightNum = leftNum + 1
109
+ * curBank < maxRank, there must have left child
110
+ * if have left child but no right child, headHash = leftHash
111
+ * if both have left child and right child, headHash = SHA256(leftHash||rightHash)
112
+ * curBank = maxRank, no child, it is real leaf. Its hash in hashList.
113
+ */
114
+ public void testAnyHashNum () {
115
+ int maxNum = 128 ;
116
+ for (int hashNum = 1 ; hashNum <= maxNum ; hashNum ++){
117
+ int maxRank = getRank (hashNum );
118
+ List <Sha256Hash > hashList = getHash (hashNum );
119
+ MerkleTree tree = MerkleTree .getInstance ().createTree (hashList );
120
+ Leaf root = tree .getRoot ();
121
+ pareTree (root , hashList , maxRank , 0 , 0 );
122
+ }
108
123
}
109
124
110
- private Vector <Sha256Hash > getSha256Hashes (BlockCapsule blockCapsule ) {
111
- /* blockCapsule.addTransaction(transactionCapsule1);
112
- blockCapsule.addTransaction(transactionCapsule2);
113
- blockCapsule.addTransaction(transactionCapsule3);
114
-
115
- List<Protocol.Transaction> transactionList = blockCapsule.getInstance().getTransactionsList();
116
- return getSha256Hashes(transactionList); */
117
- return null ;
125
+ //number: the number of hash
126
+ private static void pareTree (Leaf head , List <Sha256Hash > hashList , int maxRank , int curBank ,
127
+ int number ) {
128
+ Leaf left = head .getLeft ();
129
+ Leaf right = head .getRight ();
130
+ if (curBank < maxRank ) {
131
+ curBank ++;
132
+ number = number << 1 ;
133
+ pareTree (left , hashList , maxRank , curBank , number );
134
+ number ++;
135
+ if ( (number <<(maxRank -curBank )) >= hashList .size ()) { //The smallest leaf child number = number<<(maxRank-curBank)
136
+ Assert .assertTrue (right == null );
137
+ Assert .assertEquals (head .getHash (), left .getHash ()); //No right, leaf = left
138
+ } else {
139
+ pareTree (right , hashList , maxRank , curBank , number );
140
+ Assert .assertEquals (head .getHash (), computeHash (left .getHash (), right .getHash ())); //hash = sha256(left || right)
141
+ }
142
+ } else {
143
+ // last rank, no child, it is real leaf. Its hash in hashList.
144
+ Assert .assertTrue (left == null );
145
+ Assert .assertTrue (right == null );
146
+ Assert .assertEquals (head .getHash (), hashList .get (number ));
147
+ System .out .println ("curBank :" + curBank + " number :" + number );
148
+ System .out .println (ByteArray .toHexString (head .getHash ().getBytes ()));
149
+ }
118
150
}
119
151
120
- private Vector <Sha256Hash > getSha256Hashes (List <Protocol .Transaction > transactionList ) {
121
- return transactionList .stream ()
122
- .map (TransactionCapsule ::new )
123
- .map (TransactionCapsule ::getHash )
124
- .collect (Collectors .toCollection (Vector ::new ));
152
+ private static int getRank (int num ) {
153
+ if (num <= 0 ) {
154
+ return 0 ;
155
+ }
156
+ if (num == 1 ) {
157
+ return 1 ;
158
+ }
159
+ int rank = 0 ;
160
+ int temp = num ;
161
+ while (num > 0 ) {
162
+ num = num >> 1 ;
163
+ rank ++;
164
+ }
165
+ if (temp == Math .pow (2 , rank - 1 )) {
166
+ rank -= 1 ;
167
+ }
168
+ return rank ;
125
169
}
126
170
}
0 commit comments