OSDN Git Service

68dcb7d2638ffeaf2de6dd5210675b8ba8be056e
[bytom/vapor.git] / protocol / bc / types / merkle_test.go
1 package types
2
3 import (
4         "encoding/hex"
5
6         "math/rand"
7         "testing"
8         "time"
9
10         "github.com/vapor/protocol/bc"
11         "github.com/vapor/protocol/vm"
12         "github.com/vapor/testutil"
13 )
14
15 func TestMerkleRoot(t *testing.T) {
16         cases := []struct {
17                 witnesses [][][]byte
18                 want      bc.Hash
19         }{{
20                 witnesses: [][][]byte{
21                         {
22                                 {1},
23                                 []byte("00000"),
24                         },
25                 },
26                 want: testutil.MustDecodeHash("fe34dbd5da0ce3656f423fd7aad7fc7e879353174d33a6446c2ed0e3f3512101"),
27         }, {
28                 witnesses: [][][]byte{
29                         {
30                                 {1},
31                                 []byte("000000"),
32                         },
33                         {
34                                 {1},
35                                 []byte("111111"),
36                         },
37                 },
38                 want: testutil.MustDecodeHash("0e4b4c1af18b8f59997804d69f8f66879ad5e30027346ee003ff7c7a512e5554"),
39         }, {
40                 witnesses: [][][]byte{
41                         {
42                                 {1},
43                                 []byte("000000"),
44                         },
45                         {
46                                 {2},
47                                 []byte("111111"),
48                                 []byte("222222"),
49                         },
50                 },
51                 want: testutil.MustDecodeHash("0e4b4c1af18b8f59997804d69f8f66879ad5e30027346ee003ff7c7a512e5554"),
52         }}
53
54         for _, c := range cases {
55                 var txs []*bc.Tx
56                 for _, wit := range c.witnesses {
57                         txs = append(txs, NewTx(TxData{
58                                 Inputs: []*TxInput{
59                                         &TxInput{
60                                                 AssetVersion: 1,
61                                                 TypedInput: &SpendInput{
62                                                         Arguments: wit,
63                                                         SpendCommitment: SpendCommitment{
64                                                                 AssetAmount: bc.AssetAmount{
65                                                                         AssetId: &bc.AssetID{V0: 0},
66                                                                 },
67                                                         },
68                                                 },
69                                         },
70                                 },
71                         }).Tx)
72                 }
73                 got, err := TxMerkleRoot(txs)
74                 if err != nil {
75                         t.Fatalf("unexpected error %s", err)
76                 }
77                 if got != c.want {
78                         t.Log("witnesses", c.witnesses)
79                         t.Errorf("got merkle root = %x want %x", got.Bytes(), c.want.Bytes())
80                 }
81         }
82 }
83
84 func TestMerkleRootRealTx(t *testing.T) {
85         rawTxs := []string{
86                 "070100010160015e5ac79a73db78e5c9215b37cb752f0147d1157c542bb4884908ceb97abc33fe0affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0f280d42b0001160014085a02ecdf934a56343aa59a3dec9d9feb86ee43630240035e1ef422b4901997ad3c20c50d82e726d03cb6e8ccb5dddc20e0c09e0a6f2e0055331e2b54d9ec52cffb1c47d8fdf2f8887d55c336753637cbf8f832c7af0b20a29601468f08c57ca9c383d28736a9d5c7737cd483126d8db3d85490fe497b3502013f003dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0aad1b30601160014991b78d1bf731390e2dd838c05ff37ec5146886b00013f003dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8086d8f024011600145ade29df622cc68d0473aa1a20fb89690451c66e00",
87                 "070100020160015e4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adeaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c480c1240201160014cb9f2391bafe2bc1159b2c4c8a0f17ba1b4dd94e630240d96b8f31519c5e34ef983bb7dfb92e807df7fc1ae5a4c08846d00d4f84ebd2f8634b9e0b0374eb2508d0f989520f622aef051862c26daba0e466944e3d55d00b201381d35e235813ad1e62f9a602c82abee90565639cc4573568206b55bcd2aed901300008ede605460cacbf107b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad1480d0dbc3f402b001467b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d0125ae2054a71277cc162eb3eb21b5bd9fe54402829a53b294deaed91692a2cd8a081f9c5151ad01403a54a3ca0210d005cc9bce490478b518c405ba72e0bc1d134b739f29a73e008345229f0e061c420aa3c56a48bc1c9bf592914252ab9100e69252deeac532430f03013f003dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80e0e8f011011600144ab5249140ca4630729030941f59f75e507bd4d5000140003e7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad1480d0dbc3f402011600145ade29df622cc68d0473aa1a20fb89690451c66e00013f003dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80a2c0a012011600145ade29df622cc68d0473aa1a20fb89690451c66e00",
88                 "07010001016c016acf24f1471d67c25a01ac84482ecdd8550229180171cae22321f87fe43d4f6a13ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80b4c4c32101012200200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac66ef02044059c7a12d006fd34bf8b9b2cb2f99756e5c3c3fdca4c928b830c014819e933b01c92a99bfeb6add73a5087870a3de3465cfed2c99f736b5f77d5fbdc69d91ff0040b95d110d118b873a8232104a6613f0e8c6a791efa3a695c02108cebd5239c8a8471551a48f18ab8ea05d10900b485af5e95b74cd3c01044c1742e71854099c0b40a1b63dae273e3b5b757b7c61286088a934e7282e837d08d62e60d7f75eb739529cd8c6cfef2254d47a546bf8b789657ce0944fec2f7e130c8498e28cae2a9108a901ae20d441b6f375659325a04eede4fc3b74579bb08ccd05b41b99776501e22d6dca7320af6d98ca2c3cd10bf0affbfa6e86609b750523cfadb662ec963c164f05798a49209820b9f1553b03aaebe7e3f9e9222ed7db73b5079b18564042fd3b2cef74156a20271b52de5f554aa4a6f1358f1c2193617bfb3fed4546d13c4af773096a429f9420eeb4a78d8b5cb8283c221ca2d3fd96b8946b3cddee02b7ceffb8f605932588595355ad02014b0049ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80a0d9e61d012200206e8060ef3daca62841802dd9660b24b7dca81c1662b2d68ba8884ecbcd3e1e2200013f003dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80d293ad0301160014ed7d3c466dbc6cc1f3a9af21267ac162f11b30a200",
89                 "070100020161015f4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adea0dafd0f0e42f06f3bf9a8cf5787519d3860650f27a2b3393d34e1fe06e89b469ddc3f8c2f40200011600141da7f908979e521bf2ba12d280b2c84fc1d024416302409524d0d817176eeb718ce45671d95831cdb138d27289aa8a920104e38a8cab8a7dc8cc3fb60d65aa337b719aed0f696fb12610bfe68add89169a47ac1241e0002033444e1b57524161af3899e50fdfe270a90a1ea97fe38e86019a1e252667fb2d0161015fed3181c99ca80db720231aee6948e1183bfe29c64208c1769afa7f938d3b2cf0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff809cd2b0f4020101160014cfbccfac5018ad4b4bfbcb1fab834e3c8503746063024065beb1da2f0840188af0e3c0127b158f7a2a36f1612499694a731df1e3a9d1abe6694c42986b8700aa9856f59cb3692ee88d68b20d1278f05592fb253c58bd0520e5966eee4092eeefdd805b06f2ad368bb9392edec20998993ebe2a929052c1ce030140003e0dafd0f0e42f06f3bf9a8cf5787519d3860650f27a2b3393d34e1fe06e89b469ddfbc8a2cf0201160014583c0323603dd397ba5414255adc80b076cf232b00013f003d0dafd0f0e42f06f3bf9a8cf5787519d3860650f27a2b3393d34e1fe06e89b46980c8afa02501160014fdb3e6abf7f430fdabb53484ca2469103b2af1b5000140003effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80dafa80f4020116001408e75789f47d2a39622e5a940fa918260bf44c5400",
90                 "07010001016d016b1f134a47da4f6df00822935e02a07514718ea99ce5ac4e07bd6c204e098eb525ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808a858fa70200012200206205ec178dc1ac6ea05ea01bb0fcda6aa978173026fa75204a101bdad7bd6b4889010240d8d5bbf4969fba52df8fba06f75c5de0f51b2bd5f902bf234591f90e78bae20bfb5b7904cb83a1d6577c431f644d37722b432df9d64718b8300e3ab74a871a0046ae2068003e53d467b6d81beaf1e7bd9b60a5ffedc79b36ce14ecd1f30a2dcbcd0551200449030407a3a1fa0731f7f784a72c325b5ce4d534fc3cf8fb7140536ba928605152ad02014c004affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80f699b2a302012200209a0b4b27fde7d29d3b465d20eb2e19f4bda3a873d19d11f4cba53958bde92ed000013f003dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80b3ffc40301160014ed7d3c466dbc6cc1f3a9af21267ac162f11b30a200",
91         }
92         wantMerkleRoot := "9100f5258bdc059d911b745eada2afb3a64008e91d64e245d7b3729b8909f0c1"
93
94         var txs []*bc.Tx
95         for i, rawTx := range rawTxs {
96                 tx := Tx{}
97                 if err := tx.UnmarshalText([]byte(rawTx)); err != nil {
98                         t.Fatalf("case#%d, %v", i, err)
99                 }
100
101                 txs = append(txs, tx.Tx)
102         }
103
104         gotMerkleRoot, err := TxMerkleRoot(txs)
105         if err != nil {
106                 t.Fatal(err)
107         }
108
109         if wantMerkleRoot != gotMerkleRoot.String() {
110                 t.Errorf("got merkle root:%s, want merkle root:%s", gotMerkleRoot.String(), wantMerkleRoot)
111         }
112 }
113
114 func TestDuplicateLeaves(t *testing.T) {
115         trueProg := []byte{byte(vm.OP_TRUE)}
116         assetID := bc.ComputeAssetID(trueProg, 1, &bc.EmptyStringHash)
117         txs := make([]*bc.Tx, 6)
118         for i := uint64(0); i < 6; i++ {
119                 now := []byte(time.Now().String())
120                 txs[i] = NewTx(TxData{
121                         Version: 1,
122                         Inputs:  []*TxInput{NewIssuanceInput(now, i, trueProg, nil, nil)},
123                         Outputs: []*TxOutput{NewIntraChainOutput(assetID, i, trueProg)},
124                 }).Tx
125         }
126
127         // first, get the root of an unbalanced tree
128         txns := []*bc.Tx{txs[5], txs[4], txs[3], txs[2], txs[1], txs[0]}
129         root1, err := TxMerkleRoot(txns)
130         if err != nil {
131                 t.Fatalf("unexpected error %s", err)
132         }
133
134         // now, get the root of a balanced tree that repeats leaves 0 and 1
135         txns = []*bc.Tx{txs[5], txs[4], txs[3], txs[2], txs[1], txs[0], txs[1], txs[0]}
136         root2, err := TxMerkleRoot(txns)
137         if err != nil {
138                 t.Fatalf("unexpected error %s", err)
139         }
140
141         if root1 == root2 {
142                 t.Error("forged merkle tree by duplicating some leaves")
143         }
144 }
145
146 func TestAllDuplicateLeaves(t *testing.T) {
147         trueProg := []byte{byte(vm.OP_TRUE)}
148         assetID := bc.ComputeAssetID(trueProg, 1, &bc.EmptyStringHash)
149         now := []byte(time.Now().String())
150         issuanceInp := NewIssuanceInput(now, 1, trueProg, nil, nil)
151
152         tx := NewTx(TxData{
153                 Version: 1,
154                 Inputs:  []*TxInput{issuanceInp},
155                 Outputs: []*TxOutput{NewIntraChainOutput(assetID, 1, trueProg)},
156         }).Tx
157         tx1, tx2, tx3, tx4, tx5, tx6 := tx, tx, tx, tx, tx, tx
158
159         // first, get the root of an unbalanced tree
160         txs := []*bc.Tx{tx6, tx5, tx4, tx3, tx2, tx1}
161         root1, err := TxMerkleRoot(txs)
162         if err != nil {
163                 t.Fatalf("unexpected error %s", err)
164         }
165
166         // now, get the root of a balanced tree that repeats leaves 5 and 6
167         txs = []*bc.Tx{tx6, tx5, tx6, tx5, tx4, tx3, tx2, tx1}
168         root2, err := TxMerkleRoot(txs)
169         if err != nil {
170                 t.Fatalf("unexpected error %s", err)
171         }
172
173         if root1 == root2 {
174                 t.Error("forged merkle tree with all duplicate leaves")
175         }
176 }
177
178 func TestTxMerkleProof(t *testing.T) {
179         cases := []struct {
180                 txCount          int
181                 relatedTxIndexes []int
182                 expectHashLen    int
183                 expectFlags      []uint8
184         }{
185                 {
186                         txCount:          10,
187                         relatedTxIndexes: []int{0, 3, 7, 8},
188                         expectHashLen:    9,
189                         expectFlags:      []uint8{1, 1, 1, 1, 2, 0, 1, 0, 2, 1, 0, 1, 0, 2, 1, 2, 0},
190                 },
191                 {
192                         txCount:          10,
193                         relatedTxIndexes: []int{},
194                         expectHashLen:    1,
195                         expectFlags:      []uint8{0},
196                 },
197                 {
198                         txCount:          1,
199                         relatedTxIndexes: []int{0},
200                         expectHashLen:    1,
201                         expectFlags:      []uint8{2},
202                 },
203                 {
204                         txCount:          19,
205                         relatedTxIndexes: []int{1, 3, 5, 7, 11, 15},
206                         expectHashLen:    15,
207                         expectFlags:      []uint8{1, 1, 1, 1, 1, 0, 2, 1, 0, 2, 1, 1, 0, 2, 1, 0, 2, 1, 1, 0, 1, 0, 2, 1, 0, 1, 0, 2, 0},
208                 },
209         }
210         for _, c := range cases {
211                 txs, bcTxs := mockTransactions(c.txCount)
212
213                 var nodes []merkleNode
214                 for _, tx := range txs {
215                         nodes = append(nodes, tx.ID)
216                 }
217                 tree := buildMerkleTree(nodes)
218                 root, err := TxMerkleRoot(bcTxs)
219                 if err != nil {
220                         t.Fatalf("unexpected error %s", err)
221                 }
222                 if tree.hash != root {
223                         t.Error("build tree fail")
224                 }
225
226                 var relatedTx []*Tx
227                 for _, index := range c.relatedTxIndexes {
228                         relatedTx = append(relatedTx, txs[index])
229                 }
230                 proofHashes, flags := GetTxMerkleTreeProof(txs, relatedTx)
231                 if !testutil.DeepEqual(flags, c.expectFlags) {
232                         t.Error("The flags is not equals expect flags", flags, c.expectFlags)
233                 }
234                 if len(proofHashes) != c.expectHashLen {
235                         t.Error("The length proof hashes is not equals expect length")
236                 }
237                 var ids []*bc.Hash
238                 for _, tx := range relatedTx {
239                         ids = append(ids, &tx.ID)
240                 }
241                 if !ValidateTxMerkleTreeProof(proofHashes, flags, ids, root) {
242                         t.Error("Merkle tree validate fail")
243                 }
244         }
245 }
246
247 func TestStatusMerkleProof(t *testing.T) {
248         cases := []struct {
249                 statusCount    int
250                 relatedIndexes []int
251                 flags          []uint8
252                 expectHashLen  int
253         }{
254                 {
255                         statusCount:    10,
256                         relatedIndexes: []int{0, 3, 7, 8},
257                         flags:          []uint8{1, 1, 1, 1, 2, 0, 1, 0, 2, 1, 0, 1, 0, 2, 1, 2, 0},
258                         expectHashLen:  9,
259                 },
260                 {
261                         statusCount:    10,
262                         relatedIndexes: []int{},
263                         flags:          []uint8{0},
264                         expectHashLen:  1,
265                 },
266                 {
267                         statusCount:    1,
268                         relatedIndexes: []int{0},
269                         flags:          []uint8{2},
270                         expectHashLen:  1,
271                 },
272                 {
273                         statusCount:    19,
274                         relatedIndexes: []int{1, 3, 5, 7, 11, 15},
275                         flags:          []uint8{1, 1, 1, 1, 1, 0, 2, 1, 0, 2, 1, 1, 0, 2, 1, 0, 2, 1, 1, 0, 1, 0, 2, 1, 0, 1, 0, 2, 0},
276                         expectHashLen:  15,
277                 },
278         }
279         for _, c := range cases {
280                 statuses := mockStatuses(c.statusCount)
281                 var relatedStatuses []*bc.TxVerifyResult
282                 for _, index := range c.relatedIndexes {
283                         relatedStatuses = append(relatedStatuses, statuses[index])
284                 }
285                 hashes := GetStatusMerkleTreeProof(statuses, c.flags)
286                 if len(hashes) != c.expectHashLen {
287                         t.Error("The length proof hashes is not equals expect length")
288                 }
289                 root, _ := TxStatusMerkleRoot(statuses)
290                 if !ValidateStatusMerkleTreeProof(hashes, c.flags, relatedStatuses, root) {
291                         t.Error("Merkle tree validate fail")
292                 }
293         }
294 }
295
296 func TestUglyValidateTxMerkleProof(t *testing.T) {
297         cases := []struct {
298                 hashes        []string
299                 flags         []uint8
300                 relatedHashes []string
301                 root          string
302                 expectResult  bool
303         }{
304                 {
305                         hashes:        []string{},
306                         flags:         []uint8{},
307                         relatedHashes: []string{},
308                         root:          "",
309                         expectResult:  false,
310                 },
311                 {
312                         hashes:        []string{},
313                         flags:         []uint8{1, 1, 1, 1, 2, 0, 1, 0, 2, 1, 0, 1, 0, 2, 1, 2, 0},
314                         relatedHashes: []string{},
315                         root:          "",
316                         expectResult:  false,
317                 },
318                 {
319                         hashes: []string{
320                                 "0093370a8e19f8f131fd7e75c576615950d5672ee5e18c63f105a95bcab4332c",
321                                 "c9b7779847fb7ab74cf4b1e7f4557133918faa2bc130042753417dfb62b12dfa",
322                         },
323                         flags:         []uint8{},
324                         relatedHashes: []string{},
325                         root:          "",
326                         expectResult:  false,
327                 },
328                 {
329                         hashes: []string{},
330                         flags:  []uint8{},
331                         relatedHashes: []string{
332                                 "0093370a8e19f8f131fd7e75c576615950d5672ee5e18c63f105a95bcab4332c",
333                                 "c9b7779847fb7ab74cf4b1e7f4557133918faa2bc130042753417dfb62b12dfa",
334                         },
335                         root:         "",
336                         expectResult: false,
337                 },
338                 {
339                         hashes: []string{},
340                         flags:  []uint8{1, 1, 0, 2, 1, 2, 1, 0, 1},
341                         relatedHashes: []string{
342                                 "0093370a8e19f8f131fd7e75c576615950d5672ee5e18c63f105a95bcab4332c",
343                                 "c9b7779847fb7ab74cf4b1e7f4557133918faa2bc130042753417dfb62b12dfa",
344                         },
345                         root: "281138e0a9ea19505844bd61a2f5843787035782c093da74d12b5fba73eeeb07",
346                 },
347                 {
348                         hashes: []string{
349                                 "68f03ea2b02a21ad944d1a43ad6152a7fa6a7ed4101d59be62594dd30ef2a558",
350                         },
351                         flags: []uint8{},
352                         relatedHashes: []string{
353                                 "0093370a8e19f8f131fd7e75c576615950d5672ee5e18c63f105a95bcab4332c",
354                                 "c9b7779847fb7ab74cf4b1e7f4557133918faa2bc130042753417dfb62b12dfa",
355                         },
356                         root:         "281138e0a9ea19505844bd61a2f5843787035782c093da74d12b5fba73eeeb07",
357                         expectResult: false,
358                 },
359                 {
360                         hashes: []string{
361                                 "8ec3ee7589f95eee9b534f71fcd37142bcc839a0dbfe78124df9663827b90c35",
362                                 "011bd3380852b2946df507e0c6234222c559eec8f545e4bc58a89e960892259b",
363                                 "c205988d9c864083421f1bdb95e6cf8b52070facfcc87e46a6e8197f5389fca2",
364                         },
365                         flags: []uint8{1, 1, 0, 2, 0},
366                         relatedHashes: []string{
367                                 "504af455e328e7dd39bbc059529851946d54ee8b459b11b3aac4a0feeb474487",
368                         },
369                         root:         "aff81a46fe79204ef9007243f374d54104a59762b9f74d80d56b5291753db6fb",
370                         expectResult: true,
371                 },
372                 // flags and hashes is correct, but relatedHashes has hash that does not exist
373                 {
374                         hashes: []string{
375                                 "8ec3ee7589f95eee9b534f71fcd37142bcc839a0dbfe78124df9663827b90c35",
376                                 "011bd3380852b2946df507e0c6234222c559eec8f545e4bc58a89e960892259b",
377                                 "c205988d9c864083421f1bdb95e6cf8b52070facfcc87e46a6e8197f5389fca2",
378                         },
379                         flags: []uint8{1, 1, 0, 2, 0},
380                         relatedHashes: []string{
381                                 "504af455e328e7dd39bbc059529851946d54ee8b459b11b3aac4a0feeb474487",
382                                 "281138e0a9ea19505844bd61a2f5843787035782c093da74d12b5fba73eeeb07",
383                         },
384                         root:         "aff81a46fe79204ef9007243f374d54104a59762b9f74d80d56b5291753db6fb",
385                         expectResult: false,
386                 },
387                 // flags and hashes is correct, but relatedHashes is not enough
388                 {
389                         hashes: []string{
390                                 "8ec3ee7589f95eee9b534f71fcd37142bcc839a0dbfe78124df9663827b90c35",
391                                 "011bd3380852b2946df507e0c6234222c559eec8f545e4bc58a89e960892259b",
392                                 "c205988d9c864083421f1bdb95e6cf8b52070facfcc87e46a6e8197f5389fca2",
393                         },
394                         flags:         []uint8{1, 1, 0, 2, 0},
395                         relatedHashes: []string{},
396                         root:          "aff81a46fe79204ef9007243f374d54104a59762b9f74d80d56b5291753db6fb",
397                         expectResult:  false,
398                 },
399                 // flags is correct, but hashes has additional hash at the end
400                 {
401                         hashes: []string{
402                                 "8ec3ee7589f95eee9b534f71fcd37142bcc839a0dbfe78124df9663827b90c35",
403                                 "011bd3380852b2946df507e0c6234222c559eec8f545e4bc58a89e960892259b",
404                                 "c205988d9c864083421f1bdb95e6cf8b52070facfcc87e46a6e8197f5389fca2",
405                                 "5a06c90136e81c0f9cad29725e69edc6d21bd6fb0641265f9c4b6bb6840b37dd",
406                         },
407                         flags: []uint8{1, 1, 0, 2, 0},
408                         relatedHashes: []string{
409                                 "504af455e328e7dd39bbc059529851946d54ee8b459b11b3aac4a0feeb474487",
410                         },
411                         root:         "aff81a46fe79204ef9007243f374d54104a59762b9f74d80d56b5291753db6fb",
412                         expectResult: true,
413                 },
414         }
415
416         for _, c := range cases {
417                 var hashes, relatedHashes []*bc.Hash
418                 var hashBytes, rootBytes [32]byte
419                 var err error
420                 for _, hashStr := range c.hashes {
421                         if hashBytes, err = convertHashStr2Bytes(hashStr); err != nil {
422                                 t.Fatal(err)
423                         }
424
425                         hash := bc.NewHash(hashBytes)
426                         hashes = append(hashes, &hash)
427                 }
428                 for _, hashStr := range c.relatedHashes {
429                         if hashBytes, err = convertHashStr2Bytes(hashStr); err != nil {
430                                 t.Fatal(err)
431                         }
432
433                         hash := bc.NewHash(hashBytes)
434                         relatedHashes = append(relatedHashes, &hash)
435                 }
436                 if rootBytes, err = convertHashStr2Bytes(c.root); err != nil {
437                         t.Fatal(err)
438                 }
439
440                 root := bc.NewHash(rootBytes)
441                 if ValidateTxMerkleTreeProof(hashes, c.flags, relatedHashes, root) != c.expectResult {
442                         t.Error("Validate merkle tree proof fail")
443                 }
444         }
445 }
446
447 func convertHashStr2Bytes(hashStr string) ([32]byte, error) {
448         var result [32]byte
449         hashBytes, err := hex.DecodeString(hashStr)
450         if err != nil {
451                 return result, err
452         }
453         copy(result[:], hashBytes)
454         return result, nil
455 }
456
457 func mockTransactions(txCount int) ([]*Tx, []*bc.Tx) {
458         var txs []*Tx
459         var bcTxs []*bc.Tx
460         trueProg := []byte{byte(vm.OP_TRUE)}
461         assetID := bc.ComputeAssetID(trueProg, 1, &bc.EmptyStringHash)
462         for i := 0; i < txCount; i++ {
463                 now := []byte(time.Now().String())
464                 issuanceInp := NewIssuanceInput(now, 1, trueProg, nil, nil)
465                 tx := NewTx(TxData{
466                         Version: 1,
467                         Inputs:  []*TxInput{issuanceInp},
468                         Outputs: []*TxOutput{NewIntraChainOutput(assetID, 1, trueProg)},
469                 })
470                 txs = append(txs, tx)
471                 bcTxs = append(bcTxs, tx.Tx)
472         }
473         return txs, bcTxs
474 }
475
476 func mockStatuses(statusCount int) []*bc.TxVerifyResult {
477         var statuses []*bc.TxVerifyResult
478         for i := 0; i < statusCount; i++ {
479                 status := &bc.TxVerifyResult{}
480                 fail := rand.Intn(2)
481                 if fail == 0 {
482                         status.StatusFail = true
483                 } else {
484                         status.StatusFail = false
485                 }
486                 statuses = append(statuses, status)
487         }
488         return statuses
489 }