Skip to content

Commit 2580035

Browse files
authored
Merge pull request #641 from tronprotocol/develop-evan-mekletreetest
Develop evan mekletreetest
2 parents 5f60fb4 + 4a0e8fc commit 2580035

File tree

1 file changed

+142
-98
lines changed

1 file changed

+142
-98
lines changed
Lines changed: 142 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,126 +1,170 @@
11
package org.tron.core.capsule.utils;
22

3-
import static org.junit.Assert.assertEquals;
4-
5-
import com.google.protobuf.ByteString;
3+
import java.util.ArrayList;
64
import java.util.List;
7-
import java.util.Vector;
8-
import java.util.stream.Collectors;
95
import lombok.extern.slf4j.Slf4j;
10-
import org.junit.Ignore;
6+
import org.junit.Assert;
117
import org.junit.Test;
128
import org.tron.common.utils.ByteArray;
139
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;
1711

1812
@Slf4j
1913
public class MerkleTreeTest {
2014

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));
8324
}
84-
85-
return ids.firstElement();
25+
return hashList;
8626
}
8727

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());
9030
}
9131

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+
}
9445
}
9546

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);
10068
}
10169

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);
10494
}
10595

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+
}
108123
}
109124

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+
}
118150
}
119151

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;
125169
}
126170
}

0 commit comments

Comments
 (0)