github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/protocol/bc/types/merkle_test.go (about)

     1  package types
     2  
     3  import (
     4  	"encoding/hex"
     5  	"strings"
     6  
     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  		strings.Join([]string{
    87  			"07",
    88  			"01",
    89  			"00",
    90  			"01",
    91  			"01",
    92  			"61",
    93  			"01",
    94  			"5f",
    95  			"5ac79a73db78e5c9215b37cb752f0147d1157c542bb4884908ceb97abc33fe0a",
    96  			"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
    97  			"a0f280d42b",
    98  			"00",
    99  			"01",
   100  			"16",
   101  			"0014085a02ecdf934a56343aa59a3dec9d9feb86ee43",
   102  			"00",
   103  			"63",
   104  			"02",
   105  			"40",
   106  			"035e1ef422b4901997ad3c20c50d82e726d03cb6e8ccb5dddc20e0c09e0a6f2e0055331e2b54d9ec52cffb1c47d8fdf2f8887d55c336753637cbf8f832c7af0b",
   107  			"20",
   108  			"a29601468f08c57ca9c383d28736a9d5c7737cd483126d8db3d85490fe497b35",
   109  			"02",
   110  			"01",
   111  			"00",
   112  			"3e",
   113  			"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   114  			"a0aad1b306",
   115  			"01",
   116  			"16",
   117  			"0014991b78d1bf731390e2dd838c05ff37ec5146886b",
   118  			"00",
   119  			"00",
   120  			"01",
   121  			"00",
   122  			"3e",
   123  			"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   124  			"8086d8f024",
   125  			"01",
   126  			"16",
   127  			"00145ade29df622cc68d0473aa1a20fb89690451c66e",
   128  			"00",
   129  			"00",
   130  		}, ""),
   131  		strings.Join([]string{
   132  			"07",
   133  			"01",
   134  			"00",
   135  			"02",
   136  			"01",
   137  			"61", // input + state length
   138  			"01",
   139  			"5f", // output + state length
   140  			"4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adea",
   141  			"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   142  			"80c480c124",
   143  			"02",
   144  			"01",
   145  			"16",
   146  			"0014cb9f2391bafe2bc1159b2c4c8a0f17ba1b4dd94e",
   147  			"00", // state data
   148  			"63",
   149  			"02",
   150  			"40",
   151  			"d96b8f31519c5e34ef983bb7dfb92e807df7fc1ae5a4c08846d00d4f84ebd2f8634b9e0b0374eb2508d0f989520f622aef051862c26daba0e466944e3d55d00b",
   152  			"20",
   153  			"1381d35e235813ad1e62f9a602c82abee90565639cc4573568206b55bcd2aed9",
   154  			"01",
   155  			"30",
   156  			"00",
   157  			"08",
   158  			"ede605460cacbf10",
   159  			"7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad14",
   160  			"80d0dbc3f402b001467b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d0125ae2054a71277cc162eb3eb21b5bd9fe54402829a53b294deaed91692a2cd8a081f9c5151ad01403a54a3ca0210d005cc9bce490478b518c405ba72e0bc1d134b739f29a73e008345229f0e061c420aa3c56a48bc1c9bf592914252ab9100e69252deeac532430f",
   161  			"03",
   162  			"0100",
   163  			"3e", // state length
   164  			"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   165  			"80e0e8f011",
   166  			"01",
   167  			"16",
   168  			"00144ab5249140ca4630729030941f59f75e507bd4d5",
   169  			"00", // state data
   170  			"00",
   171  			"0100",
   172  			"3f", // state length
   173  			"7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad14",
   174  			"80d0dbc3f402",
   175  			"01",
   176  			"16",
   177  			"00145ade29df622cc68d0473aa1a20fb89690451c66e",
   178  			"00", // state data
   179  			"00",
   180  			"0100",
   181  			"3e", // state length
   182  			"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   183  			"80a2c0a012",
   184  			"01",
   185  			"16",
   186  			"00145ade29df622cc68d0473aa1a20fb89690451c66e",
   187  			"00", // state data
   188  			"00",
   189  		}, ""),
   190  		strings.Join([]string{
   191  			"07",
   192  			"01",
   193  			"00",
   194  			"01",
   195  			"01",
   196  			"6d",
   197  			"01",
   198  			"6b",
   199  			"cf24f1471d67c25a01ac84482ecdd8550229180171cae22321f87fe43d4f6a13",
   200  			"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   201  			"80b4c4c321",
   202  			"01",
   203  			"01",
   204  			"22",
   205  			"00200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac66",
   206  			"00",
   207  			"ef02",
   208  			"04",
   209  			"40",
   210  			"59c7a12d006fd34bf8b9b2cb2f99756e5c3c3fdca4c928b830c014819e933b01c92a99bfeb6add73a5087870a3de3465cfed2c99f736b5f77d5fbdc69d91ff00",
   211  			"40",
   212  			"b95d110d118b873a8232104a6613f0e8c6a791efa3a695c02108cebd5239c8a8471551a48f18ab8ea05d10900b485af5e95b74cd3c01044c1742e71854099c0b",
   213  			"40",
   214  			"a1b6",
   215  			"3dae273e3b5b757b7c61286088a934e7282e837d08d62e60d7f75eb739529cd8c6cfef2254d47a546bf8b789657ce0944fec2f7e130c8498e28cae2a9108a901ae20d441b6f375659325a04eede4fc3b74579bb08ccd05b41b99776501e22d6dca7320af6d98ca2c3cd10bf0affbfa6e86609b750523cfadb662ec963c164f05798a49209820b9f1553b03aaebe7e3f9e9222ed7db73b5079b18564042fd3b2cef74156a20271b52de5f554aa4a6f1358f1c2193617bfb3fed4546d13c4af773096a429f9420eeb4a78d8b5cb8283c221ca2d3fd96b8946b3cddee02b7ceffb8f605932588595355ad",
   216  			"02",
   217  			"0100",
   218  			"4a",
   219  			"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   220  			"80a0d9e61d",
   221  			"01",
   222  			"22",
   223  			"00206e8060ef3daca62841802dd9660b24b7dca81c1662b2d68ba8884ecbcd3e1e22",
   224  			"00",
   225  			"00",
   226  			"0100",
   227  			"3e",
   228  			"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   229  			"80d293ad03",
   230  			"01",
   231  			"16",
   232  			"0014ed7d3c466dbc6cc1f3a9af21267ac162f11b30a2",
   233  			"00",
   234  			"00",
   235  		}, ""),
   236  		strings.Join([]string{
   237  			"07",
   238  			"01",
   239  			"00",
   240  			"02",
   241  			"01",
   242  			"62",
   243  			"01",
   244  			"60",
   245  			"4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adea",
   246  			"0dafd0f0e42f06f3bf9a8cf5787519d3860650f27a2b3393d34e1fe06e89b469",
   247  			"ddc3f8c2f402",
   248  			"00",
   249  			"01",
   250  			"16",
   251  			"00141da7f908979e521bf2ba12d280b2c84fc1d02441",
   252  			"00",
   253  			"63",
   254  			"02",
   255  			"40",
   256  			"9524d0d817176eeb718ce45671d95831cdb138d27289aa8a920104e38a8cab8a7dc8cc3fb60d65aa337b719aed0f696fb12610bfe68add89169a47ac1241e000",
   257  			"20",
   258  			"33444e1b57524161af3899e50fdfe270a90a1ea97fe38e86019a1e252667fb2d",
   259  			"01",
   260  			"62",
   261  			"01",
   262  			"60",
   263  			"ed3181c99ca80db720231aee6948e1183bfe29c64208c1769afa7f938d3b2cf0",
   264  			"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   265  			"809cd2b0f402",
   266  			"01",
   267  			"01",
   268  			"16",
   269  			"0014cfbccfac5018ad4b4bfbcb1fab834e3c85037460",
   270  			"00",
   271  			"63",
   272  			"02",
   273  			"40",
   274  			"65beb1da2f0840188af0e3c0127b158f7a2a36f1612499694a731df1e3a9d1abe6694c42986b8700aa9856f59cb3692ee88d68b20d1278f05592fb253c58bd05",
   275  			"20",
   276  			"e5966eee4092eeefdd805b06f2ad368bb9392edec20998993ebe2a929052c1ce",
   277  			"03",
   278  			"0100",
   279  			"3f",
   280  			"0dafd0f0e42f06f3bf9a8cf5787519d3860650f27a2b3393d34e1fe06e89b469",
   281  			"ddfbc8a2cf02",
   282  			"01",
   283  			"16",
   284  			"0014583c0323603dd397ba5414255adc80b076cf232b",
   285  			"00",
   286  			"00",
   287  			"0100",
   288  			"3e",
   289  			"0dafd0f0e42f06f3bf9a8cf5787519d3860650f27a2b3393d34e1fe06e89b469",
   290  			"80c8afa025",
   291  			"01",
   292  			"16",
   293  			"0014fdb3e6abf7f430fdabb53484ca2469103b2af1b5",
   294  			"00",
   295  			"00",
   296  			"0100",
   297  			"3f",
   298  			"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   299  			"80dafa80f402",
   300  			"01",
   301  			"16001408e75789f47d2a39622e5a940fa918260bf44c54",
   302  			"00",
   303  			"00",
   304  		}, ""),
   305  		strings.Join([]string{
   306  			"07",
   307  			"01",
   308  			"00",
   309  			"01",
   310  			"01",
   311  			"6e",
   312  			"01",
   313  			"6c",
   314  			"1f134a47da4f6df00822935e02a07514718ea99ce5ac4e07bd6c204e098eb525",
   315  			"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   316  			"808a858fa702",
   317  			"00",
   318  			"01",
   319  			"22",
   320  			"00206205ec178dc1ac6ea05ea01bb0fcda6aa978173026fa75204a101bdad7bd6b48",
   321  			"00",
   322  			"8901",
   323  			"02",
   324  			"40",
   325  			"d8d5bbf4969fba52df8fba06f75c5de0f51b2bd5f902bf234591f90e78bae20bfb5b7904cb83a1d6577c431f644d37722b432df9d64718b8300e3ab74a871a00",
   326  			"46ae",
   327  			"2068003e53d467b6d81beaf1e7bd9b60a5ffedc79b36ce14ecd1f30a2dcbcd0551200449030407a3a1fa0731f7f784a72c325b5ce4d534fc3cf8fb7140536ba928605152ad",
   328  			"02",
   329  			"0100",
   330  			"4b",
   331  			"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   332  			"80f699b2a302",
   333  			"01",
   334  			"22",
   335  			"00209a0b4b27fde7d29d3b465d20eb2e19f4bda3a873d19d11f4cba53958bde92ed0",
   336  			"00",
   337  			"00",
   338  			"0100",
   339  			"3e",
   340  			"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   341  			"80b3ffc403",
   342  			"01",
   343  			"16",
   344  			"0014ed7d3c466dbc6cc1f3a9af21267ac162f11b30a2",
   345  			"00",
   346  			"00",
   347  		}, ""),
   348  	}
   349  	wantMerkleRoot := "a23ae3e435a7bdfb52cb92b58be6e658982fd883283caf9547f9df50d65881df"
   350  
   351  	var txs []*bc.Tx
   352  	for _, rawTx := range rawTxs {
   353  		tx := Tx{}
   354  		if err := tx.UnmarshalText([]byte(rawTx)); err != nil {
   355  			t.Fatal(err)
   356  		}
   357  
   358  		txs = append(txs, tx.Tx)
   359  	}
   360  
   361  	gotMerkleRoot, err := TxMerkleRoot(txs)
   362  	if err != nil {
   363  		t.Fatal(err)
   364  	}
   365  
   366  	if wantMerkleRoot != gotMerkleRoot.String() {
   367  		t.Errorf("got merkle root:%s, want merkle root:%s", gotMerkleRoot.String(), wantMerkleRoot)
   368  	}
   369  }
   370  
   371  func TestDuplicateLeaves(t *testing.T) {
   372  	trueProg := []byte{byte(vm.OP_TRUE)}
   373  	assetID := bc.ComputeAssetID(trueProg, 1, &bc.EmptyStringHash)
   374  	txs := make([]*bc.Tx, 6)
   375  	for i := uint64(0); i < 6; i++ {
   376  		now := []byte(time.Now().String())
   377  		txs[i] = NewTx(TxData{
   378  			Version: 1,
   379  			Inputs:  []*TxInput{NewIssuanceInput(now, i, trueProg, nil, nil)},
   380  			Outputs: []*TxOutput{NewOriginalTxOutput(assetID, i, trueProg, nil)},
   381  		}).Tx
   382  	}
   383  
   384  	// first, get the root of an unbalanced tree
   385  	txns := []*bc.Tx{txs[5], txs[4], txs[3], txs[2], txs[1], txs[0]}
   386  	root1, err := TxMerkleRoot(txns)
   387  	if err != nil {
   388  		t.Fatalf("unexpected error %s", err)
   389  	}
   390  
   391  	// now, get the root of a balanced tree that repeats leaves 0 and 1
   392  	txns = []*bc.Tx{txs[5], txs[4], txs[3], txs[2], txs[1], txs[0], txs[1], txs[0]}
   393  	root2, err := TxMerkleRoot(txns)
   394  	if err != nil {
   395  		t.Fatalf("unexpected error %s", err)
   396  	}
   397  
   398  	if root1 == root2 {
   399  		t.Error("forged merkle tree by duplicating some leaves")
   400  	}
   401  }
   402  
   403  func TestAllDuplicateLeaves(t *testing.T) {
   404  	trueProg := []byte{byte(vm.OP_TRUE)}
   405  	assetID := bc.ComputeAssetID(trueProg, 1, &bc.EmptyStringHash)
   406  	now := []byte(time.Now().String())
   407  	issuanceInp := NewIssuanceInput(now, 1, trueProg, nil, nil)
   408  
   409  	tx := NewTx(TxData{
   410  		Version: 1,
   411  		Inputs:  []*TxInput{issuanceInp},
   412  		Outputs: []*TxOutput{NewOriginalTxOutput(assetID, 1, trueProg, nil)},
   413  	}).Tx
   414  	tx1, tx2, tx3, tx4, tx5, tx6 := tx, tx, tx, tx, tx, tx
   415  
   416  	// first, get the root of an unbalanced tree
   417  	txs := []*bc.Tx{tx6, tx5, tx4, tx3, tx2, tx1}
   418  	root1, err := TxMerkleRoot(txs)
   419  	if err != nil {
   420  		t.Fatalf("unexpected error %s", err)
   421  	}
   422  
   423  	// now, get the root of a balanced tree that repeats leaves 5 and 6
   424  	txs = []*bc.Tx{tx6, tx5, tx6, tx5, tx4, tx3, tx2, tx1}
   425  	root2, err := TxMerkleRoot(txs)
   426  	if err != nil {
   427  		t.Fatalf("unexpected error %s", err)
   428  	}
   429  
   430  	if root1 == root2 {
   431  		t.Error("forged merkle tree with all duplicate leaves")
   432  	}
   433  }
   434  
   435  func TestTxMerkleProof(t *testing.T) {
   436  	cases := []struct {
   437  		txCount          int
   438  		relatedTxIndexes []int
   439  		expectHashLen    int
   440  		expectFlags      []uint8
   441  	}{
   442  		{
   443  			txCount:          10,
   444  			relatedTxIndexes: []int{0, 3, 7, 8},
   445  			expectHashLen:    9,
   446  			expectFlags:      []uint8{1, 1, 1, 1, 2, 0, 1, 0, 2, 1, 0, 1, 0, 2, 1, 2, 0},
   447  		},
   448  		{
   449  			txCount:          10,
   450  			relatedTxIndexes: []int{},
   451  			expectHashLen:    1,
   452  			expectFlags:      []uint8{0},
   453  		},
   454  		{
   455  			txCount:          1,
   456  			relatedTxIndexes: []int{0},
   457  			expectHashLen:    1,
   458  			expectFlags:      []uint8{2},
   459  		},
   460  		{
   461  			txCount:          19,
   462  			relatedTxIndexes: []int{1, 3, 5, 7, 11, 15},
   463  			expectHashLen:    15,
   464  			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},
   465  		},
   466  	}
   467  	for _, c := range cases {
   468  		txs, bcTxs := mockTransactions(c.txCount)
   469  
   470  		var nodes []merkleNode
   471  		for _, tx := range txs {
   472  			nodes = append(nodes, tx.ID)
   473  		}
   474  		tree := buildMerkleTree(nodes)
   475  		root, err := TxMerkleRoot(bcTxs)
   476  		if err != nil {
   477  			t.Fatalf("unexpected error %s", err)
   478  		}
   479  		if tree.hash != root {
   480  			t.Error("build tree fail")
   481  		}
   482  
   483  		var relatedTx []*Tx
   484  		for _, index := range c.relatedTxIndexes {
   485  			relatedTx = append(relatedTx, txs[index])
   486  		}
   487  		proofHashes, flags := GetTxMerkleTreeProof(txs, relatedTx)
   488  		if !testutil.DeepEqual(flags, c.expectFlags) {
   489  			t.Error("The flags is not equals expect flags", flags, c.expectFlags)
   490  		}
   491  		if len(proofHashes) != c.expectHashLen {
   492  			t.Error("The length proof hashes is not equals expect length")
   493  		}
   494  		var ids []*bc.Hash
   495  		for _, tx := range relatedTx {
   496  			ids = append(ids, &tx.ID)
   497  		}
   498  		if !ValidateTxMerkleTreeProof(proofHashes, flags, ids, root) {
   499  			t.Error("Merkle tree validate fail")
   500  		}
   501  	}
   502  }
   503  
   504  func TestUglyValidateTxMerkleProof(t *testing.T) {
   505  	cases := []struct {
   506  		hashes        []string
   507  		flags         []uint8
   508  		relatedHashes []string
   509  		root          string
   510  		expectResult  bool
   511  	}{
   512  		{
   513  			hashes:        []string{},
   514  			flags:         []uint8{},
   515  			relatedHashes: []string{},
   516  			root:          "",
   517  			expectResult:  false,
   518  		},
   519  		{
   520  			hashes:        []string{},
   521  			flags:         []uint8{1, 1, 1, 1, 2, 0, 1, 0, 2, 1, 0, 1, 0, 2, 1, 2, 0},
   522  			relatedHashes: []string{},
   523  			root:          "",
   524  			expectResult:  false,
   525  		},
   526  		{
   527  			hashes: []string{
   528  				"0093370a8e19f8f131fd7e75c576615950d5672ee5e18c63f105a95bcab4332c",
   529  				"c9b7779847fb7ab74cf4b1e7f4557133918faa2bc130042753417dfb62b12dfa",
   530  			},
   531  			flags:         []uint8{},
   532  			relatedHashes: []string{},
   533  			root:          "",
   534  			expectResult:  false,
   535  		},
   536  		{
   537  			hashes: []string{},
   538  			flags:  []uint8{},
   539  			relatedHashes: []string{
   540  				"0093370a8e19f8f131fd7e75c576615950d5672ee5e18c63f105a95bcab4332c",
   541  				"c9b7779847fb7ab74cf4b1e7f4557133918faa2bc130042753417dfb62b12dfa",
   542  			},
   543  			root:         "",
   544  			expectResult: false,
   545  		},
   546  		{
   547  			hashes: []string{},
   548  			flags:  []uint8{1, 1, 0, 2, 1, 2, 1, 0, 1},
   549  			relatedHashes: []string{
   550  				"0093370a8e19f8f131fd7e75c576615950d5672ee5e18c63f105a95bcab4332c",
   551  				"c9b7779847fb7ab74cf4b1e7f4557133918faa2bc130042753417dfb62b12dfa",
   552  			},
   553  			root: "281138e0a9ea19505844bd61a2f5843787035782c093da74d12b5fba73eeeb07",
   554  		},
   555  		{
   556  			hashes: []string{
   557  				"68f03ea2b02a21ad944d1a43ad6152a7fa6a7ed4101d59be62594dd30ef2a558",
   558  			},
   559  			flags: []uint8{},
   560  			relatedHashes: []string{
   561  				"0093370a8e19f8f131fd7e75c576615950d5672ee5e18c63f105a95bcab4332c",
   562  				"c9b7779847fb7ab74cf4b1e7f4557133918faa2bc130042753417dfb62b12dfa",
   563  			},
   564  			root:         "281138e0a9ea19505844bd61a2f5843787035782c093da74d12b5fba73eeeb07",
   565  			expectResult: false,
   566  		},
   567  		{
   568  			hashes: []string{
   569  				"8ec3ee7589f95eee9b534f71fcd37142bcc839a0dbfe78124df9663827b90c35",
   570  				"011bd3380852b2946df507e0c6234222c559eec8f545e4bc58a89e960892259b",
   571  				"c205988d9c864083421f1bdb95e6cf8b52070facfcc87e46a6e8197f5389fca2",
   572  			},
   573  			flags: []uint8{1, 1, 0, 2, 0},
   574  			relatedHashes: []string{
   575  				"504af455e328e7dd39bbc059529851946d54ee8b459b11b3aac4a0feeb474487",
   576  			},
   577  			root:         "aff81a46fe79204ef9007243f374d54104a59762b9f74d80d56b5291753db6fb",
   578  			expectResult: true,
   579  		},
   580  		// flags and hashes is correct, but relatedHashes has hash that does not exist
   581  		{
   582  			hashes: []string{
   583  				"8ec3ee7589f95eee9b534f71fcd37142bcc839a0dbfe78124df9663827b90c35",
   584  				"011bd3380852b2946df507e0c6234222c559eec8f545e4bc58a89e960892259b",
   585  				"c205988d9c864083421f1bdb95e6cf8b52070facfcc87e46a6e8197f5389fca2",
   586  			},
   587  			flags: []uint8{1, 1, 0, 2, 0},
   588  			relatedHashes: []string{
   589  				"504af455e328e7dd39bbc059529851946d54ee8b459b11b3aac4a0feeb474487",
   590  				"281138e0a9ea19505844bd61a2f5843787035782c093da74d12b5fba73eeeb07",
   591  			},
   592  			root:         "aff81a46fe79204ef9007243f374d54104a59762b9f74d80d56b5291753db6fb",
   593  			expectResult: false,
   594  		},
   595  		// flags and hashes is correct, but relatedHashes is not enough
   596  		{
   597  			hashes: []string{
   598  				"8ec3ee7589f95eee9b534f71fcd37142bcc839a0dbfe78124df9663827b90c35",
   599  				"011bd3380852b2946df507e0c6234222c559eec8f545e4bc58a89e960892259b",
   600  				"c205988d9c864083421f1bdb95e6cf8b52070facfcc87e46a6e8197f5389fca2",
   601  			},
   602  			flags:         []uint8{1, 1, 0, 2, 0},
   603  			relatedHashes: []string{},
   604  			root:          "aff81a46fe79204ef9007243f374d54104a59762b9f74d80d56b5291753db6fb",
   605  			expectResult:  false,
   606  		},
   607  		// flags is correct, but hashes has additional hash at the end
   608  		{
   609  			hashes: []string{
   610  				"8ec3ee7589f95eee9b534f71fcd37142bcc839a0dbfe78124df9663827b90c35",
   611  				"011bd3380852b2946df507e0c6234222c559eec8f545e4bc58a89e960892259b",
   612  				"c205988d9c864083421f1bdb95e6cf8b52070facfcc87e46a6e8197f5389fca2",
   613  				"5a06c90136e81c0f9cad29725e69edc6d21bd6fb0641265f9c4b6bb6840b37dd",
   614  			},
   615  			flags: []uint8{1, 1, 0, 2, 0},
   616  			relatedHashes: []string{
   617  				"504af455e328e7dd39bbc059529851946d54ee8b459b11b3aac4a0feeb474487",
   618  			},
   619  			root:         "aff81a46fe79204ef9007243f374d54104a59762b9f74d80d56b5291753db6fb",
   620  			expectResult: true,
   621  		},
   622  	}
   623  
   624  	for _, c := range cases {
   625  		var hashes, relatedHashes []*bc.Hash
   626  		var hashBytes, rootBytes [32]byte
   627  		var err error
   628  		for _, hashStr := range c.hashes {
   629  			if hashBytes, err = convertHashStr2Bytes(hashStr); err != nil {
   630  				t.Fatal(err)
   631  			}
   632  
   633  			hash := bc.NewHash(hashBytes)
   634  			hashes = append(hashes, &hash)
   635  		}
   636  		for _, hashStr := range c.relatedHashes {
   637  			if hashBytes, err = convertHashStr2Bytes(hashStr); err != nil {
   638  				t.Fatal(err)
   639  			}
   640  
   641  			hash := bc.NewHash(hashBytes)
   642  			relatedHashes = append(relatedHashes, &hash)
   643  		}
   644  		if rootBytes, err = convertHashStr2Bytes(c.root); err != nil {
   645  			t.Fatal(err)
   646  		}
   647  
   648  		root := bc.NewHash(rootBytes)
   649  		if ValidateTxMerkleTreeProof(hashes, c.flags, relatedHashes, root) != c.expectResult {
   650  			t.Error("Validate merkle tree proof fail")
   651  		}
   652  	}
   653  }
   654  
   655  func convertHashStr2Bytes(hashStr string) ([32]byte, error) {
   656  	var result [32]byte
   657  	hashBytes, err := hex.DecodeString(hashStr)
   658  	if err != nil {
   659  		return result, err
   660  	}
   661  	copy(result[:], hashBytes)
   662  	return result, nil
   663  }
   664  
   665  func mockTransactions(txCount int) ([]*Tx, []*bc.Tx) {
   666  	var txs []*Tx
   667  	var bcTxs []*bc.Tx
   668  	trueProg := []byte{byte(vm.OP_TRUE)}
   669  	assetID := bc.ComputeAssetID(trueProg, 1, &bc.EmptyStringHash)
   670  	for i := 0; i < txCount; i++ {
   671  		now := []byte(time.Now().String())
   672  		issuanceInp := NewIssuanceInput(now, 1, trueProg, nil, nil)
   673  		tx := NewTx(TxData{
   674  			Version: 1,
   675  			Inputs:  []*TxInput{issuanceInp},
   676  			Outputs: []*TxOutput{NewOriginalTxOutput(assetID, 1, trueProg, nil)},
   677  		})
   678  		txs = append(txs, tx)
   679  		bcTxs = append(bcTxs, tx.Tx)
   680  	}
   681  	return txs, bcTxs
   682  }