github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/protocol/bc/types/merkle_test.go (about)

     1  package types
     2  
     3  import (
     4  	"encoding/hex"
     5  
     6  	"math/rand"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/bytom/bytom/protocol/bc"
    11  	"github.com/bytom/bytom/protocol/vm"
    12  	"github.com/bytom/bytom/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  		"070100010160015e5ac79a73db78e5c9215b37cb752f0147d1157c542bb4884908ceb97abc33fe0affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0f280d42b0001160014085a02ecdf934a56343aa59a3dec9d9feb86ee43630240035e1ef422b4901997ad3c20c50d82e726d03cb6e8ccb5dddc20e0c09e0a6f2e0055331e2b54d9ec52cffb1c47d8fdf2f8887d55c336753637cbf8f832c7af0b20a29601468f08c57ca9c383d28736a9d5c7737cd483126d8db3d85490fe497b3502013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0aad1b30601160014991b78d1bf731390e2dd838c05ff37ec5146886b00013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8086d8f024011600145ade29df622cc68d0473aa1a20fb89690451c66e00",
    87  		"070100020160015e4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adeaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c480c1240201160014cb9f2391bafe2bc1159b2c4c8a0f17ba1b4dd94e630240d96b8f31519c5e34ef983bb7dfb92e807df7fc1ae5a4c08846d00d4f84ebd2f8634b9e0b0374eb2508d0f989520f622aef051862c26daba0e466944e3d55d00b201381d35e235813ad1e62f9a602c82abee90565639cc4573568206b55bcd2aed901300008ede605460cacbf107b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad1480d0dbc3f402b001467b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d0125ae2054a71277cc162eb3eb21b5bd9fe54402829a53b294deaed91692a2cd8a081f9c5151ad01403a54a3ca0210d005cc9bce490478b518c405ba72e0bc1d134b739f29a73e008345229f0e061c420aa3c56a48bc1c9bf592914252ab9100e69252deeac532430f03013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80e0e8f011011600144ab5249140ca4630729030941f59f75e507bd4d500013e7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad1480d0dbc3f402011600145ade29df622cc68d0473aa1a20fb89690451c66e00013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80a2c0a012011600145ade29df622cc68d0473aa1a20fb89690451c66e00",
    88  		"07010001016c016acf24f1471d67c25a01ac84482ecdd8550229180171cae22321f87fe43d4f6a13ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80b4c4c32101012200200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac66ef02044059c7a12d006fd34bf8b9b2cb2f99756e5c3c3fdca4c928b830c014819e933b01c92a99bfeb6add73a5087870a3de3465cfed2c99f736b5f77d5fbdc69d91ff0040b95d110d118b873a8232104a6613f0e8c6a791efa3a695c02108cebd5239c8a8471551a48f18ab8ea05d10900b485af5e95b74cd3c01044c1742e71854099c0b40a1b63dae273e3b5b757b7c61286088a934e7282e837d08d62e60d7f75eb739529cd8c6cfef2254d47a546bf8b789657ce0944fec2f7e130c8498e28cae2a9108a901ae20d441b6f375659325a04eede4fc3b74579bb08ccd05b41b99776501e22d6dca7320af6d98ca2c3cd10bf0affbfa6e86609b750523cfadb662ec963c164f05798a49209820b9f1553b03aaebe7e3f9e9222ed7db73b5079b18564042fd3b2cef74156a20271b52de5f554aa4a6f1358f1c2193617bfb3fed4546d13c4af773096a429f9420eeb4a78d8b5cb8283c221ca2d3fd96b8946b3cddee02b7ceffb8f605932588595355ad020149ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80a0d9e61d012200206e8060ef3daca62841802dd9660b24b7dca81c1662b2d68ba8884ecbcd3e1e2200013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80d293ad0301160014ed7d3c466dbc6cc1f3a9af21267ac162f11b30a200",
    89  		"070100020161015f4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adea0dafd0f0e42f06f3bf9a8cf5787519d3860650f27a2b3393d34e1fe06e89b469ddc3f8c2f40200011600141da7f908979e521bf2ba12d280b2c84fc1d024416302409524d0d817176eeb718ce45671d95831cdb138d27289aa8a920104e38a8cab8a7dc8cc3fb60d65aa337b719aed0f696fb12610bfe68add89169a47ac1241e0002033444e1b57524161af3899e50fdfe270a90a1ea97fe38e86019a1e252667fb2d0161015fed3181c99ca80db720231aee6948e1183bfe29c64208c1769afa7f938d3b2cf0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff809cd2b0f4020101160014cfbccfac5018ad4b4bfbcb1fab834e3c8503746063024065beb1da2f0840188af0e3c0127b158f7a2a36f1612499694a731df1e3a9d1abe6694c42986b8700aa9856f59cb3692ee88d68b20d1278f05592fb253c58bd0520e5966eee4092eeefdd805b06f2ad368bb9392edec20998993ebe2a929052c1ce03013e0dafd0f0e42f06f3bf9a8cf5787519d3860650f27a2b3393d34e1fe06e89b469ddfbc8a2cf0201160014583c0323603dd397ba5414255adc80b076cf232b00013d0dafd0f0e42f06f3bf9a8cf5787519d3860650f27a2b3393d34e1fe06e89b46980c8afa02501160014fdb3e6abf7f430fdabb53484ca2469103b2af1b500013effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80dafa80f4020116001408e75789f47d2a39622e5a940fa918260bf44c5400",
    90  		"07010001016d016b1f134a47da4f6df00822935e02a07514718ea99ce5ac4e07bd6c204e098eb525ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808a858fa70200012200206205ec178dc1ac6ea05ea01bb0fcda6aa978173026fa75204a101bdad7bd6b4889010240d8d5bbf4969fba52df8fba06f75c5de0f51b2bd5f902bf234591f90e78bae20bfb5b7904cb83a1d6577c431f644d37722b432df9d64718b8300e3ab74a871a0046ae2068003e53d467b6d81beaf1e7bd9b60a5ffedc79b36ce14ecd1f30a2dcbcd0551200449030407a3a1fa0731f7f784a72c325b5ce4d534fc3cf8fb7140536ba928605152ad02014affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80f699b2a302012200209a0b4b27fde7d29d3b465d20eb2e19f4bda3a873d19d11f4cba53958bde92ed000013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80b3ffc40301160014ed7d3c466dbc6cc1f3a9af21267ac162f11b30a200",
    91  	}
    92  	wantMerkleRoot := "0f07b8a453771c2dc628f3895ebb33fea82a8de42e11aa588bec26419af22065"
    93  
    94  	var txs []*bc.Tx
    95  	for _, rawTx := range rawTxs {
    96  		tx := Tx{}		
    97  		if err := tx.UnmarshalText([]byte(rawTx)); err != nil {
    98  			t.Fatal(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{NewTxOutput(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{NewTxOutput(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{NewTxOutput(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  }